mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
Compare commits
1446 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1462636e97 | ||
|
|
7e59a7f4af | ||
|
|
e9a21848bc | ||
|
|
1dcb251ecb | ||
|
|
3f33543cee | ||
|
|
84bd2088f2 | ||
|
|
4f4a3132c5 | ||
|
|
e064c934cb | ||
|
|
16fc3cabf2 | ||
|
|
7e002ff6c2 | ||
|
|
323c0c62c3 | ||
|
|
ff5bd301cc | ||
|
|
c37712b0f0 | ||
|
|
ee9e238592 | ||
|
|
da5d6fa157 | ||
|
|
d471f08b15 | ||
|
|
b97424f767 | ||
|
|
c29a276188 | ||
|
|
d1694aa8bd | ||
|
|
570cf6fc51 | ||
|
|
8eab86e489 | ||
|
|
566568f61a | ||
|
|
56a73a4d17 | ||
|
|
656d25b75e | ||
|
|
dcdc80ade3 | ||
|
|
09f2d65d5e | ||
|
|
b304d46f7e | ||
|
|
3391f971ec | ||
|
|
778fed27a5 | ||
|
|
1755dbc877 | ||
|
|
4e6f538519 | ||
|
|
a6ecb0ef85 | ||
|
|
438ec6ac5c | ||
|
|
8089e66642 | ||
|
|
d27e0561f2 | ||
|
|
97b21bfa8b | ||
|
|
ec4343ed30 | ||
|
|
948decb3b5 | ||
|
|
d510fee7f6 | ||
|
|
70b7a3d662 | ||
|
|
b142a6f31e | ||
|
|
14705a9b30 | ||
|
|
32b0f1ba10 | ||
|
|
cbffdf4900 | ||
|
|
1238da5e54 | ||
|
|
cba203be09 | ||
|
|
d89c6156b9 | ||
|
|
e06475b3b7 | ||
|
|
5ff99bd45e | ||
|
|
127dd6ac41 | ||
|
|
9e05384513 | ||
|
|
9ffda72ae3 | ||
|
|
72a4c00e72 | ||
|
|
c95e95ef67 | ||
|
|
0c0d4bffbf | ||
|
|
2a494b1d60 | ||
|
|
1463723e52 | ||
|
|
9ade48d078 | ||
|
|
7ba8274fd4 | ||
|
|
238443074c | ||
|
|
0decbec595 | ||
|
|
0eb77c7f72 | ||
|
|
f05df0db0a | ||
|
|
13fbaf1f74 | ||
|
|
969d2642de | ||
|
|
17ce6d39b4 | ||
|
|
261d2b1fe8 | ||
|
|
a54aeb3838 | ||
|
|
cc4f9a9db5 | ||
|
|
a311bac89b | ||
|
|
029f273dd9 | ||
|
|
bbbdd7e4d3 | ||
|
|
3f3ef6b24f | ||
|
|
8c3dfd4a36 | ||
|
|
af57599df9 | ||
|
|
bde25f6ac8 | ||
|
|
c989b97ffa | ||
|
|
5f5c225300 | ||
|
|
36e4071b7f | ||
|
|
1068884bce | ||
|
|
32d102dbc9 | ||
|
|
4e1f092b98 | ||
|
|
bd60a18ff4 | ||
|
|
3b3d7d76eb | ||
|
|
ec76448e9f | ||
|
|
872c84974c | ||
|
|
5dd2008969 | ||
|
|
55ddac2bc7 | ||
|
|
a62dd22f83 | ||
|
|
a503879858 | ||
|
|
14f19dd735 | ||
|
|
9a727f68ce | ||
|
|
d26819d268 | ||
|
|
44752cc9aa | ||
|
|
11e0757387 | ||
|
|
1f1ebc3c44 | ||
|
|
4be97b6ea6 | ||
|
|
3facca5499 | ||
|
|
bfbd25012a | ||
|
|
063fff2ab4 | ||
|
|
fbdc8d5b99 | ||
|
|
625c0a3321 | ||
|
|
2972300112 | ||
|
|
a8e71895ee | ||
|
|
d7a76081e3 | ||
|
|
fd925a6718 | ||
|
|
4fc890a77c | ||
|
|
b804463b73 | ||
|
|
8f161b4b5a | ||
|
|
c6338169f3 | ||
|
|
6cea24ed9e | ||
|
|
3d8eb9eb66 | ||
|
|
a84aceb1ba | ||
|
|
8adb7e3021 | ||
|
|
bc0d5dc9b5 | ||
|
|
1d935d6659 | ||
|
|
445466acd0 | ||
|
|
30af74f806 | ||
|
|
16ddd100d3 | ||
|
|
c946ec170d | ||
|
|
ca514dd76e | ||
|
|
cf44a5c50b | ||
|
|
91b8c02c7f | ||
|
|
ca3b2b4b07 | ||
|
|
722dde63df | ||
|
|
c85baf4dc6 | ||
|
|
96b7770ab2 | ||
|
|
0c00117820 | ||
|
|
3465fa68b4 | ||
|
|
28278a75a7 | ||
|
|
f68a871dd6 | ||
|
|
93d424cfe1 | ||
|
|
a1adde0888 | ||
|
|
13528b49cb | ||
|
|
f3be3f2d1c | ||
|
|
241fe855cc | ||
|
|
ea2447dcb7 | ||
|
|
f40baed65e | ||
|
|
eed11d211b | ||
|
|
19f27a8d56 | ||
|
|
cf3fa17666 | ||
|
|
6fdc56f2d3 | ||
|
|
9f17a5b26d | ||
|
|
fa53e90847 | ||
|
|
50c630f403 | ||
|
|
5630c161ea | ||
|
|
7d16ff9e79 | ||
|
|
a9ea9daec3 | ||
|
|
45bdd40dce | ||
|
|
a2bca88eec | ||
|
|
c0dd02ee13 | ||
|
|
97495a6093 | ||
|
|
4ad45088c4 | ||
|
|
d6d1d4b1b7 | ||
|
|
6e453c170f | ||
|
|
beb2deee52 | ||
|
|
9c69043b2c | ||
|
|
4df34b3f9d | ||
|
|
ee01756188 | ||
|
|
0386aaa18b | ||
|
|
92c4230cde | ||
|
|
26165999e0 | ||
|
|
38b2641078 | ||
|
|
4e19169312 | ||
|
|
46de81c1c9 | ||
|
|
9bf4da7acf | ||
|
|
6f32236fb7 | ||
|
|
c25d857e78 | ||
|
|
8cc2925fd0 | ||
|
|
2b87d3c4db | ||
|
|
7f6f366744 | ||
|
|
b1fdbde5cd | ||
|
|
417f0f5f1c | ||
|
|
ec7673790c | ||
|
|
7d0bdf3b9e | ||
|
|
2ef5270095 | ||
|
|
61ba011c3b | ||
|
|
8d8b9f3e98 | ||
|
|
69899ec29f | ||
|
|
5063621c95 | ||
|
|
030177f739 | ||
|
|
808f5a6381 | ||
|
|
9602b191a9 | ||
|
|
34bd2d781c | ||
|
|
cf364c1264 | ||
|
|
a997820bb6 | ||
|
|
b8fabd59c0 | ||
|
|
97d290795e | ||
|
|
2a237ff5fc | ||
|
|
13a418f74e | ||
|
|
5c56dbfed6 | ||
|
|
0d2f37e1da | ||
|
|
0494c2161c | ||
|
|
635a620439 | ||
|
|
0a7c76ec72 | ||
|
|
9ad8fb38e8 | ||
|
|
1dbe968952 | ||
|
|
460b6492cb | ||
|
|
67b0faa9ae | ||
|
|
5553425a1a | ||
|
|
8ff516e43a | ||
|
|
b6207bafde | ||
|
|
b9f43fd560 | ||
|
|
c617d9f569 | ||
|
|
9efb9761c6 | ||
|
|
03f9115fbf | ||
|
|
a2859cedb5 | ||
|
|
0c604b1023 | ||
|
|
cdee0594f8 | ||
|
|
808833d749 | ||
|
|
581c64b601 | ||
|
|
40418607e5 | ||
|
|
5436ea88d8 | ||
|
|
7bec5ec6dc | ||
|
|
c953ff84d0 | ||
|
|
96cd207df3 | ||
|
|
7a75f62a6a | ||
|
|
61e5fe58c2 | ||
|
|
1a3baba702 | ||
|
|
58dc14bb46 | ||
|
|
a5b7e04943 | ||
|
|
22f2aa5475 | ||
|
|
d4e9cb12be | ||
|
|
75da361480 | ||
|
|
7488bcb7b0 | ||
|
|
1b1a9be107 | ||
|
|
db2f94aa53 | ||
|
|
810146b993 | ||
|
|
93091662ab | ||
|
|
d349227fbf | ||
|
|
c9423e3aa8 | ||
|
|
b9737ca4f1 | ||
|
|
4b4990635d | ||
|
|
afaa2c8c78 | ||
|
|
f506ef0d4f | ||
|
|
d30fe66cac | ||
|
|
270e998e86 | ||
|
|
c395386c05 | ||
|
|
4f1207b0db | ||
|
|
dc3878e290 | ||
|
|
be2876149d | ||
|
|
52bae9dfb0 | ||
|
|
bb636bac3f | ||
|
|
502b18fa86 | ||
|
|
e0a5450264 | ||
|
|
5ffb23c37f | ||
|
|
b75f22b7bd | ||
|
|
35fa3197c8 | ||
|
|
f03725ae36 | ||
|
|
2b640e2129 | ||
|
|
2a983f5c03 | ||
|
|
cacc5daa14 | ||
|
|
593502287d | ||
|
|
7a9bdf9be0 | ||
|
|
170c22c5ed | ||
|
|
7e8fa58bd7 | ||
|
|
046200625c | ||
|
|
710ed55152 | ||
|
|
ce527329a6 | ||
|
|
b455dd41ab | ||
|
|
b47ed94f40 | ||
|
|
f1351a2093 | ||
|
|
c1c5e81df0 | ||
|
|
8e3c8ba6c5 | ||
|
|
dfe4404a17 | ||
|
|
b3fb63c9f5 | ||
|
|
9db3dfff26 | ||
|
|
3c9051e7de | ||
|
|
798a6d061c | ||
|
|
19afbe99d9 | ||
|
|
4715d8d16c | ||
|
|
193da2bc4d | ||
|
|
799f8efe22 | ||
|
|
f6062e1ec4 | ||
|
|
c790778a46 | ||
|
|
4344f1b3a0 | ||
|
|
d520b30500 | ||
|
|
11c02e5f50 | ||
|
|
aa4c6ee9da | ||
|
|
98f8557392 | ||
|
|
6f6a860887 | ||
|
|
38695e9e16 | ||
|
|
242c478cb3 | ||
|
|
f003e835bd | ||
|
|
267defb321 | ||
|
|
4392c7627b | ||
|
|
fde65b2730 | ||
|
|
e908362f0a | ||
|
|
a40b837634 | ||
|
|
b391465fbf | ||
|
|
bad0428f5b | ||
|
|
97018df2f9 | ||
|
|
9d84501bc8 | ||
|
|
e9fb2b3fdc | ||
|
|
f60250fd8a | ||
|
|
5fc3cae28a | ||
|
|
e7935be85b | ||
|
|
89363b2ea1 | ||
|
|
e84390ee46 | ||
|
|
65a0f467ae | ||
|
|
4afb150106 | ||
|
|
0f6702217e | ||
|
|
13a0097858 | ||
|
|
01c830ad92 | ||
|
|
dce4f4623c | ||
|
|
d530624362 | ||
|
|
2e878b62d1 | ||
|
|
d27a246dfe | ||
|
|
778def118a | ||
|
|
bc5587477b | ||
|
|
03a775cd31 | ||
|
|
875083a924 | ||
|
|
f6fc925c9e | ||
|
|
74e1972781 | ||
|
|
2f5c54bb49 | ||
|
|
465798ee3d | ||
|
|
425f3acced | ||
|
|
546382e471 | ||
|
|
7e91d78633 | ||
|
|
136e1e4e30 | ||
|
|
f5f6850172 | ||
|
|
28cdde3f17 | ||
|
|
29b801e13d | ||
|
|
1435469ee5 | ||
|
|
4a0bd2c09f | ||
|
|
f8d67f863f | ||
|
|
0291dd5416 | ||
|
|
9014435d4d | ||
|
|
07ad467c73 | ||
|
|
35e23574cf | ||
|
|
9b62b8395f | ||
|
|
45e7022deb | ||
|
|
32dce16363 | ||
|
|
e34b5eafe1 | ||
|
|
4e1e749094 | ||
|
|
ede9293377 | ||
|
|
9101324a1f | ||
|
|
4b844353ee | ||
|
|
2134c19c58 | ||
|
|
c974784ebb | ||
|
|
5eb6961023 | ||
|
|
07cbd8b97b | ||
|
|
09c7f15364 | ||
|
|
b879b393ad | ||
|
|
e4503c2a54 | ||
|
|
7e2d02b997 | ||
|
|
d286550572 | ||
|
|
4e44e25d30 | ||
|
|
9fef2f9d05 | ||
|
|
04f1f5921d | ||
|
|
f9ecffb850 | ||
|
|
c9b5274ccf | ||
|
|
d209d47b9e | ||
|
|
21baaf810c | ||
|
|
95b4366270 | ||
|
|
c3adadfe2f | ||
|
|
adf7753617 | ||
|
|
d491847754 | ||
|
|
6afc747790 | ||
|
|
ff46935448 | ||
|
|
78c2f98f1f | ||
|
|
91be9aa2fe | ||
|
|
13e5da584f | ||
|
|
1762e0b7a6 | ||
|
|
05240abfe0 | ||
|
|
b515e8be04 | ||
|
|
24bc7fb0b5 | ||
|
|
0d2e1e6d18 | ||
|
|
f23c523baf | ||
|
|
76fee29f5b | ||
|
|
ec77746a43 | ||
|
|
92cd6f8f34 | ||
|
|
e7d2b5cbb6 | ||
|
|
4d175da3a0 | ||
|
|
5f047ddda9 | ||
|
|
ccca6fe88e | ||
|
|
a1f18e1ec9 | ||
|
|
afdaf7a0a5 | ||
|
|
62f0ef19f4 | ||
|
|
b736502c27 | ||
|
|
2be2dae3d6 | ||
|
|
aefe104ca4 | ||
|
|
3e6bce9cec | ||
|
|
a6394cac38 | ||
|
|
1e09ddfc93 | ||
|
|
664f5c98e9 | ||
|
|
c7bfd2ea82 | ||
|
|
9ce7ddd088 | ||
|
|
cca8d427d2 | ||
|
|
aa9263a2e7 | ||
|
|
5eaebde437 | ||
|
|
7f15f557a5 | ||
|
|
b459715cb5 | ||
|
|
bfede219d0 | ||
|
|
ef21efecf5 | ||
|
|
2bfbc9dc12 | ||
|
|
c3a1b45546 | ||
|
|
b72508f920 | ||
|
|
22bb80218d | ||
|
|
873a7e8572 | ||
|
|
0c5016fe89 | ||
|
|
607b084697 | ||
|
|
9d8ffec276 | ||
|
|
15f08e9b7c | ||
|
|
08aa6b1894 | ||
|
|
06b02c4f7c | ||
|
|
b56acd271f | ||
|
|
b24e2db59e | ||
|
|
f215356629 | ||
|
|
069a7c809c | ||
|
|
883b4d735a | ||
|
|
9f39b269bb | ||
|
|
36c405c708 | ||
|
|
bc7c68ebe4 | ||
|
|
6c502ad4c5 | ||
|
|
100aa0b621 | ||
|
|
8e42b19934 | ||
|
|
1a456d5d68 | ||
|
|
e83c26a76a | ||
|
|
6e7c2a616b | ||
|
|
0699454df8 | ||
|
|
92c110548a | ||
|
|
ca88023560 | ||
|
|
12fc2299ec | ||
|
|
2089c77b84 | ||
|
|
4f5a3e8d8b | ||
|
|
95522846ac | ||
|
|
614ac956de | ||
|
|
c228362c01 | ||
|
|
f6c5db07f2 | ||
|
|
78e7839213 | ||
|
|
f7be12df67 | ||
|
|
a1d1e221ae | ||
|
|
0a4dc54fb9 | ||
|
|
b8c7801365 | ||
|
|
a7099c039f | ||
|
|
a4d2d347e3 | ||
|
|
829c537fd3 | ||
|
|
28437f99cf | ||
|
|
c1402d85e1 | ||
|
|
32e071ab89 | ||
|
|
01125e030e | ||
|
|
b43278439a | ||
|
|
7a445aabd7 | ||
|
|
86a4f306c6 | ||
|
|
0e523f1193 | ||
|
|
9041a16b22 | ||
|
|
596ff3382d | ||
|
|
cbd80252ed | ||
|
|
bcd7a7e3dd | ||
|
|
9c98f1a553 | ||
|
|
c3d214aa23 | ||
|
|
d301f6e104 | ||
|
|
eb9fa585f7 | ||
|
|
16c6ffb032 | ||
|
|
7858e42e37 | ||
|
|
30132aa6b0 | ||
|
|
bf4d4cc2c5 | ||
|
|
9f0554c883 | ||
|
|
218ea6ce47 | ||
|
|
0baae7da8b | ||
|
|
fb4576fc1b | ||
|
|
16f3f9e6ff | ||
|
|
fee7cf6265 | ||
|
|
2dd75c4a64 | ||
|
|
d2f46cd0b5 | ||
|
|
10914083e6 | ||
|
|
5d167da55e | ||
|
|
b381e20e57 | ||
|
|
380dae1017 | ||
|
|
fb15cdc546 | ||
|
|
a525fe29db | ||
|
|
475cc9a9a5 | ||
|
|
264d6fbd6d | ||
|
|
2826cf379b | ||
|
|
d28745df29 | ||
|
|
94f9e4a1be | ||
|
|
ec547e1d65 | ||
|
|
61d4eb649b | ||
|
|
52ad15e375 | ||
|
|
ff00a6c0f0 | ||
|
|
9b1ebd658d | ||
|
|
f842530537 | ||
|
|
63077bbb19 | ||
|
|
4dad337377 | ||
|
|
10a965d765 | ||
|
|
3e9c9c9066 | ||
|
|
8b5a738e65 | ||
|
|
2c041dce3a | ||
|
|
ef151c68f4 | ||
|
|
52feaac92a | ||
|
|
cddbb3d7d4 | ||
|
|
42764550e6 | ||
|
|
6ee737b314 | ||
|
|
f460ef7685 | ||
|
|
9977bcb468 | ||
|
|
7437d984c7 | ||
|
|
5cd0b2403c | ||
|
|
a372da22f3 | ||
|
|
8b10d3ba5a | ||
|
|
a8b15c6a12 | ||
|
|
23bac7e5fd | ||
|
|
b82ee2ef61 | ||
|
|
b7761f4b71 | ||
|
|
f9a4f9771c | ||
|
|
d2acb2c98a | ||
|
|
bf0685cee2 | ||
|
|
d60bd5df14 | ||
|
|
73b6ca3762 | ||
|
|
8262793751 | ||
|
|
5ec7848fb0 | ||
|
|
450fc123ff | ||
|
|
3802c64be3 | ||
|
|
7bf1b26812 | ||
|
|
6c18431a30 | ||
|
|
a49d20249f | ||
|
|
ad384acd57 | ||
|
|
69851b7f3a | ||
|
|
92b53bf0df | ||
|
|
93e0496fd2 | ||
|
|
5151951f46 | ||
|
|
58dbccec2d | ||
|
|
90de14d013 | ||
|
|
f1792e46c6 | ||
|
|
84e9c36280 | ||
|
|
2ef6a2c3c9 | ||
|
|
5f961618bf | ||
|
|
37c375e2fa | ||
|
|
1758c175ed | ||
|
|
96f2a02cfa | ||
|
|
96d4bda6c8 | ||
|
|
02cf6050a1 | ||
|
|
38cf32a2e9 | ||
|
|
2ae7589d14 | ||
|
|
bcb2e1f0a1 | ||
|
|
14932d3f07 | ||
|
|
c3b9dc397d | ||
|
|
58b653f55d | ||
|
|
1dcdc42dde | ||
|
|
58a0a16985 | ||
|
|
a117243f14 | ||
|
|
22411060be | ||
|
|
045263ae58 | ||
|
|
024b6daaf6 | ||
|
|
bd5512c121 | ||
|
|
9afce83a02 | ||
|
|
07a8bd9486 | ||
|
|
bcdc0a8fce | ||
|
|
b295809432 | ||
|
|
52763ab932 | ||
|
|
99666265c9 | ||
|
|
af3e280d74 | ||
|
|
b57e4c0565 | ||
|
|
aca9931560 | ||
|
|
d09e166e4a | ||
|
|
68a7a60ff2 | ||
|
|
f21261914b | ||
|
|
7b11339fdc | ||
|
|
081fd43d98 | ||
|
|
ef2eedfc7c | ||
|
|
0dba9265be | ||
|
|
301aae9b8e | ||
|
|
c63f4e9662 | ||
|
|
47508dc6ac | ||
|
|
3a8879608a | ||
|
|
b221889549 | ||
|
|
c00d99b85f | ||
|
|
0bf87b753d | ||
|
|
53f2730064 | ||
|
|
d487c3b005 | ||
|
|
fef6ae7ff7 | ||
|
|
f6b42754de | ||
|
|
2ae9bb381d | ||
|
|
53bde84710 | ||
|
|
d006ac27ff | ||
|
|
c478d28b71 | ||
|
|
99f7b9ad84 | ||
|
|
ab58101ce3 | ||
|
|
d8f3682dc0 | ||
|
|
1fec7ba553 | ||
|
|
418f55f34e | ||
|
|
05d795b2ae | ||
|
|
a365b750d9 | ||
|
|
0aecfb565f | ||
|
|
0cf4edd9e5 | ||
|
|
dd7b7c6aef | ||
|
|
0bd677c46b | ||
|
|
1a131d5206 | ||
|
|
016e515ae2 | ||
|
|
456ceb3c58 | ||
|
|
2169be1b45 | ||
|
|
49eb0b0201 | ||
|
|
2e222bcdea | ||
|
|
c7fa475128 | ||
|
|
4174b065f3 | ||
|
|
df6256d989 | ||
|
|
c27db56321 | ||
|
|
97bed8554a | ||
|
|
751c0e16e9 | ||
|
|
936de60700 | ||
|
|
f6b64d48ec | ||
|
|
b043da7d4c | ||
|
|
7e47cc2443 | ||
|
|
b8b45f9442 | ||
|
|
66337f9af6 | ||
|
|
54646706a0 | ||
|
|
e8ee037d09 | ||
|
|
6d705e568a | ||
|
|
e768791eba | ||
|
|
2aff7c97f9 | ||
|
|
ca6fc7773e | ||
|
|
a1395a5490 | ||
|
|
61dd4d71d6 | ||
|
|
6beda53238 | ||
|
|
941441d7e1 | ||
|
|
d10ea41b47 | ||
|
|
9458870f70 | ||
|
|
095794bbd1 | ||
|
|
c7fc0aa936 | ||
|
|
a8d98ced61 | ||
|
|
831b3d851a | ||
|
|
8c891c7016 | ||
|
|
5c4706cbc9 | ||
|
|
db66a6c4f0 | ||
|
|
0517e4fc02 | ||
|
|
dd7fa4a87d | ||
|
|
e5956900ea | ||
|
|
3755593c14 | ||
|
|
8ddd3b6d68 | ||
|
|
840083940d | ||
|
|
0cdfd29ecf | ||
|
|
bb32c727b6 | ||
|
|
f978c04750 | ||
|
|
b6a504e121 | ||
|
|
5fae367fab | ||
|
|
6e807f44b2 | ||
|
|
53ebed7f89 | ||
|
|
1c10c41808 | ||
|
|
01170b669b | ||
|
|
b56215e5e3 | ||
|
|
221e801561 | ||
|
|
90edbe23d7 | ||
|
|
5b16a814c8 | ||
|
|
ef01721464 | ||
|
|
efd8cf8236 | ||
|
|
8dbfc6d5d6 | ||
|
|
ef343397d4 | ||
|
|
cae02d31db | ||
|
|
96c78cbc16 | ||
|
|
f8c769644d | ||
|
|
0bd1e413b0 | ||
|
|
07c9ad484a | ||
|
|
5fd5b1206e | ||
|
|
8e107647bd | ||
|
|
12b7389376 | ||
|
|
45332c8126 | ||
|
|
02a9d4e31d | ||
|
|
a4377e81cb | ||
|
|
8d2ed3faf6 | ||
|
|
e7dacb8fef | ||
|
|
60e2ffac5f | ||
|
|
73c37b2018 | ||
|
|
1b3cc223da | ||
|
|
51be7ad832 | ||
|
|
f93d035e4e | ||
|
|
a3885d7a48 | ||
|
|
bbf2331766 | ||
|
|
2164bd363b | ||
|
|
6205e18c45 | ||
|
|
959b3e46fa | ||
|
|
09d8d09aad | ||
|
|
70336e31c7 | ||
|
|
600e0f3d67 | ||
|
|
023e356057 | ||
|
|
27786ec00a | ||
|
|
e52e72c5a8 | ||
|
|
802dd08ce7 | ||
|
|
568ec5a1a2 | ||
|
|
035d196392 | ||
|
|
dd3ffc64b9 | ||
|
|
c9a38f0a13 | ||
|
|
78461a9d5a | ||
|
|
79b8fb910a | ||
|
|
405e3df1f0 | ||
|
|
f7126d154f | ||
|
|
d8df8c9631 | ||
|
|
37b35f9063 | ||
|
|
f61a7288eb | ||
|
|
47a1122f04 | ||
|
|
e1bfabbce5 | ||
|
|
9708fec0e0 | ||
|
|
7f4efaf0a3 | ||
|
|
269eb0ba29 | ||
|
|
428c6b7813 | ||
|
|
db2452a4ec | ||
|
|
7dac3825d7 | ||
|
|
7c99872278 | ||
|
|
64c7318cfc | ||
|
|
a9d6483829 | ||
|
|
13a6b92e47 | ||
|
|
9ba008002b | ||
|
|
8914cf78a1 | ||
|
|
d360375b4f | ||
|
|
1caab194af | ||
|
|
31754eba5d | ||
|
|
3cfa16b8b7 | ||
|
|
f80d2bacf4 | ||
|
|
5df3717d94 | ||
|
|
68897f04a2 | ||
|
|
4cb6aeae36 | ||
|
|
0a765a35bf | ||
|
|
6c0b122fbc | ||
|
|
4da2bd90cb | ||
|
|
f0275192c6 | ||
|
|
df905a1d73 | ||
|
|
ad8ad06f44 | ||
|
|
d6b9e2df62 | ||
|
|
5c9b36556f | ||
|
|
80a8348a99 | ||
|
|
005c9f471e | ||
|
|
b40532a830 | ||
|
|
fc7a4408e9 | ||
|
|
93b5f0081d | ||
|
|
ce049ea3ee | ||
|
|
fcc39b2db5 | ||
|
|
cb70fb4e82 | ||
|
|
2593a43d72 | ||
|
|
e44ff5b72a | ||
|
|
22cb1b50a6 | ||
|
|
a42c413705 | ||
|
|
d59d38dc7c | ||
|
|
77582be7fd | ||
|
|
0cb50355b7 | ||
|
|
a2d66e91ff | ||
|
|
ccdb981917 | ||
|
|
d80b581ace | ||
|
|
53efb6711d | ||
|
|
1de6e875f9 | ||
|
|
95a15c3cf8 | ||
|
|
ab320684f5 | ||
|
|
a284b69a1e | ||
|
|
b590f41254 | ||
|
|
a97076ead5 | ||
|
|
0b6df8be1c | ||
|
|
150bab0b57 | ||
|
|
d3355eda65 | ||
|
|
fbf10e553d | ||
|
|
fb37be5734 | ||
|
|
54e6cefa67 | ||
|
|
33b25c1129 | ||
|
|
44d8545c09 | ||
|
|
7a2808243c | ||
|
|
1be84de26b | ||
|
|
78e37f7ab4 | ||
|
|
e49459fd8b | ||
|
|
52f6e7fc32 | ||
|
|
c8ea61dc79 | ||
|
|
16a769ea61 | ||
|
|
6b880af447 | ||
|
|
475781db91 | ||
|
|
4dae082cd5 | ||
|
|
57405b2f56 | ||
|
|
88576f68fd | ||
|
|
aa4e013097 | ||
|
|
d67cfc911b | ||
|
|
00a3ad738f | ||
|
|
1d39d34d7c | ||
|
|
5f6013edd4 | ||
|
|
3e198ecd28 | ||
|
|
d48b98f582 | ||
|
|
9b839231f7 | ||
|
|
dd80614465 | ||
|
|
8c2be1b406 | ||
|
|
8152b7dad6 | ||
|
|
fb4fe175d9 | ||
|
|
5e03eb9b51 | ||
|
|
ef25575f85 | ||
|
|
b77b338c7a | ||
|
|
0e4fe4e9bb | ||
|
|
f742f83834 | ||
|
|
e6e4e53a73 | ||
|
|
7c594ba7a9 | ||
|
|
0156a9a9d5 | ||
|
|
3facbc0900 | ||
|
|
78cef1b3c7 | ||
|
|
d907c469ed | ||
|
|
cc238d3e34 | ||
|
|
0f9b38895e | ||
|
|
8fa1eae352 | ||
|
|
e13fb25f14 | ||
|
|
e36f942129 | ||
|
|
d34619824c | ||
|
|
80297f113f | ||
|
|
80f51bfe1e | ||
|
|
f8b9f4c1fa | ||
|
|
587f431ef4 | ||
|
|
65a4f66d2c | ||
|
|
a253b6c0cf | ||
|
|
efcbc1fbdb | ||
|
|
e560f9cbd6 | ||
|
|
80235d53f4 | ||
|
|
892b9a732e | ||
|
|
d8a0a015e4 | ||
|
|
e60e3b9fae | ||
|
|
6715f01b8c | ||
|
|
465af9bc41 | ||
|
|
d10bcfc72f | ||
|
|
942e5b9cd1 | ||
|
|
51a90d32f8 | ||
|
|
ac46632e73 | ||
|
|
1192bef1ae | ||
|
|
b9ec382589 | ||
|
|
5ecf19ef4f | ||
|
|
9636809b4d | ||
|
|
ba1c1ed952 | ||
|
|
7452390614 | ||
|
|
69042e42b7 | ||
|
|
1e93deab2a | ||
|
|
16ea809bb3 | ||
|
|
78aa4343b7 | ||
|
|
6815109e15 | ||
|
|
e34fbcec58 | ||
|
|
bb2a21270b | ||
|
|
49b9ec9025 | ||
|
|
a2e896e102 | ||
|
|
2e1ef647a9 | ||
|
|
f0c314df80 | ||
|
|
4db39828ef | ||
|
|
b2d40825ac | ||
|
|
6df5d3334e | ||
|
|
0e982df90c | ||
|
|
3834d93c9d | ||
|
|
16920a5b82 | ||
|
|
d66e35fdde | ||
|
|
d93dde0a03 | ||
|
|
2d232124dd | ||
|
|
ac6702fcf7 | ||
|
|
c4b016c9c8 | ||
|
|
6baa583a28 | ||
|
|
82df2ecfa9 | ||
|
|
06b3de720a | ||
|
|
b0edd5659f | ||
|
|
bb5c2eea10 | ||
|
|
e31e4dfe3a | ||
|
|
caf2cd8487 | ||
|
|
15c6f11a5e | ||
|
|
a4ea88f4be | ||
|
|
36d5747fbf | ||
|
|
3d8c535ffa | ||
|
|
1c067d0284 | ||
|
|
b6be0462a5 | ||
|
|
cce91ea16d | ||
|
|
d756041b06 | ||
|
|
2d0eb0a05b | ||
|
|
02f3239669 | ||
|
|
14a9240c45 | ||
|
|
c659638fb4 | ||
|
|
fd15b63044 | ||
|
|
263e6c34b5 | ||
|
|
eb62a3dc17 | ||
|
|
161ee090a8 | ||
|
|
560ec437b9 | ||
|
|
ccd0597b35 | ||
|
|
c5c0a3768a | ||
|
|
5aa2d24d58 | ||
|
|
ae28c595f9 | ||
|
|
1d08ddda60 | ||
|
|
578379fd00 | ||
|
|
7c9f550d4c | ||
|
|
84d4510d70 | ||
|
|
fa194ec258 | ||
|
|
fd56de403d | ||
|
|
85fde46504 | ||
|
|
b283178979 | ||
|
|
e0dddfceba | ||
|
|
bddef38a7c | ||
|
|
b5f2f77944 | ||
|
|
fca0718ed0 | ||
|
|
0d44ade6ea | ||
|
|
08ca2aa266 | ||
|
|
fe15758e59 | ||
|
|
674efae184 | ||
|
|
4a65bc88d5 | ||
|
|
a8f3d59729 | ||
|
|
6018f83a22 | ||
|
|
0b6247851b | ||
|
|
8640dee053 | ||
|
|
824db2e3bd | ||
|
|
c2c79c4676 | ||
|
|
4795fe5687 | ||
|
|
d508f339c1 | ||
|
|
c7054537e7 | ||
|
|
b98b904023 | ||
|
|
253df9325d | ||
|
|
78a9cc1d0c | ||
|
|
b25fcc3381 | ||
|
|
a2c0df5891 | ||
|
|
dc33c26960 | ||
|
|
51d7bc2c37 | ||
|
|
cdbdccf1ad | ||
|
|
397c369114 | ||
|
|
6f9bbb184a | ||
|
|
b12c818862 | ||
|
|
9118dcf925 | ||
|
|
d333d0c9e4 | ||
|
|
7f9cf6f45c | ||
|
|
9b465cb550 | ||
|
|
9144b7206e | ||
|
|
dd14843f2e | ||
|
|
09a18b2305 | ||
|
|
31f2feee2e | ||
|
|
218bb62bfd | ||
|
|
694c2ad767 | ||
|
|
97943fcd38 | ||
|
|
77f33467d2 | ||
|
|
651454170d | ||
|
|
7ca48bd136 | ||
|
|
968e508bb5 | ||
|
|
a6d318a197 | ||
|
|
cd20f4086b | ||
|
|
ebd5905947 | ||
|
|
817a3c62bb | ||
|
|
f8f58400fe | ||
|
|
ef06840649 | ||
|
|
b17c14d62e | ||
|
|
19dba94064 | ||
|
|
601e24f9e7 | ||
|
|
c7f323ee13 | ||
|
|
e4522f3af4 | ||
|
|
79af461a5b | ||
|
|
2e8e07faf6 | ||
|
|
ecdb000818 | ||
|
|
999fd0d4da | ||
|
|
705dd9558f | ||
|
|
97ca866ffa | ||
|
|
543b977db7 | ||
|
|
ebb8a6d025 | ||
|
|
506543281e | ||
|
|
60322be22a | ||
|
|
e1f30f24a8 | ||
|
|
1759f6b25c | ||
|
|
6578f25cc9 | ||
|
|
8c26e0323f | ||
|
|
a5575894ab | ||
|
|
357823a027 | ||
|
|
a6d3f6b3eb | ||
|
|
ae4c69e75c | ||
|
|
31cadc532b | ||
|
|
6e8443473b | ||
|
|
cca4ab3cd8 | ||
|
|
dab0ee3306 | ||
|
|
c6d1ed91a7 | ||
|
|
a613a244f4 | ||
|
|
268fe15004 | ||
|
|
7bc9be686f | ||
|
|
751919ec5a | ||
|
|
da913b426e | ||
|
|
d8ef99cd8f | ||
|
|
d08a6d7dd3 | ||
|
|
896e9bca8e | ||
|
|
1df9597bb1 | ||
|
|
eaf55f2099 | ||
|
|
5018a1f9eb | ||
|
|
71ba8f55a7 | ||
|
|
b65db707ed | ||
|
|
ed62266a43 | ||
|
|
49913b7dad | ||
|
|
3eeeb9e00b | ||
|
|
bfb1642284 | ||
|
|
0544a605c3 | ||
|
|
3f5acda132 | ||
|
|
02b1ba2926 | ||
|
|
7f7f9e3c7c | ||
|
|
6fcee03752 | ||
|
|
5782ceeb5d | ||
|
|
f752db5892 | ||
|
|
bce58bc97b | ||
|
|
d373687bc4 | ||
|
|
e5e510c825 | ||
|
|
29064ec72f | ||
|
|
953eee1dc8 | ||
|
|
75f76f4875 | ||
|
|
ecfbe68c33 | ||
|
|
7f02eb9cf0 | ||
|
|
4ab90065dc | ||
|
|
d3e39a1359 | ||
|
|
60e5861de4 | ||
|
|
ca7f5045ae | ||
|
|
299bd67151 | ||
|
|
4d4bb3fd7f | ||
|
|
7fd64a1b73 | ||
|
|
e3e8765b91 | ||
|
|
b0997fb5d2 | ||
|
|
435cf05f9f | ||
|
|
37dab9fb22 | ||
|
|
943dfe0619 | ||
|
|
be7114d3e6 | ||
|
|
fb44c8fbe4 | ||
|
|
94375b7d36 | ||
|
|
8b585deb78 | ||
|
|
4d8b544aed | ||
|
|
548d651d29 | ||
|
|
0b342acec9 | ||
|
|
cc6d3c1b1a | ||
|
|
74a748d92e | ||
|
|
1de81d0af5 | ||
|
|
ff9ef21f67 | ||
|
|
266a546478 | ||
|
|
87407ca832 | ||
|
|
90282d4436 | ||
|
|
abbe6d6c1f | ||
|
|
a28f701e6f | ||
|
|
4cdc995a7f | ||
|
|
713a01bfa9 | ||
|
|
ac291b688d | ||
|
|
84f7e244f2 | ||
|
|
4a8207f367 | ||
|
|
9cfd4d27e9 | ||
|
|
1b23cfd747 | ||
|
|
c708205593 | ||
|
|
a22c6c8013 | ||
|
|
b576f473e5 | ||
|
|
0b127caa83 | ||
|
|
5801bf3bdf | ||
|
|
4507ce359d | ||
|
|
3e14f28dc2 | ||
|
|
a9dcf09d13 | ||
|
|
c8998c2bcf | ||
|
|
10bf1295bc | ||
|
|
1e869973d4 | ||
|
|
731c8962c9 | ||
|
|
294b8bb789 | ||
|
|
4f9b819f48 | ||
|
|
5318d5fa8e | ||
|
|
98b156bdde | ||
|
|
511dd02107 | ||
|
|
f1f7a2e7b6 | ||
|
|
d557cf5427 | ||
|
|
2b1c55ee67 | ||
|
|
925ddaa63a | ||
|
|
2b60b18d47 | ||
|
|
d502406fa2 | ||
|
|
afdbf711f7 | ||
|
|
39d2941099 | ||
|
|
b4f7b1d71d | ||
|
|
69061cd41c | ||
|
|
8ba7f7f961 | ||
|
|
5e5aa17e14 | ||
|
|
551f5fc929 | ||
|
|
4e7b0d11d0 | ||
|
|
06bc53692a | ||
|
|
007ee38cb4 | ||
|
|
2a732306a1 | ||
|
|
82192bef91 | ||
|
|
0c51dfe19c | ||
|
|
24a9fa1ccc | ||
|
|
14b06507cb | ||
|
|
b46233087b | ||
|
|
28fb2e2a08 | ||
|
|
943e211cf1 | ||
|
|
ad0a13004e | ||
|
|
04bb6a5275 | ||
|
|
d3c917eac1 | ||
|
|
4c13271a5b | ||
|
|
20027c2db7 | ||
|
|
6affc70a66 | ||
|
|
ab4c9bdeda | ||
|
|
b4a9c9b7f5 | ||
|
|
5e20d50abf | ||
|
|
53abbbbe56 | ||
|
|
1938cb586d | ||
|
|
50490ece84 | ||
|
|
f291cc2bd3 | ||
|
|
2542c8bd53 | ||
|
|
b457fd634e | ||
|
|
041fd0e0cd | ||
|
|
a983edde1e | ||
|
|
7eb642dd13 | ||
|
|
e0bc93371e | ||
|
|
db56486506 | ||
|
|
c99be13697 | ||
|
|
0830c78728 | ||
|
|
edade93054 | ||
|
|
8a72b30cbc | ||
|
|
ed9cb0f918 | ||
|
|
7e0915cb9c | ||
|
|
a51294d570 | ||
|
|
d962f218a1 | ||
|
|
7b248427f0 | ||
|
|
b99fb8b11f | ||
|
|
26250e790f | ||
|
|
b26dbe81f4 | ||
|
|
903212345b | ||
|
|
025f6564dc | ||
|
|
35f97368fa | ||
|
|
09e5c86488 | ||
|
|
8998371cae | ||
|
|
29e1dc6b55 | ||
|
|
439e63b52f | ||
|
|
eea341fb33 | ||
|
|
359eedf773 | ||
|
|
866751ffc1 | ||
|
|
38a3a0768d | ||
|
|
03b42749cd | ||
|
|
60fd78e082 | ||
|
|
9edaf58929 | ||
|
|
5000186f85 | ||
|
|
cacf0ea987 | ||
|
|
067501cbe7 | ||
|
|
9fe0cf496b | ||
|
|
9d0823038e | ||
|
|
5a05efefdd | ||
|
|
988d171bdd | ||
|
|
e6f72bf343 | ||
|
|
89c5a0c57b | ||
|
|
d97146393c | ||
|
|
1c52f1f76c | ||
|
|
9bd3a68115 | ||
|
|
f58780d36b | ||
|
|
6eb15ab437 | ||
|
|
00dc7004f5 | ||
|
|
8ec0e57235 | ||
|
|
d75dc9e70c | ||
|
|
ec2fccbb0e | ||
|
|
34861166e8 | ||
|
|
584fa0a26e | ||
|
|
6c48489d89 | ||
|
|
ba9c884a0c | ||
|
|
360f0bafe0 | ||
|
|
4327c13dca | ||
|
|
4f2256f713 | ||
|
|
5167cd368f | ||
|
|
ef7289d11a | ||
|
|
cb11d98bf7 | ||
|
|
992349da8c | ||
|
|
2e7637f274 | ||
|
|
1f8eaf4a64 | ||
|
|
46ac7a9dc7 | ||
|
|
0d86d39217 | ||
|
|
1f591f3d1b | ||
|
|
30c6ddba37 | ||
|
|
406eeaec96 | ||
|
|
2fe5652bc6 | ||
|
|
39bf68a6bd | ||
|
|
a7a4a19824 | ||
|
|
7f906ba0ea | ||
|
|
07bf6e4506 | ||
|
|
a331760321 | ||
|
|
d9c240d729 | ||
|
|
d9526c19e7 | ||
|
|
1798ccd284 | ||
|
|
ab1ce7fab1 | ||
|
|
e9b2f17171 | ||
|
|
d3bf4433b7 | ||
|
|
ba0f43455b | ||
|
|
638af4bcd7 | ||
|
|
5eab843d97 | ||
|
|
c55f0e239e | ||
|
|
32d9381745 | ||
|
|
77fc564e70 | ||
|
|
3b84314c45 | ||
|
|
5729c20386 | ||
|
|
a4d70d8095 | ||
|
|
8fcce349d5 | ||
|
|
5a94676a3a | ||
|
|
f32d72ee62 | ||
|
|
e35fc8620c | ||
|
|
277c288952 | ||
|
|
240b08e55c | ||
|
|
fe7f345661 | ||
|
|
c8db01c958 | ||
|
|
f456185f7d | ||
|
|
801b555835 | ||
|
|
eee177e64b | ||
|
|
63639f8e96 | ||
|
|
de1b0b1bb6 | ||
|
|
bbdd7fc2b4 | ||
|
|
6addb5c4b4 | ||
|
|
b47e0c88d6 | ||
|
|
d06993d940 | ||
|
|
d31f167b9e | ||
|
|
f12ee6c167 | ||
|
|
983b341f33 | ||
|
|
f3e6642f05 | ||
|
|
0a63990d21 | ||
|
|
6909bb4b03 | ||
|
|
620aa8bcee | ||
|
|
6db39d1860 | ||
|
|
1762ead89f | ||
|
|
d13ddeb944 | ||
|
|
1b5da0e1d1 | ||
|
|
7a2d0e7fcb | ||
|
|
477c3b6b1e | ||
|
|
95312c3650 | ||
|
|
98a3c4b0f5 | ||
|
|
6e990a7e31 | ||
|
|
8e49904f8d | ||
|
|
69f52c8abd | ||
|
|
d7b0754327 | ||
|
|
2a00de11f1 | ||
|
|
923cc51f3e | ||
|
|
c8f7478170 | ||
|
|
9006e835c6 | ||
|
|
f801d61929 | ||
|
|
a143e5777c | ||
|
|
bffac60bf8 | ||
|
|
bf500e46e7 | ||
|
|
4a2f79f390 | ||
|
|
c24ce7c5bc | ||
|
|
8a6a0c7971 | ||
|
|
de6e5bd800 | ||
|
|
e18a04f9e6 | ||
|
|
14fc652f4b | ||
|
|
9a876e747a | ||
|
|
f8ee8b27fb | ||
|
|
ce1a1487aa | ||
|
|
fe1e364a1d | ||
|
|
eabb052107 | ||
|
|
734f3621f1 | ||
|
|
ae8323e2f8 | ||
|
|
9612a81f2e | ||
|
|
2945a36cef | ||
|
|
b84dc5bfcc | ||
|
|
60486fd880 | ||
|
|
891091cebc | ||
|
|
1493ddcf41 | ||
|
|
4299c50537 | ||
|
|
14577c396d | ||
|
|
e9b566241d | ||
|
|
d39b08c035 | ||
|
|
69ac683c8c | ||
|
|
eafd0b3d06 | ||
|
|
310a4989dc | ||
|
|
3d0df51839 | ||
|
|
ede02aaaa5 | ||
|
|
beff149004 | ||
|
|
07db6e8fb0 | ||
|
|
46852c0780 | ||
|
|
a5e41c573f | ||
|
|
ed91aa4648 | ||
|
|
9a94395d30 | ||
|
|
04aa61c2bb | ||
|
|
035a13df54 | ||
|
|
e8a6f0ca3d | ||
|
|
1fc519b9de | ||
|
|
2bcf38e2e3 | ||
|
|
8eb44a68cb | ||
|
|
30c7b442a8 | ||
|
|
cee2211108 | ||
|
|
b7bcbccd45 | ||
|
|
d2ccb97eba | ||
|
|
39d56f2603 | ||
|
|
83e904dd2d | ||
|
|
110c787eba | ||
|
|
7c7ff289de | ||
|
|
617a35c51b | ||
|
|
73487ccf65 | ||
|
|
712bff9c99 | ||
|
|
eedfcf86aa | ||
|
|
f730848928 | ||
|
|
61d0574c5c | ||
|
|
2f01e01ec1 | ||
|
|
cbcf66df7f | ||
|
|
cfaeea039b | ||
|
|
a891d1eb54 | ||
|
|
4372052ef0 | ||
|
|
8734b062dc | ||
|
|
343451de65 | ||
|
|
144d65c776 | ||
|
|
a6815574f7 | ||
|
|
e5a116a0d4 | ||
|
|
0beef6b108 | ||
|
|
7341008449 | ||
|
|
49bd53194a | ||
|
|
baf4437efc | ||
|
|
b244f80f81 | ||
|
|
e41c91a42b | ||
|
|
b9a2e3ceac | ||
|
|
fa7dd3bdc4 | ||
|
|
9a8c68b846 | ||
|
|
698e33ddf4 | ||
|
|
909258ba14 | ||
|
|
2ad6bd1d23 | ||
|
|
510ffd41d8 | ||
|
|
4f00591c4e | ||
|
|
5b65ed87cd | ||
|
|
b0121c422d | ||
|
|
a9e9fad222 | ||
|
|
b5fc07acc7 | ||
|
|
140ebfdb92 | ||
|
|
37d0179de1 | ||
|
|
823d4b0fe2 | ||
|
|
dd1eacf4f0 | ||
|
|
86c33dd686 | ||
|
|
c6757cc61b | ||
|
|
a38cf284dd | ||
|
|
575b8e3f7f | ||
|
|
bc443f47f1 | ||
|
|
b631bcc0db | ||
|
|
5ccd92ece6 | ||
|
|
2f3c8868a7 | ||
|
|
6f7b5e8005 | ||
|
|
10d1e4b798 | ||
|
|
9d5934df14 | ||
|
|
be507de6c1 | ||
|
|
e5d3c08821 | ||
|
|
027b4ab7da | ||
|
|
fefea0d7ec | ||
|
|
33f30bfd19 | ||
|
|
e9d4b9961a | ||
|
|
b94248fe79 | ||
|
|
225975e0dd | ||
|
|
eac7492143 | ||
|
|
b3c40bf448 | ||
|
|
02f7cd77f4 | ||
|
|
7f8f3aa99b | ||
|
|
0bcdc14909 | ||
|
|
526c25a02b | ||
|
|
f48da9dab1 | ||
|
|
2e8dfda12e | ||
|
|
63da576d85 | ||
|
|
0ab4206540 | ||
|
|
212ae90401 | ||
|
|
d4e5d0be45 | ||
|
|
3520a0f1fb | ||
|
|
036090a947 | ||
|
|
dc570c683a | ||
|
|
9f85d34c91 | ||
|
|
16bf1fb6c3 | ||
|
|
47c4d508e0 | ||
|
|
e5d9060623 | ||
|
|
fdf28fc385 | ||
|
|
9015a4d56b | ||
|
|
38301454a6 | ||
|
|
9b3a22c4ca | ||
|
|
548dbc3649 | ||
|
|
3474129812 | ||
|
|
63193feebe | ||
|
|
51f22bfe75 | ||
|
|
7d0f7e1c8e | ||
|
|
dd8ab242fb | ||
|
|
60f3428da7 | ||
|
|
c6fec0a131 | ||
|
|
fdc43fc0d3 | ||
|
|
0b880aa335 | ||
|
|
74f50ec992 | ||
|
|
1bdf4532db | ||
|
|
f97783ddef | ||
|
|
1024d6fc07 | ||
|
|
3ec59d0c58 | ||
|
|
c43249316c | ||
|
|
ed5180ffd6 | ||
|
|
e9ec769340 | ||
|
|
5e16ff8dff | ||
|
|
364b6631ea | ||
|
|
48a18e53e3 | ||
|
|
bcc8282d73 | ||
|
|
15017ed49c | ||
|
|
50d36fe91b | ||
|
|
23e67a2908 | ||
|
|
0dab1b73cc | ||
|
|
3c086a92e2 | ||
|
|
647d72514b | ||
|
|
15328b4fd7 | ||
|
|
b49a498f9c | ||
|
|
8d14d5f87c | ||
|
|
a6db352ecd | ||
|
|
ccbb26c176 | ||
|
|
8f6af73541 | ||
|
|
a59f17fdb2 | ||
|
|
14222e40ad | ||
|
|
7d48bf06fe | ||
|
|
1d06a2c2e8 | ||
|
|
cf141f0e55 | ||
|
|
9113c31612 | ||
|
|
00b4e0a6fd | ||
|
|
e3cac95d37 | ||
|
|
64d850c583 | ||
|
|
2fe1b9e726 | ||
|
|
1315d847b9 | ||
|
|
b5954102b6 | ||
|
|
1c8ba0c538 | ||
|
|
be18317a6d | ||
|
|
88d2b8266e | ||
|
|
949ca5ddff | ||
|
|
3eb53b9648 | ||
|
|
e4a03ede1f | ||
|
|
cb65dc0e9d | ||
|
|
8ec907050e | ||
|
|
15ba00a902 | ||
|
|
89d0c301c2 | ||
|
|
2f47466f3b | ||
|
|
d70eca9774 | ||
|
|
95ce92fa18 | ||
|
|
b3db52b2ed | ||
|
|
c40912013d | ||
|
|
1c08e98c1c | ||
|
|
3f202a7cdc | ||
|
|
6f3aea8fc1 | ||
|
|
0896143838 | ||
|
|
ea94899a28 | ||
|
|
d2109cef86 | ||
|
|
cda146366c | ||
|
|
678b879a01 | ||
|
|
4c885c5e7b | ||
|
|
d5002b1c33 | ||
|
|
4f8b6d6b28 | ||
|
|
66dab41539 | ||
|
|
9e4940228d | ||
|
|
cbb11ebb03 | ||
|
|
073a25f381 | ||
|
|
40592ab876 | ||
|
|
bbfe624b51 | ||
|
|
a2af9e4c65 | ||
|
|
0123a8895f | ||
|
|
53854a4d13 | ||
|
|
4fdd44858f | ||
|
|
3c58879ce5 | ||
|
|
a7c6a881b3 | ||
|
|
ef065d31a0 | ||
|
|
d059d6b448 | ||
|
|
2d0a6f1bec | ||
|
|
a3cc5a1938 | ||
|
|
435068515a | ||
|
|
956001dbd7 | ||
|
|
460f0d9dee | ||
|
|
5155ec93c9 | ||
|
|
8bb8883e22 | ||
|
|
ffb7a6dfbb | ||
|
|
176de6f245 | ||
|
|
11f9740dbf | ||
|
|
42a91ba26c | ||
|
|
234003e2b1 | ||
|
|
534384438b | ||
|
|
ab51f35d5d | ||
|
|
511a4044d7 | ||
|
|
821efaff40 | ||
|
|
91bc994532 | ||
|
|
1323b46ac7 | ||
|
|
3a8b30ca8e | ||
|
|
923d58519f | ||
|
|
eabb1f84f6 | ||
|
|
cfbe44b946 | ||
|
|
81c35eab46 | ||
|
|
a1c7c29113 | ||
|
|
1293e2a074 |
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -15,8 +15,14 @@
|
||||
# BINARY FILES:
|
||||
# Disable line ending normalize on checkin.
|
||||
|
||||
*.dll binary
|
||||
*.dylib binary
|
||||
*.gif binary
|
||||
*.jar binary
|
||||
*.lib binary
|
||||
*.otf binary
|
||||
*.png binary
|
||||
*.sketch binary
|
||||
*.so binary
|
||||
*.ttf binary
|
||||
*.zip binary
|
||||
|
||||
8
.gitbugtraq
Normal file
8
.gitbugtraq
Normal file
@@ -0,0 +1,8 @@
|
||||
# links issue numbers in git commit messages to issue tracker
|
||||
# https://github.com/mstrap/bugtraq
|
||||
# for SmartGit - https://www.syntevo.com/smartgit/
|
||||
|
||||
[bugtraq]
|
||||
url = "https://github.com/JFormDesigner/FlatLaf/issues/%BUGID%"
|
||||
loglinkregex = "#[0-9]{1,5}"
|
||||
logregex = "[0-9]{1,5}"
|
||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
custom: https://www.formdev.com/flatlaf/sponsor/
|
||||
158
.github/workflows/ci.yml
vendored
158
.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,53 +25,48 @@ 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
|
||||
- 23 # latest
|
||||
toolchain: [""]
|
||||
# include:
|
||||
# - java: 21
|
||||
# toolchain: 22 # latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- 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-core/build/libs
|
||||
flatlaf-demo/build/libs
|
||||
flatlaf-extras/build/libs
|
||||
flatlaf-intellij-themes/build/libs
|
||||
flatlaf-jide-oss/build/libs
|
||||
flatlaf-swingx/build/libs
|
||||
flatlaf-*/build/libs
|
||||
flatlaf-*/flatlaf-*/build/libs
|
||||
!**/*-javadoc.jar
|
||||
!**/*-sources.jar
|
||||
|
||||
@@ -75,35 +76,35 @@ jobs:
|
||||
needs: build
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/master' &&
|
||||
(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
|
||||
distribution: temurin # 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: Publish snapshot to oss.jfrog.org
|
||||
run: ./gradlew artifactoryPublish
|
||||
- name: Publish snapshot to oss.sonatype.org
|
||||
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||
env:
|
||||
BINTRAY_USER: ${{ secrets.BINTRAY_USER }}
|
||||
BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
|
||||
- name: Upload theme editor
|
||||
uses: sebastianpopp/ftp-action@releases/v2
|
||||
with:
|
||||
host: ${{ secrets.FTP_SERVER }}
|
||||
user: ${{ secrets.FTP_USERNAME }}
|
||||
password: ${{ secrets.FTP_PASSWORD }}
|
||||
forceSsl: true
|
||||
localDir: "flatlaf-theme-editor/build/libs"
|
||||
remoteDir: "snapshots"
|
||||
options: "--only-newer --no-recursion --verbose=1"
|
||||
|
||||
|
||||
release:
|
||||
@@ -115,28 +116,41 @@ 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
|
||||
distribution: temurin # 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: Release a new stable version to bintray
|
||||
run: ./gradlew bintrayUpload -Drelease=true
|
||||
- name: Release a new stable version to Maven Central
|
||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
||||
env:
|
||||
BINTRAY_USER: ${{ secrets.BINTRAY_USER }}
|
||||
BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
||||
|
||||
- name: Upload demo
|
||||
uses: sebastianpopp/ftp-action@releases/v2
|
||||
with:
|
||||
host: ${{ secrets.FTP_SERVER }}
|
||||
user: ${{ secrets.FTP_USERNAME }}
|
||||
password: ${{ secrets.FTP_PASSWORD }}
|
||||
forceSsl: true
|
||||
localDir: "flatlaf-demo/build/libs"
|
||||
remoteDir: "."
|
||||
options: "--only-newer --no-recursion --verbose=1"
|
||||
|
||||
- name: Upload theme editor
|
||||
uses: sebastianpopp/ftp-action@releases/v2
|
||||
with:
|
||||
host: ${{ secrets.FTP_SERVER }}
|
||||
user: ${{ secrets.FTP_USERNAME }}
|
||||
password: ${{ secrets.FTP_PASSWORD }}
|
||||
forceSsl: true
|
||||
localDir: "flatlaf-theme-editor/build/libs"
|
||||
remoteDir: "."
|
||||
options: "--only-newer --no-recursion --verbose=1"
|
||||
|
||||
62
.github/workflows/fonts.yml
vendored
Normal file
62
.github/workflows/fonts.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||
|
||||
name: Fonts
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
tags:
|
||||
- 'fonts/*-[0-9]*'
|
||||
paths:
|
||||
- 'flatlaf-fonts/**'
|
||||
- '.github/workflows/fonts.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
- '!**.md'
|
||||
- '!**/.settings/**'
|
||||
|
||||
jobs:
|
||||
Fonts:
|
||||
strategy:
|
||||
matrix:
|
||||
font:
|
||||
- inter
|
||||
- jetbrains-mono
|
||||
- roboto
|
||||
- roboto-mono
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
distribution: temurin # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build
|
||||
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true
|
||||
|
||||
- name: Publish snapshot to 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 ) )
|
||||
53
.github/workflows/natives.yml
vendored
Normal file
53
.github/workflows/natives.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# 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
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
paths:
|
||||
- 'flatlaf-natives/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
- '!**.md'
|
||||
- '!**/.settings/**'
|
||||
|
||||
jobs:
|
||||
Natives:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- windows
|
||||
- macos
|
||||
- ubuntu
|
||||
|
||||
runs-on: ${{ matrix.os }}-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v2
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
|
||||
- name: Build with Gradle
|
||||
# --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@v4
|
||||
with:
|
||||
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||
path: |
|
||||
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 }}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -9,3 +9,7 @@ out/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.xcuserstate
|
||||
*.xcworkspacedata
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
1379
CHANGELOG.md
1379
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
333
README.md
333
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,23 @@ FlatLaf can use 3rd party themes created for IntelliJ Platform (see
|
||||

|
||||
|
||||
|
||||
Sponsors
|
||||
--------
|
||||
|
||||
### Current Sponsors
|
||||
|
||||
[](https://www.formdev.com/flatlaf/sponsor/)
|
||||
|
||||
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
|
||||
|
||||
### Previous Sponsors
|
||||
|
||||
<a href="https://www.ej-technologies.com/"><img src="https://www.formdev.com/flatlaf/sponsor/ej-technologies.png" width="200" alt="ej-technologies" title="ej-technologies - Java APM, Java Profiler, Java Installer Builder"></a>
|
||||
|
||||
<a href="https://www.dbvis.com/"><img src="https://www.formdev.com/flatlaf/sponsor/dbvisualizer.svg" width="200" alt="DbVisualizer" title="DbVisualizer - SQL Client and Editor"></a>
|
||||
|
||||
<a href="https://www.dscsag.com/"><img src="https://www.formdev.com/flatlaf/sponsor/DSC.png" height="48" alt="DSC Software AG" title="DSC Software AG - Your Companion for Integrative PLM"></a>
|
||||
|
||||
Demo
|
||||
----
|
||||
|
||||
@@ -37,7 +59,7 @@ Requires Java 8 or newer.
|
||||
Download
|
||||
--------
|
||||
|
||||
FlatLaf binaries are available on **JCenter** and **Maven Central**.
|
||||
FlatLaf binaries are available on **Maven Central**.
|
||||
|
||||
If you use Maven or Gradle, add a dependency with following coordinates to your
|
||||
build script:
|
||||
@@ -46,18 +68,23 @@ build script:
|
||||
artifactId: flatlaf
|
||||
version: (see button below)
|
||||
|
||||
Otherwise download `flatlaf-<version>.jar` here:
|
||||
Otherwise, download `flatlaf-<version>.jar` here:
|
||||
|
||||
[](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)
|
||||
[](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
|
||||
|
||||
FlatLaf snapshot binaries are available in
|
||||
[JFrog Artifactory](https://oss.jfrog.org/artifactory/oss-snapshot-local/com/formdev/).
|
||||
To access the latest snapshot, change the FlatLaf version(s) in the dependencies
|
||||
FlatLaf snapshot binaries are available on
|
||||
[Sonatype OSSRH](https://oss.sonatype.org/content/repositories/snapshots/com/formdev/flatlaf/).
|
||||
To access the latest snapshot, change the FlatLaf version in your dependencies
|
||||
to `<version>-SNAPSHOT` (e.g. `0.27-SNAPSHOT`) and add the repository
|
||||
`https://oss.jfrog.org/artifactory/oss-snapshot-local` to your build (see
|
||||
`https://oss.sonatype.org/content/repositories/snapshots/` to your build (see
|
||||
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
|
||||
and
|
||||
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
|
||||
@@ -67,57 +94,257 @@ docs).
|
||||
Addons
|
||||
------
|
||||
|
||||
- [IntelliJ Themes Pack](flatlaf-intellij-themes)
|
||||
- [Extras](flatlaf-extras)
|
||||
- [SwingX](flatlaf-swingx)
|
||||
- [JIDE Common Layer](flatlaf-jide-oss)
|
||||
- [IntelliJ Themes Pack](flatlaf-intellij-themes) - bundles many popular
|
||||
open-source 3rd party themes
|
||||
- [Extras](flatlaf-extras) - SVG icon, tri-state check box, UI inspectors, and
|
||||
more
|
||||
- [SwingX](flatlaf-swingx) - support for SwingX components
|
||||
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
|
||||
components
|
||||
- [Fonts](flatlaf-fonts) - some font families bundled in easy-to-use and
|
||||
redistributable JARs
|
||||
|
||||
|
||||
Projects using FlatLaf
|
||||
----------------------
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
- [NetBeans](https://netbeans.apache.org/) 11.3
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
||||
- [OWASP Zed Attack Proxy (ZAP)](https://www.zaproxy.org/) (in weekly releases)
|
||||
-  [jAlbum](https://jalbum.net/) 21 (commercial)
|
||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (commercial)
|
||||
- [Total Validator](https://www.totalvalidator.com/) 15 (commercial)
|
||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org)
|
||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5
|
||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||
0.13.b024
|
||||
- [Rest Suite](https://github.com/supanadit/restsuite)
|
||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy)
|
||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote)
|
||||
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
||||
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
||||
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||
[AS4](https://mendelson-e-c.com/as4/) and
|
||||
[OFTP2](https://mendelson-e-c.com/oftp2) (commercial)
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform)
|
||||
- [Jes - Die Java-E<>R](https://www.jes-eur.de)
|
||||
- [Mapton](https://mapton.org/) 2.0
|
||||
([source code](https://github.com/trixon/mapton)) based on NetBeans platform
|
||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE)
|
||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis)
|
||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - Multifunctional LED
|
||||
Control Software
|
||||
- and more...
|
||||
To use FlatLaf, add following code to your main method before you create any
|
||||
Swing component:
|
||||
|
||||
~~~java
|
||||
FlatLightLaf.setup();
|
||||
|
||||
Buzz
|
||||
----
|
||||
|
||||
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
||||
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||
// create UI here...
|
||||
~~~
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
For more information and documentation visit
|
||||
[FlatLaf Home](https://www.formdev.com/flatlaf/)
|
||||
[FlatLaf Home](https://www.formdev.com/flatlaf/):
|
||||
|
||||
- [Themes](https://www.formdev.com/flatlaf/themes/)
|
||||
- [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
|
||||
----
|
||||
|
||||
- [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/)
|
||||
|
||||
|
||||
Applications using FlatLaf
|
||||
--------------------------
|
||||
|
||||
### 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)
|
||||
(**commercial**) - the powerful multi-platform Java installer builder
|
||||
-  [DbVisualizer](https://www.dbvis.com/)
|
||||
(**commercial**) - the universal database tool for developers, analysts and
|
||||
DBAs
|
||||
-  [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)
|
||||
(**commercial**) - the leading software for web security testing
|
||||
- 
|
||||
[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
|
||||
- [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**)
|
||||
|
||||
### 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
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- [MEKA](https://github.com/Waikato/meka) - multi-label classifiers and
|
||||
evaluation procedures using the Weka machine learning framework
|
||||
|
||||
107
build.gradle.kts
107
build.gradle.kts
@@ -14,16 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "0.45"
|
||||
val developmentVersion = "0.46-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
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,19 +42,15 @@ 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()
|
||||
|
||||
|
||||
extra["bintray.user"] = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
|
||||
extra["bintray.key"] = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
|
||||
|
||||
// if true, do not upload to bintray
|
||||
extra["bintray.dryRun"] = false
|
||||
|
||||
// if true, uploaded artifacts are visible to all
|
||||
// if false, only visible to owner when logged into bintray
|
||||
extra["bintray.publish"] = false
|
||||
|
||||
plugins {
|
||||
alias( libs.plugins.errorprone ) apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
tasks {
|
||||
@@ -58,18 +59,86 @@ allprojects {
|
||||
targetCompatibility = "1.8"
|
||||
|
||||
options.encoding = "ISO-8859-1"
|
||||
options.isDeprecation = false
|
||||
}
|
||||
|
||||
withType<Jar>().configureEach {
|
||||
// manifest for all created JARs
|
||||
manifest.attributes(mapOf(
|
||||
manifest.attributes(
|
||||
"Implementation-Vendor" to "FormDev Software GmbH",
|
||||
"Implementation-Copyright" to "Copyright (C) ${java.time.LocalDate.now().year} FormDev Software GmbH. All rights reserved.",
|
||||
"Implementation-Version" to project.version))
|
||||
"Implementation-Copyright" to "Copyright (C) 2019-${java.time.LocalDate.now().year} FormDev Software GmbH. All rights reserved.",
|
||||
"Implementation-Version" to project.version
|
||||
)
|
||||
|
||||
// add META-INF/LICENSE to all created JARs
|
||||
from("${rootDir}/LICENSE") {
|
||||
into("META-INF")
|
||||
from( "${rootDir}/LICENSE" ) {
|
||||
into( "META-INF" )
|
||||
}
|
||||
}
|
||||
|
||||
withType<Javadoc>().configureEach {
|
||||
options {
|
||||
this as StandardJavadocDocletOptions
|
||||
|
||||
title = "${project.name} $version"
|
||||
header = title
|
||||
isUse = true
|
||||
tags = listOf( "uiDefault", "clientProperty" )
|
||||
addStringOption( "Xdoclint:all,-missing", "-Xdoclint:all,-missing" )
|
||||
links( "https://docs.oracle.com/en/java/javase/11/docs/api/" )
|
||||
}
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,5 @@ plugins {
|
||||
|
||||
// required for kotlin-dsl or embedded-kotlin plugins
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// NOTE: keep plugin versions in sync with settings.gradle.kts
|
||||
|
||||
// "com.jfrog.bintray" plugin
|
||||
implementation( "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4" )
|
||||
|
||||
// "com.jfrog.artifactory" plugin
|
||||
implementation( "org.jfrog.buildinfo:build-info-extractor-gradle:4.13.0" )
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@@ -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" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,10 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
add( "java9Implementation", sourceSets.main.get().output )
|
||||
}
|
||||
|
||||
tasks {
|
||||
named<JavaCompile>( "compileJava9Java" ) {
|
||||
sourceCompatibility = "9"
|
||||
|
||||
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" )
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,17 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
sourceSets {
|
||||
create( "module-info" ) {
|
||||
java {
|
||||
// include "src/main/java" here to get compile errors if classes are
|
||||
// include "src/main/java" and "src/main/java9" here to get compile errors if classes are
|
||||
// used from other modules that are not specified in module dependencies
|
||||
setSrcDirs( listOf( "src/main/module-info", "src/main/java" ) )
|
||||
setSrcDirs( listOf( "src/main/module-info", "src/main/java", "src/main/java9" ) )
|
||||
|
||||
// exclude Java 8 source file if an equally named Java 9+ source file exists
|
||||
exclude {
|
||||
if( it.isDirectory )
|
||||
return@exclude false
|
||||
val java9file = file( "${projectDir}/src/main/java9/${it.path}" )
|
||||
java9file.exists() && java9file != it.file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,16 +56,13 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
dependsOn( extension.paths )
|
||||
|
||||
options.compilerArgs.add( "--module-path" )
|
||||
options.compilerArgs.add( configurations.runtimeClasspath.get().asPath )
|
||||
options.compilerArgs.add( configurations.runtimeClasspath.get().asPath
|
||||
+ File.pathSeparator + configurations.compileClasspath.get().asPath )
|
||||
}
|
||||
|
||||
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" )
|
||||
@@ -26,8 +29,7 @@ val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
||||
|
||||
plugins {
|
||||
`maven-publish`
|
||||
id( "com.jfrog.bintray" )
|
||||
id( "com.jfrog.artifactory" )
|
||||
signing
|
||||
}
|
||||
|
||||
publishing {
|
||||
@@ -42,75 +44,89 @@ 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 {
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
connection = "scm:git:git://github.com/JFormDesigner/FlatLaf.git"
|
||||
url = "https://github.com/JFormDesigner/FlatLaf"
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
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
|
||||
} )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "OSSRH"
|
||||
|
||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||
|
||||
credentials {
|
||||
// get from gradle.properties
|
||||
val ossrhUsername: String? by project
|
||||
val ossrhPassword: String? by project
|
||||
|
||||
username = System.getenv( "OSSRH_USERNAME" ) ?: ossrhUsername
|
||||
password = System.getenv( "OSSRH_PASSWORD" ) ?: ossrhPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = rootProject.extra["bintray.user"] as String?
|
||||
key = rootProject.extra["bintray.key"] as String?
|
||||
signing {
|
||||
// get from gradle.properties
|
||||
val signingKey: String? by project
|
||||
val signingPassword: String? by project
|
||||
|
||||
setPublications( "maven" )
|
||||
val key = System.getenv( "SIGNING_KEY" ) ?: signingKey
|
||||
val password = System.getenv( "SIGNING_PASSWORD" ) ?: signingPassword
|
||||
|
||||
with( pkg ) {
|
||||
repo = "flatlaf"
|
||||
afterEvaluate {
|
||||
this@with.name = extension.artifactId
|
||||
}
|
||||
setLicenses( "Apache-2.0" )
|
||||
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
|
||||
useInMemoryPgpKeys( key, password )
|
||||
sign( publishing.publications["maven"] )
|
||||
}
|
||||
|
||||
with( version ) {
|
||||
name = project.version.toString()
|
||||
}
|
||||
// disable signing of snapshots
|
||||
tasks.withType<Sign>().configureEach {
|
||||
onlyIf { rootProject.hasProperty( "release" ) }
|
||||
}
|
||||
|
||||
publish = rootProject.extra["bintray.publish"] as Boolean
|
||||
dryRun = rootProject.extra["bintray.dryRun"] as Boolean
|
||||
// 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'." )
|
||||
}
|
||||
}
|
||||
|
||||
artifactory {
|
||||
setContextUrl( "https://oss.jfrog.org" )
|
||||
|
||||
publish( closureOf<org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig> {
|
||||
repository( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
setProperty( "repoKey", "oss-snapshot-local" )
|
||||
setProperty( "username", rootProject.extra["bintray.user"] as String? )
|
||||
setProperty( "password", rootProject.extra["bintray.key"] as String? )
|
||||
} )
|
||||
|
||||
defaults( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
invokeMethod( "publications", "maven" )
|
||||
setProperty( "publishArtifacts", true )
|
||||
setProperty( "publishPom", true )
|
||||
} )
|
||||
} )
|
||||
|
||||
resolve( delegateClosureOf<org.jfrog.gradle.plugin.artifactory.dsl.ResolverConfig> {
|
||||
setProperty( "repoKey", "jcenter" )
|
||||
} )
|
||||
}
|
||||
|
||||
26
buildSrc/src/main/kotlin/flatlaf-toolchain.gradle.kts
Normal file
26
buildSrc/src/main/kotlin/flatlaf-toolchain.gradle.kts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||
if( !toolchainJavaVersion.isNullOrEmpty() ) {
|
||||
java.toolchain {
|
||||
languageVersion = JavaLanguageVersion.of( toolchainJavaVersion )
|
||||
}
|
||||
}
|
||||
2
flatlaf-core/.settings/org.eclipse.core.resources.prefs
Normal file
2
flatlaf-core/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=ISO-8859-1
|
||||
@@ -14,43 +14,130 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Flatlaf_publish_gradle.NativeArtifact
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`flatlaf-toolchain`
|
||||
`flatlaf-module-info`
|
||||
`flatlaf-java9`
|
||||
`flatlaf-publish`
|
||||
}
|
||||
|
||||
val sigtest = configurations.create( "sigtest" )
|
||||
|
||||
dependencies {
|
||||
testImplementation( libs.junit )
|
||||
testRuntimeOnly( libs.junit.launcher )
|
||||
|
||||
// https://github.com/jtulach/netbeans-apitest
|
||||
sigtest( libs.sigtest )
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
tasks {
|
||||
compileJava {
|
||||
// generate JNI headers
|
||||
options.headerOutputDirectory = layout.buildDirectory.dir( "generated/jni-headers" )
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
archiveBaseName = "flatlaf"
|
||||
|
||||
doLast {
|
||||
ReorderJarEntries.reorderJarEntries( outputs.files.singleFile );
|
||||
}
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options {
|
||||
this as StandardJavadocDocletOptions
|
||||
use( true )
|
||||
tags = listOf( "uiDefault", "clientProperty" )
|
||||
addStringOption( "Xdoclint:all,-missing", "-Xdoclint:all,-missing" )
|
||||
named<Jar>( "sourcesJar" ) {
|
||||
archiveBaseName = "flatlaf"
|
||||
}
|
||||
|
||||
named<Jar>( "javadocJar" ) {
|
||||
archiveBaseName = "flatlaf"
|
||||
}
|
||||
|
||||
register<Zip>( "jarNoNatives" ) {
|
||||
group = "build"
|
||||
dependsOn( "jar" )
|
||||
|
||||
archiveBaseName = "flatlaf"
|
||||
archiveClassifier = "no-natives"
|
||||
archiveExtension = "jar"
|
||||
destinationDirectory = layout.buildDirectory.dir( "libs" )
|
||||
|
||||
from( zipTree( jar.get().archiveFile.get().asFile ) )
|
||||
exclude( "com/formdev/flatlaf/natives/**" )
|
||||
}
|
||||
|
||||
withType<AbstractPublishToMaven>().configureEach {
|
||||
dependsOn( "jarNoNatives" )
|
||||
}
|
||||
|
||||
withType<Sign>().configureEach {
|
||||
dependsOn( "jarNoNatives" )
|
||||
}
|
||||
|
||||
check {
|
||||
dependsOn( "sigtestCheck" )
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 )
|
||||
jvmArgs( listOf( "--add-opens", "java.desktop/javax.swing.plaf.basic=ALL-UNNAMED" ) )
|
||||
}
|
||||
|
||||
register( "sigtestGenerate" ) {
|
||||
group = "verification"
|
||||
dependsOn( "jar" )
|
||||
|
||||
doLast {
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"(
|
||||
"name" to "sigtest",
|
||||
"classname" to "org.netbeans.apitest.Sigtest",
|
||||
"classpath" to sigtest.asPath )
|
||||
|
||||
"sigtest"(
|
||||
"action" to "generate",
|
||||
"fileName" to "${project.name}-sigtest.txt",
|
||||
"classpath" to jar.get().outputs.files.asPath,
|
||||
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.themes,com.formdev.flatlaf.util",
|
||||
"version" to version,
|
||||
"release" to "1.8", // Java version
|
||||
"failonerror" to "true" )
|
||||
}
|
||||
}
|
||||
isFailOnError = false
|
||||
}
|
||||
|
||||
named<Jar>("sourcesJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
}
|
||||
register( "sigtestCheck" ) {
|
||||
group = "verification"
|
||||
dependsOn( "jar" )
|
||||
|
||||
named<Jar>("javadocJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
doLast {
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"(
|
||||
"name" to "sigtest",
|
||||
"classname" to "org.netbeans.apitest.Sigtest",
|
||||
"classpath" to sigtest.asPath )
|
||||
|
||||
"sigtest"(
|
||||
"action" to "check",
|
||||
"fileName" to "${project.name}-sigtest.txt",
|
||||
"classpath" to jar.get().outputs.files.asPath,
|
||||
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.util",
|
||||
"version" to version,
|
||||
"release" to "1.8", // Java version
|
||||
"failonerror" to "true" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,4 +145,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" ),
|
||||
)
|
||||
}
|
||||
|
||||
1245
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
1245
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* A Flat LaF that has a dark color scheme and looks like Darcula LaF.
|
||||
* <p>
|
||||
@@ -29,10 +31,30 @@ public class FlatDarculaLaf
|
||||
{
|
||||
public static final String NAME = "FlatLaf Darcula";
|
||||
|
||||
public static boolean install() {
|
||||
return install( new 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() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #setup()} instead; this method will be removed in a future version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean install() {
|
||||
return setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, FlatDarculaLaf.class );
|
||||
}
|
||||
|
||||
@@ -33,9 +33,19 @@ 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() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #setup()} instead; this method will be removed in a future version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean install() {
|
||||
return install( new FlatDarkLaf() );
|
||||
return setup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -42,13 +42,16 @@ class FlatInputMaps
|
||||
}
|
||||
|
||||
private static void initBasicInputMaps( UIDefaults defaults ) {
|
||||
defaults.put( "Button.focusInputMap", new UIDefaults.LazyInputMap( new Object[] {
|
||||
"SPACE", "pressed",
|
||||
"released SPACE", "released"
|
||||
} ) );
|
||||
if( SystemInfo.isMacOS ) {
|
||||
defaults.put( "Button.focusInputMap", new UIDefaults.LazyInputMap( new Object[] {
|
||||
"SPACE", "pressed",
|
||||
"released SPACE", "released"
|
||||
} ) );
|
||||
}
|
||||
|
||||
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" ),
|
||||
@@ -68,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 ) {
|
||||
@@ -594,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
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* A Flat LaF that has a light color scheme and looks like IntelliJ LaF.
|
||||
* <p>
|
||||
@@ -29,10 +31,30 @@ public class FlatIntelliJLaf
|
||||
{
|
||||
public static final String NAME = "FlatLaf IntelliJ";
|
||||
|
||||
public static boolean install() {
|
||||
return install( new 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() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #setup()} instead; this method will be removed in a future version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean install() {
|
||||
return setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, FlatIntelliJLaf.class );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,9 +33,19 @@ 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() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #setup()} instead; this method will be removed in a future version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean install() {
|
||||
return install( new FlatLightLaf() );
|
||||
return setup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,14 +21,17 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
|
||||
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
||||
|
||||
/**
|
||||
* A Flat LaF that is able to load UI defaults from properties passed to the constructor.
|
||||
* <p>
|
||||
* Specify the base theme in the properties with {@code @baseTheme=<baseTheme>}.
|
||||
* Allowed values for {@code <baseTheme>} are {@code light} (the default), {@code dark},
|
||||
* {@code intellij} or {@code darcula}.
|
||||
* {@code intellij}, {@code darcula}, {@code maclight} or {@code macdark}.
|
||||
* <p>
|
||||
* The properties are applied after loading the base theme and may overwrite base properties.
|
||||
* All features of FlatLaf properties files are available.
|
||||
@@ -70,7 +73,8 @@ public class FlatPropertiesLaf
|
||||
this.properties = properties;
|
||||
|
||||
baseTheme = properties.getProperty( "@baseTheme", "light" );
|
||||
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme );
|
||||
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme ) ||
|
||||
"macdark".equalsIgnoreCase( baseTheme );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +100,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 );
|
||||
@@ -115,6 +119,16 @@ public class FlatPropertiesLaf
|
||||
lafClasses.add( FlatDarkLaf.class );
|
||||
lafClasses.add( FlatDarculaLaf.class );
|
||||
break;
|
||||
|
||||
case "maclight":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
lafClasses.add( FlatMacLightLaf.class );
|
||||
break;
|
||||
|
||||
case "macdark":
|
||||
lafClasses.add( FlatDarkLaf.class );
|
||||
lafClasses.add( FlatMacDarkLaf.class );
|
||||
break;
|
||||
}
|
||||
return lafClasses;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Defines/documents own system properties used in FlatLaf.
|
||||
@@ -35,6 +35,8 @@ 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 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>
|
||||
*/
|
||||
String UI_SCALE = "flatlaf.uiScale";
|
||||
@@ -47,6 +49,17 @@ public interface FlatSystemProperties
|
||||
*/
|
||||
String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled";
|
||||
|
||||
/**
|
||||
* Specifies whether values smaller than 100% are allowed for the user scale factor
|
||||
* (see {@link UIScale#getUserScaleFactor()}).
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> {@code false}
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.uiScale.allowScaleDown";
|
||||
|
||||
/**
|
||||
* Specifies whether Ubuntu font should be used on Ubuntu Linux.
|
||||
* By default, if not running in a JetBrains Runtime, the Liberation Sans font
|
||||
@@ -58,11 +71,18 @@ public interface FlatSystemProperties
|
||||
String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont";
|
||||
|
||||
/**
|
||||
* Specifies whether custom look and feel window decorations should be used
|
||||
* Specifies whether native window decorations should be used
|
||||
* when creating {@code JFrame} or {@code JDialog}.
|
||||
* <p>
|
||||
* If this system property is set, FlatLaf invokes {@link JFrame#setDefaultLookAndFeelDecorated(boolean)}
|
||||
* and {@link JDialog#setDefaultLookAndFeelDecorated(boolean)} on LaF initialization.
|
||||
* Setting this to {@code true} forces using native window decorations
|
||||
* even if they are not enabled by the application.<br>
|
||||
* Setting this to {@code false} disables using native window decorations.
|
||||
* <p>
|
||||
* This system property has higher priority than client property
|
||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||
* UI default {@code TitlePane.useWindowDecorations}.
|
||||
* <p>
|
||||
* (requires Windows 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -73,22 +93,37 @@ 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 true} forces using JetBrains Runtime custom window decorations
|
||||
* even if they are not enabled by the application.
|
||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||
* Then FlatLaf native window decorations are used.
|
||||
* <p>
|
||||
* (requires Windows 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";
|
||||
|
||||
/**
|
||||
* Specifies whether menubar is embedded into custom window decorations.
|
||||
* Specifies whether the menu bar is embedded into the window title pane
|
||||
* if window decorations are enabled.
|
||||
* <p>
|
||||
* Setting this to {@code true} forces embedding.<br>
|
||||
* Setting this to {@code false} disables embedding.
|
||||
* <p>
|
||||
* This system property has higher priority than client property
|
||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||
* <p>
|
||||
* (requires Windows 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> {@code true}
|
||||
* <strong>Default</strong> none
|
||||
*/
|
||||
String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded";
|
||||
|
||||
@@ -100,6 +135,18 @@ public interface FlatSystemProperties
|
||||
*/
|
||||
String ANIMATION = "flatlaf.animation";
|
||||
|
||||
/**
|
||||
* Specifies whether native rounded popup borders should be used (if supported by operating system).
|
||||
* <p>
|
||||
* (requires Windows 11 or macOS)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> {@code true}; except on macOS 14.4+ where it is {@code false}
|
||||
*
|
||||
* @since 3.5.2
|
||||
*/
|
||||
String USE_ROUNDED_POPUP_BORDER = "flatlaf.useRoundedPopupBorder";
|
||||
|
||||
/**
|
||||
* Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens.
|
||||
* <p>
|
||||
@@ -108,6 +155,77 @@ 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";
|
||||
|
||||
/**
|
||||
* Specifies whether safe triangle is used to improve usability of submenus.
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> {@code true}
|
||||
*
|
||||
* @since 3.5.1
|
||||
*/
|
||||
String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle";
|
||||
|
||||
/**
|
||||
* Checks whether a system property is set and returns {@code true} if its value
|
||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||
|
||||
@@ -16,25 +16,32 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
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.logging.Level;
|
||||
import java.util.Map.Entry;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import com.formdev.flatlaf.json.Json;
|
||||
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.
|
||||
@@ -56,28 +63,40 @@ public class IntelliJTheme
|
||||
public final boolean dark;
|
||||
public final String author;
|
||||
|
||||
private final Map<String, String> colors;
|
||||
private final Map<String, Object> ui;
|
||||
private final Map<String, Object> icons;
|
||||
private final boolean isMaterialUILite;
|
||||
|
||||
private Map<String, String> colors;
|
||||
private Map<String, Object> ui;
|
||||
private Map<String, Object> icons;
|
||||
|
||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
||||
|
||||
/**
|
||||
* Loads a IntelliJ .theme.json file from the given input stream,
|
||||
* creates a Laf instance for it and installs it.
|
||||
* creates a Laf instance for it and sets it up.
|
||||
*
|
||||
* The input stream is automatically closed.
|
||||
* Using a buffered input stream is not necessary.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean install( InputStream in ) {
|
||||
public static boolean setup( InputStream in ) {
|
||||
try {
|
||||
return FlatLaf.install( createLaf( in ) );
|
||||
return FlatLaf.setup( createLaf( in ) );
|
||||
} catch( Exception ex ) {
|
||||
FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: Failed to load IntelliJ theme", ex );
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #setup(InputStream)} instead; this method will be removed in a future version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean install( InputStream in ) {
|
||||
return setup( in );
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a IntelliJ .theme.json file from the given input stream and
|
||||
* creates a Laf instance for it.
|
||||
@@ -119,6 +138,8 @@ public class IntelliJTheme
|
||||
dark = Boolean.parseBoolean( (String) json.get( "dark" ) );
|
||||
author = (String) json.get( "author" );
|
||||
|
||||
isMaterialUILite = author.equals( "Mallowigi" );
|
||||
|
||||
colors = (Map<String, String>) json.get( "colors" );
|
||||
ui = (Map<String, Object>) json.get( "ui" );
|
||||
icons = (Map<String, Object>) json.get( "icons" );
|
||||
@@ -148,15 +169,23 @@ 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" );
|
||||
defaults.put( "Button.disabledBackground", panelBackground );
|
||||
defaults.put( "ToggleButton.disabledBackground", panelBackground );
|
||||
|
||||
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||
// fix Button borders
|
||||
copyIfNotSet( defaults, "Button.focusedBorderColor", "Component.focusedBorderColor", uiKeys );
|
||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
|
||||
// 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 )
|
||||
@@ -171,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" ) );
|
||||
@@ -180,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" ) )
|
||||
@@ -205,30 +254,103 @@ public class IntelliJTheme
|
||||
if( !uiKeys.contains( "ToggleButton.foreground" ) && uiKeys.contains( "Button.foreground" ) )
|
||||
defaults.put( "ToggleButton.foreground", defaults.get( "Button.foreground" ) );
|
||||
|
||||
// fix DesktopPane background (use Panel.background and make it 5% darker/lighter)
|
||||
Color desktopBackgroundBase = defaults.getColor( "Panel.background" );
|
||||
Color desktopBackground = ColorFunctions.applyFunctions( desktopBackgroundBase,
|
||||
new ColorFunctions.HSLIncreaseDecrease( 2, dark, 5, false, true ) );
|
||||
defaults.put( "Desktop.background", new ColorUIResource( desktopBackground ) );
|
||||
|
||||
// fix List and Table background colors in Material UI Lite themes
|
||||
if( isMaterialUILite ) {
|
||||
defaults.put( "List.background", defaults.get( "Tree.background" ) );
|
||||
defaults.put( "Table.background", defaults.get( "Tree.background" ) );
|
||||
}
|
||||
|
||||
// limit tree row height
|
||||
int rowHeight = defaults.getInt( "Tree.rowHeight" );
|
||||
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 ) {
|
||||
// search for theme specific UI defaults keys
|
||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && ((String)key).startsWith( "[" ) )
|
||||
if( key instanceof String && ((String)key).startsWith( "[" ) && !((String)key).startsWith( "[style]" ) )
|
||||
themeSpecificKeys.add( (String) key );
|
||||
}
|
||||
|
||||
// remove theme specific UI defaults and remember only those for current theme
|
||||
Map<Object, Object> themeSpecificDefaults = new HashMap<>();
|
||||
String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
|
||||
String currentThemeAndAuthorPrefix = '[' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + ']';
|
||||
String currentAuthorPrefix = "[author-" + author.replace( ' ', '_' ) + ']';
|
||||
String allThemesPrefix = "[*]";
|
||||
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, allThemesPrefix };
|
||||
for( String key : themeSpecificKeys ) {
|
||||
Object value = defaults.remove( key );
|
||||
if( key.startsWith( currentThemePrefix ) )
|
||||
themeSpecificDefaults.put( key.substring( currentThemePrefix.length() ), value );
|
||||
for( String prefix : prefixes ) {
|
||||
if( key.startsWith( prefix ) ) {
|
||||
themeSpecificDefaults.put( key.substring( prefix.length() ), value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return themeSpecificDefaults;
|
||||
@@ -245,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 );
|
||||
@@ -260,24 +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
|
||||
boolean isMaterialUILite = author.equals( "Mallowigi" );
|
||||
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
|
||||
@@ -300,9 +445,9 @@ public class IntelliJTheme
|
||||
|
||||
// parse value
|
||||
try {
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr );
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr, null );
|
||||
} catch( RuntimeException ex ) {
|
||||
UIDefaultsLoader.logParseError( Level.CONFIG, key, valueStr, ex );
|
||||
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
||||
return; // ignore invalid value
|
||||
}
|
||||
}
|
||||
@@ -322,6 +467,11 @@ 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( "TabbedPane.focusColor" ) )
|
||||
continue;
|
||||
|
||||
if( k instanceof String ) {
|
||||
// support replacing of mapped keys
|
||||
// (e.g. set ComboBox.buttonEditableBackground to *.background
|
||||
@@ -377,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".
|
||||
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
||||
* 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 ) {
|
||||
@@ -402,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" );
|
||||
|
||||
@@ -427,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
|
||||
@@ -453,44 +600,104 @@ public class IntelliJTheme
|
||||
}
|
||||
}
|
||||
|
||||
// remove hover and pressed colors
|
||||
// update hover, pressed and focused colors
|
||||
if( checkboxModified ) {
|
||||
// for non-filled checkbox/radiobutton used in dark themes
|
||||
defaults.remove( "CheckBox.icon.focusWidth" );
|
||||
defaults.remove( "CheckBox.icon.hoverBorderColor" );
|
||||
defaults.remove( "CheckBox.icon.focusedBackground" );
|
||||
defaults.remove( "CheckBox.icon.hoverBackground" );
|
||||
defaults.remove( "CheckBox.icon.pressedBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedFocusedBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedHoverBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedPressedBackground" );
|
||||
defaults.put( "CheckBox.icon.hoverBorderColor", defaults.get( "CheckBox.icon.focusedBorderColor" ) );
|
||||
|
||||
// for filled checkbox/radiobutton used in light themes
|
||||
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
||||
defaults.remove( "CheckBox.icon[filled].hoverBorderColor" );
|
||||
defaults.remove( "CheckBox.icon[filled].focusedBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].hoverBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].pressedBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].selectedFocusedBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].selectedHoverBackground" );
|
||||
defaults.remove( "CheckBox.icon[filled].selectedPressedBackground" );
|
||||
defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
||||
defaults.put( "CheckBox.icon[filled].focusedSelectedBackground", defaults.get( "CheckBox.icon[filled].selectedBackground" ) );
|
||||
|
||||
if( dark ) {
|
||||
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
||||
// radioFocused.svg and radioSelectedFocused.svg
|
||||
// use opacity=".65" for the border
|
||||
// --> add alpha to focused border colors
|
||||
String[] focusedBorderColorKeys = {
|
||||
"CheckBox.icon.focusedBorderColor",
|
||||
"CheckBox.icon.focusedSelectedBorderColor",
|
||||
"CheckBox.icon[filled].focusedBorderColor",
|
||||
"CheckBox.icon[filled].focusedSelectedBorderColor",
|
||||
};
|
||||
for( String key : focusedBorderColorKeys ) {
|
||||
Color color = defaults.getColor( key );
|
||||
if( color != null ) {
|
||||
defaults.put( key, new ColorUIResource( new Color(
|
||||
(color.getRGB() & 0xffffff) | 0xa6000000, true ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyIfNotSet( UIDefaults defaults, String destKey, String srcKey, Set<String> uiKeys ) {
|
||||
if( !uiKeys.contains( destKey ) )
|
||||
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" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
||||
uiKeyCopying.put( "ComboBox.buttonSeparatorColor", "Component.borderColor" );
|
||||
uiKeyCopying.put( "ComboBox.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
||||
|
||||
// Component
|
||||
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
|
||||
@@ -507,6 +714,7 @@ public class IntelliJTheme
|
||||
uiKeyCopying.put( "CheckBoxMenuItem.margin", "MenuItem.margin" );
|
||||
uiKeyCopying.put( "RadioButtonMenuItem.margin", "MenuItem.margin" );
|
||||
uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" );
|
||||
uiKeyCopying.put( "MenuItem.underlineSelectionColor", "TabbedPane.underlineColor" );
|
||||
|
||||
// IDEA uses List.selectionBackground also for menu selection
|
||||
uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" );
|
||||
@@ -535,6 +743,15 @@ public class IntelliJTheme
|
||||
uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" );
|
||||
uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" );
|
||||
|
||||
// Spinner
|
||||
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" );
|
||||
@@ -559,7 +776,7 @@ public class IntelliJTheme
|
||||
checkboxKeyMapping.put( "Checkbox.Background.Selected", "CheckBox.icon.selectedBackground" );
|
||||
checkboxKeyMapping.put( "Checkbox.Border.Selected", "CheckBox.icon.selectedBorderColor" );
|
||||
checkboxKeyMapping.put( "Checkbox.Foreground.Selected", "CheckBox.icon.checkmarkColor" );
|
||||
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.selectedFocusedBorderColor" );
|
||||
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.focusedSelectedBorderColor" );
|
||||
|
||||
checkboxDuplicateColors.put( "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
||||
checkboxDuplicateColors.put( "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
||||
|
||||
@@ -17,18 +17,23 @@
|
||||
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 java.util.logging.Level;
|
||||
import javax.swing.text.StyleContext;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -54,24 +59,38 @@ class LinuxFontPolicy
|
||||
|
||||
String family = "";
|
||||
int style = Font.PLAIN;
|
||||
int size = 10;
|
||||
double dsize = 10;
|
||||
|
||||
// parse pango font description
|
||||
// see https://developer.gnome.org/pango/1.46/pango-Fonts.html#pango-font-description-from-string
|
||||
StringTokenizer st = new StringTokenizer( (String) fontName );
|
||||
while( st.hasMoreTokens() ) {
|
||||
String word = st.nextToken();
|
||||
|
||||
if( word.equalsIgnoreCase( "italic" ) )
|
||||
// remove trailing ',' (e.g. in "Ubuntu Condensed, 11" or "Ubuntu Condensed, Bold 11")
|
||||
if( word.endsWith( "," ) )
|
||||
word = word.substring( 0, word.length() - 1 ).trim();
|
||||
|
||||
String lword = word.toLowerCase( Locale.ENGLISH );
|
||||
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
|
||||
style |= Font.ITALIC;
|
||||
else if( word.equalsIgnoreCase( "bold" ) )
|
||||
else if( lword.equals( "bold" ) )
|
||||
style |= Font.BOLD;
|
||||
else if( Character.isDigit( word.charAt( 0 ) ) ) {
|
||||
try {
|
||||
size = Integer.parseInt( word );
|
||||
dsize = Double.parseDouble( word );
|
||||
} catch( NumberFormatException ex ) {
|
||||
// ignore
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
// remove '-' from "Semi-Bold", "Extra-Light", etc
|
||||
if( lword.startsWith( "semi-" ) || lword.startsWith( "demi-" ) )
|
||||
word = word.substring( 0, 4 ) + word.substring( 5 );
|
||||
else if( lword.startsWith( "extra-" ) || lword.startsWith( "ultra-" ) )
|
||||
word = word.substring( 0, 5 ) + word.substring( 6 );
|
||||
|
||||
family = family.isEmpty() ? word : (family + ' ' + word);
|
||||
}
|
||||
}
|
||||
|
||||
// Ubuntu font is rendered poorly (except if running in JetBrains VM)
|
||||
@@ -82,26 +101,58 @@ class LinuxFontPolicy
|
||||
family = "Liberation Sans";
|
||||
|
||||
// scale font size
|
||||
double dsize = size * getGnomeFontScale();
|
||||
size = (int) (dsize + 0.5);
|
||||
dsize *= getGnomeFontScale();
|
||||
int size = (int) (dsize + 0.5);
|
||||
if( size < 1 )
|
||||
size = 1;
|
||||
|
||||
// handle logical font names
|
||||
String logicalFamily = mapFcName( family.toLowerCase() );
|
||||
String logicalFamily = mapFcName( family.toLowerCase( Locale.ENGLISH ) );
|
||||
if( logicalFamily != null )
|
||||
family = logicalFamily;
|
||||
|
||||
return createFont( family, style, size, dsize );
|
||||
return createFontEx( family, style, size );
|
||||
}
|
||||
|
||||
private static Font createFont( String family, int style, int size, double dsize ) {
|
||||
Font font = FlatLaf.createCompositeFont( family, style, size );
|
||||
/**
|
||||
* Create a font for the given family, style and size.
|
||||
* If the font family does not match any font on the system,
|
||||
* then the last word (usually a font weight) from the family name is removed and tried again.
|
||||
* E.g. family 'URW Bookman Light' is not found, but 'URW Bookman' is found.
|
||||
* If still not found, then font of family 'Dialog' is returned.
|
||||
*/
|
||||
private static Font createFontEx( String family, int style, int size ) {
|
||||
for(;;) {
|
||||
Font font = FlatLaf.createCompositeFont( family, style, size );
|
||||
|
||||
// set font size in floating points
|
||||
font = font.deriveFont( style, (float) dsize );
|
||||
if( Font.DIALOG.equals( family ) )
|
||||
return font;
|
||||
|
||||
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 FlatLaf.createCompositeFont( Font.DIALOG, style, size );
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
// find last word in family
|
||||
int index = family.lastIndexOf( ' ' );
|
||||
if( index < 0 )
|
||||
return FlatLaf.createCompositeFont( Font.DIALOG, style, size );
|
||||
|
||||
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
||||
String lastWord = family.substring( index + 1 ).toLowerCase( Locale.ENGLISH );
|
||||
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
|
||||
style |= Font.BOLD;
|
||||
|
||||
// remove last word from family and try again
|
||||
family = family.substring( 0, index );
|
||||
}
|
||||
}
|
||||
|
||||
private static double getGnomeFontScale() {
|
||||
@@ -113,7 +164,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 )
|
||||
@@ -140,10 +191,10 @@ class LinuxFontPolicy
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default font for KDE for KDE configuration files.
|
||||
* Gets the default font for KDE from KDE configuration files.
|
||||
*
|
||||
* The Swing fonts are not updated when the user changes system font size
|
||||
* (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
|
||||
@@ -172,7 +223,7 @@ class LinuxFontPolicy
|
||||
if( "1".equals( strs.get( 5 ) ) )
|
||||
style |= Font.ITALIC;
|
||||
} catch( RuntimeException ex ) {
|
||||
FlatLaf.LOG.log( Level.CONFIG, "FlatLaf: Failed to parse 'font=" + generalFont + "'.", ex );
|
||||
LoggingFacade.INSTANCE.logConfig( "FlatLaf: Failed to parse 'font=" + generalFont + "'.", ex );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +237,7 @@ class LinuxFontPolicy
|
||||
if( dpi < 50 )
|
||||
dpi = 50;
|
||||
} catch( NumberFormatException ex ) {
|
||||
FlatLaf.LOG.log( Level.CONFIG, "FlatLaf: Failed to parse 'forceFontDPI=" + forceFontDPI + "'.", ex );
|
||||
LoggingFacade.INSTANCE.logConfig( "FlatLaf: Failed to parse 'forceFontDPI=" + forceFontDPI + "'.", ex );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,9 +248,10 @@ class LinuxFontPolicy
|
||||
if( size < 1 )
|
||||
size = 1;
|
||||
|
||||
return createFont( family, style, size, dsize );
|
||||
return FlatLaf.createCompositeFont( family, style, size );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone
|
||||
private static List<String> readConfig( String filename ) {
|
||||
File userHome = new File( System.getProperty( "user.home" ) );
|
||||
|
||||
@@ -220,12 +272,14 @@ 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 ) {
|
||||
FlatLaf.LOG.log( Level.CONFIG, "FlatLaf: Failed to read '" + filename + "'.", ex );
|
||||
LoggingFacade.INSTANCE.logConfig( "FlatLaf: Failed to read '" + filename + "'.", ex );
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
@@ -264,6 +318,9 @@ class LinuxFontPolicy
|
||||
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
||||
*/
|
||||
private static boolean isSystemScaling() {
|
||||
if( GraphicsEnvironment.isHeadless() )
|
||||
return true;
|
||||
|
||||
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||
return UIScale.getSystemScaleFactor( gc ) > 1;
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenu;
|
||||
@@ -137,10 +138,17 @@ class MnemonicHandler
|
||||
// get menu bar and first menu
|
||||
Component c = e.getComponent();
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
Window window = (rootPane != null) ? SwingUtilities.getWindowAncestor( rootPane ) : null;
|
||||
JMenuBar menuBar = (rootPane != null) ? rootPane.getJMenuBar() : null;
|
||||
if( menuBar == null && window instanceof JFrame )
|
||||
menuBar = ((JFrame)window).getJMenuBar();
|
||||
if( menuBar == null ) {
|
||||
// get menu bar from frame/dialog because there
|
||||
// may be multiple nested root panes in a frame/dialog
|
||||
// (e.g. each internal frame has its own root pane)
|
||||
Window window = SwingUtilities.getWindowAncestor( c );
|
||||
if( window instanceof JFrame )
|
||||
menuBar = ((JFrame)window).getJMenuBar();
|
||||
else if( window instanceof JDialog )
|
||||
menuBar = ((JDialog)window).getJMenuBar();
|
||||
}
|
||||
JMenu firstMenu = (menuBar != null) ? menuBar.getMenu( 0 ) : null;
|
||||
|
||||
// select first menu and show mnemonics
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.MouseInfo;
|
||||
import java.awt.Point;
|
||||
import java.awt.PointerInfo;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.RootPaneContainer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
/**
|
||||
* Improves usability of submenus by using a
|
||||
* <a href="https://height.app/blog/guide-to-build-context-menus#safe-triangle">safe triangle</a>
|
||||
* to avoid that the submenu closes while the user moves the mouse to it.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class SubMenuUsabilityHelper
|
||||
implements ChangeListener
|
||||
{
|
||||
private static final String KEY_USE_SAFE_TRIANGLE = "Menu.useSafeTriangle";
|
||||
private static final String KEY_SHOW_SAFE_TRIANGLE = "FlatLaf.debug.menu.showSafeTriangle";
|
||||
|
||||
// Using a static field to ensure that there is only one instance in the system.
|
||||
// Multiple instances would freeze the application.
|
||||
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
|
||||
private static SubMenuUsabilityHelper instance;
|
||||
|
||||
private boolean eventQueuePushNotSupported;
|
||||
private SubMenuEventQueue subMenuEventQueue;
|
||||
private SafeTrianglePainter safeTrianglePainter;
|
||||
private boolean changePending;
|
||||
|
||||
// mouse location in screen coordinates
|
||||
private int mouseX;
|
||||
private int mouseY;
|
||||
|
||||
// target popup bounds in screen coordinates
|
||||
private int targetX;
|
||||
private int targetTopY;
|
||||
private int targetBottomY;
|
||||
|
||||
private Rectangle invokerBounds;
|
||||
|
||||
static synchronized boolean install() {
|
||||
if( instance != null )
|
||||
return false;
|
||||
|
||||
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_SUB_MENU_SAFE_TRIANGLE, true ) )
|
||||
return false;
|
||||
|
||||
instance = new SubMenuUsabilityHelper();
|
||||
MenuSelectionManager.defaultManager().addChangeListener( instance );
|
||||
return true;
|
||||
}
|
||||
|
||||
static synchronized void uninstall() {
|
||||
if( instance == null )
|
||||
return;
|
||||
|
||||
MenuSelectionManager.defaultManager().removeChangeListener( instance );
|
||||
instance.uninstallEventQueue();
|
||||
instance = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e ) {
|
||||
if( eventQueuePushNotSupported || !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||
return;
|
||||
|
||||
// handle menu selection change later, but only once in case of temporary changes
|
||||
// e.g. moving mouse from one menu item to another one, fires two events:
|
||||
// 1. old menu item is removed from menu selection
|
||||
// 2. new menu item is added to menu selection
|
||||
synchronized( this ) {
|
||||
if( changePending )
|
||||
return;
|
||||
changePending = true;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater( () -> {
|
||||
synchronized( this ) {
|
||||
changePending = false;
|
||||
}
|
||||
menuSelectionChanged();
|
||||
} );
|
||||
}
|
||||
|
||||
private void menuSelectionChanged() {
|
||||
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
|
||||
/*debug
|
||||
System.out.println( "--- " + path.length );
|
||||
for( int i = 0; i < path.length; i++ )
|
||||
System.out.println( " " + i + ": " + path[i].getClass().getName() );
|
||||
debug*/
|
||||
|
||||
// find submenu in menu selection
|
||||
int subMenuIndex = findSubMenu( path );
|
||||
|
||||
// uninstall if there is no submenu in selection
|
||||
if( subMenuIndex < 0 || subMenuIndex != path.length - 1 ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// get current mouse location
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point mouseLocation = (pointerInfo != null) ? pointerInfo.getLocation() : new Point();
|
||||
mouseX = mouseLocation.x;
|
||||
mouseY = mouseLocation.y;
|
||||
|
||||
// check whether popup is showing, which is e.g. not the case if it is empty
|
||||
JPopupMenu popup = (JPopupMenu) path[subMenuIndex];
|
||||
if( !popup.isShowing() ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// get invoker screen bounds
|
||||
Component invoker = popup.getInvoker();
|
||||
invokerBounds = (invoker != null && invoker.isShowing())
|
||||
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
||||
: null;
|
||||
|
||||
// check whether mouse location is within invoker
|
||||
if( invokerBounds != null && !invokerBounds.contains( mouseX, mouseY ) ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// compute top/bottom target locations
|
||||
Point popupLocation = popup.getLocationOnScreen();
|
||||
Dimension popupSize = popup.getSize();
|
||||
targetX = (mouseX < popupLocation.x + (popupSize.width / 2))
|
||||
? popupLocation.x
|
||||
: popupLocation.x + popupSize.width;
|
||||
targetTopY = popupLocation.y;
|
||||
targetBottomY = popupLocation.y + popupSize.height;
|
||||
|
||||
// install own event queue to suppress mouse events when mouse is moved within safe triangle
|
||||
if( subMenuEventQueue == null ) {
|
||||
SubMenuEventQueue queue = new SubMenuEventQueue();
|
||||
|
||||
try {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
toolkit.getSystemEventQueue().push( queue );
|
||||
|
||||
// check whether push() worked
|
||||
// (e.g. SWTSwing uses own event queue that does not support push())
|
||||
if( toolkit.getSystemEventQueue() != queue ) {
|
||||
eventQueuePushNotSupported = true;
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", null );
|
||||
return;
|
||||
}
|
||||
|
||||
subMenuEventQueue = queue;
|
||||
} catch( RuntimeException ex ) {
|
||||
// catch runtime exception from EventQueue.push()
|
||||
eventQueuePushNotSupported = true;
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", ex );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// create safe triangle painter
|
||||
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
||||
safeTrianglePainter = new SafeTrianglePainter( popup );
|
||||
}
|
||||
|
||||
private void uninstallEventQueue() {
|
||||
if( subMenuEventQueue != null ) {
|
||||
subMenuEventQueue.uninstall();
|
||||
subMenuEventQueue = null;
|
||||
}
|
||||
|
||||
if( safeTrianglePainter != null ) {
|
||||
safeTrianglePainter.uninstall();
|
||||
safeTrianglePainter = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int findSubMenu( MenuElement[] path ) {
|
||||
for( int i = path.length - 1; i >= 1; i-- ) {
|
||||
if( path[i] instanceof JPopupMenu &&
|
||||
path[i - 1] instanceof JMenu &&
|
||||
!((JMenu)path[i - 1]).isTopLevelMenu() )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Polygon createSafeTriangle() {
|
||||
return new Polygon(
|
||||
new int[] { mouseX, targetX, targetX },
|
||||
new int[] { mouseY, targetTopY, targetBottomY },
|
||||
3 );
|
||||
}
|
||||
|
||||
//---- class SubMenuEventQueue --------------------------------------------
|
||||
|
||||
private class SubMenuEventQueue
|
||||
extends EventQueue
|
||||
{
|
||||
private Timer mouseUpdateTimer;
|
||||
private Timer timeoutTimer;
|
||||
|
||||
private int newMouseX;
|
||||
private int newMouseY;
|
||||
private AWTEvent lastMouseEvent;
|
||||
|
||||
SubMenuEventQueue() {
|
||||
// timer used to slightly delay update of mouse location used for safe triangle
|
||||
mouseUpdateTimer = new Timer( 50, e -> {
|
||||
mouseX = newMouseX;
|
||||
mouseY = newMouseY;
|
||||
|
||||
if( safeTrianglePainter != null )
|
||||
safeTrianglePainter.repaint();
|
||||
} );
|
||||
mouseUpdateTimer.setRepeats( false );
|
||||
|
||||
// timer used to timeout safe triangle when mouse stops moving
|
||||
timeoutTimer = new Timer( 200, e -> {
|
||||
if( invokerBounds != null && !invokerBounds.contains( newMouseX, newMouseY ) ) {
|
||||
// post last mouse event, which selects menu item at mouse location
|
||||
if( lastMouseEvent != null ) {
|
||||
postEvent( lastMouseEvent );
|
||||
lastMouseEvent = null;
|
||||
}
|
||||
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
} );
|
||||
timeoutTimer.setRepeats( false );
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
mouseUpdateTimer.stop();
|
||||
mouseUpdateTimer = null;
|
||||
|
||||
timeoutTimer.stop();
|
||||
timeoutTimer = null;
|
||||
|
||||
lastMouseEvent = null;
|
||||
|
||||
super.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchEvent( AWTEvent e ) {
|
||||
int id = e.getID();
|
||||
|
||||
if( e instanceof MouseEvent &&
|
||||
(id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED) )
|
||||
{
|
||||
newMouseX = ((MouseEvent)e).getXOnScreen();
|
||||
newMouseY = ((MouseEvent)e).getYOnScreen();
|
||||
|
||||
if( safeTrianglePainter != null )
|
||||
safeTrianglePainter.repaint();
|
||||
|
||||
mouseUpdateTimer.stop();
|
||||
timeoutTimer.stop();
|
||||
|
||||
// check whether mouse moved within safe triangle
|
||||
if( createSafeTriangle().contains( newMouseX, newMouseY ) ) {
|
||||
// update mouse location delayed (this changes the safe triangle)
|
||||
mouseUpdateTimer.start();
|
||||
|
||||
timeoutTimer.start();
|
||||
|
||||
// remember last mouse event, which will be posted if the mouse stops moving
|
||||
lastMouseEvent = e;
|
||||
|
||||
// ignore mouse event
|
||||
return;
|
||||
}
|
||||
|
||||
// update mouse location immediately (this changes the safe triangle)
|
||||
mouseX = newMouseX;
|
||||
mouseY = newMouseY;
|
||||
}
|
||||
|
||||
super.dispatchEvent( e );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class SafeTrianglePainter ------------------------------------------
|
||||
|
||||
private class SafeTrianglePainter
|
||||
extends JComponent
|
||||
{
|
||||
SafeTrianglePainter( JPopupMenu popup ) {
|
||||
Window window = SwingUtilities.windowForComponent( popup.getInvoker() );
|
||||
if( window instanceof RootPaneContainer ) {
|
||||
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
|
||||
setSize( layeredPane.getSize() );
|
||||
layeredPane.add( this, Integer.valueOf( JLayeredPane.POPUP_LAYER + 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
Container parent = getParent();
|
||||
if( parent != null ) {
|
||||
parent.remove( this );
|
||||
parent.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
Point locationOnScreen = getLocationOnScreen();
|
||||
g.translate( -locationOnScreen.x, -locationOnScreen.y );
|
||||
|
||||
g.setColor( Color.red );
|
||||
((Graphics2D)g).draw( createSafeTriangle() );
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@ public abstract class FlatAbstractIcon
|
||||
{
|
||||
protected final int width;
|
||||
protected final int height;
|
||||
protected final Color color;
|
||||
protected Color color;
|
||||
|
||||
public FlatAbstractIcon( int width, int height, Color color ) {
|
||||
this.width = width;
|
||||
@@ -57,6 +57,8 @@ public abstract class FlatAbstractIcon
|
||||
// g2.setColor( Color.blue );
|
||||
// g2.drawRect( x, y, getIconWidth() - 1, getIconHeight() - 1 );
|
||||
|
||||
paintBackground( c, g2, x, y );
|
||||
|
||||
g2.translate( x, y );
|
||||
UIScale.scaleGraphics( g2 );
|
||||
|
||||
@@ -69,7 +71,11 @@ public abstract class FlatAbstractIcon
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void paintIcon( Component c, Graphics2D g2 );
|
||||
/** @since 3.5.2 */
|
||||
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
|
||||
}
|
||||
|
||||
protected abstract void paintIcon( Component c, Graphics2D g );
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* This makes it possible to use a share icon instance for multiple components.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public abstract class FlatAnimatedIcon
|
||||
extends FlatAbstractIcon
|
||||
implements AnimatedIcon
|
||||
{
|
||||
public FlatAnimatedIcon( int width, int height, Color color ) {
|
||||
super( width, height, color );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
super.paintIcon( c, g, x, y );
|
||||
AnimatedIcon.AnimationSupport.saveIconLocation( this, c, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
AnimatedIcon.AnimationSupport.paintIcon( this, c, g, 0, 0 );
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,11 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.TableHeaderUI;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import com.formdev.flatlaf.ui.FlatTableHeaderUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
@@ -35,8 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatAscendingSortIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
||||
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
||||
protected boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
||||
protected Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
||||
|
||||
public FlatAscendingSortIcon() {
|
||||
super( 10, 5, null );
|
||||
@@ -44,7 +48,28 @@ public class FlatAscendingSortIcon
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
boolean chevron = this.chevron;
|
||||
Color sortIconColor = this.sortIconColor;
|
||||
|
||||
// Because this icon is always shared for all table headers,
|
||||
// get icon specific style from FlatTableHeaderUI.
|
||||
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
|
||||
if( tableHeader != null ) {
|
||||
TableHeaderUI ui = tableHeader.getUI();
|
||||
if( ui instanceof FlatTableHeaderUI ) {
|
||||
FlatTableHeaderUI fui = (FlatTableHeaderUI) ui;
|
||||
if( fui.arrowType != null )
|
||||
chevron = FlatUIUtils.isChevron( fui.arrowType );
|
||||
if( fui.sortIconColor != null )
|
||||
sortIconColor = fui.sortIconColor;
|
||||
}
|
||||
}
|
||||
|
||||
g.setColor( sortIconColor );
|
||||
paintArrow( c, g, chevron );
|
||||
}
|
||||
|
||||
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
|
||||
if( chevron ) {
|
||||
// chevron arrow
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
|
||||
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;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
@@ -34,26 +39,51 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatCapsLockIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatCapsLockIcon() {
|
||||
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
Object oldValue;
|
||||
switch( key ) {
|
||||
case "capsLockIconColor": oldValue = color; color = (Color) value; return oldValue;
|
||||
default: throw new UnknownStyleException( key );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
switch( key ) {
|
||||
case "capsLockIconColor": return color;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||
<rect width="6" height="2" x="5" y="12" fill="#FFF"/>
|
||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
||||
<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, 12, 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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,82 +23,115 @@ import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* Icon for {@link javax.swing.JCheckBox}.
|
||||
*
|
||||
* Note: If Component.focusWidth is greater than zero, then the outline focus border
|
||||
* <p>
|
||||
* <strong>Note</strong>:
|
||||
* If Component.focusWidth is greater than zero, then the outer focus border
|
||||
* is painted outside of the icon bounds. Make sure that the checkbox
|
||||
* has margins, which are equal or greater than focusWidth.
|
||||
*
|
||||
* @uiDefault CheckBox.icon.style String optional; "outline"/null (default) or "filled"
|
||||
* @uiDefault CheckBox.icon.style String optional; "outlined"/null (default) or "filled"
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.borderWidth int
|
||||
* @uiDefault Component.focusColor Color
|
||||
* @uiDefault CheckBox.icon.focusWidth int optional; defaults to Component.focusWidth
|
||||
* @uiDefault CheckBox.icon.focusWidth int or float optional; defaults to Component.focusWidth
|
||||
* @uiDefault CheckBox.icon.borderWidth int or float optional; defaults to Component.borderWidth
|
||||
* @uiDefault CheckBox.icon.selectedBorderWidth int or float optional; defaults to CheckBox.icon.borderWidth
|
||||
* @uiDefault CheckBox.icon.disabledSelectedBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth
|
||||
* @uiDefault CheckBox.arc int
|
||||
*
|
||||
* @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor
|
||||
* @uiDefault CheckBox.icon.borderColor Color
|
||||
* @uiDefault CheckBox.icon.background Color
|
||||
* @uiDefault CheckBox.icon.selectedBorderColor Color
|
||||
* @uiDefault CheckBox.icon.selectedBackground Color
|
||||
* @uiDefault CheckBox.icon.checkmarkColor Color
|
||||
*
|
||||
* @uiDefault CheckBox.icon.disabledBorderColor Color
|
||||
* @uiDefault CheckBox.icon.disabledBackground Color
|
||||
* @uiDefault CheckBox.icon.disabledSelectedBorderColor Color optional; CheckBox.icon.disabledBorderColor is used if not specified
|
||||
* @uiDefault CheckBox.icon.disabledSelectedBackground Color optional; CheckBox.icon.disabledBackground is used if not specified
|
||||
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color
|
||||
* @uiDefault CheckBox.icon.focusedBorderColor Color
|
||||
*
|
||||
* @uiDefault CheckBox.icon.focusedBorderColor Color optional
|
||||
* @uiDefault CheckBox.icon.focusedBackground Color optional
|
||||
* @uiDefault CheckBox.icon.selectedFocusedBorderColor Color optional
|
||||
* @uiDefault CheckBox.icon.selectedFocusedBackground Color optional
|
||||
* @uiDefault CheckBox.icon.focusedSelectedBorderColor Color optional; CheckBox.icon.focusedBorderColor is used if not specified
|
||||
* @uiDefault CheckBox.icon.focusedSelectedBackground Color optional; CheckBox.icon.focusedBackground is used if not specified
|
||||
* @uiDefault CheckBox.icon.focusedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified
|
||||
*
|
||||
* @uiDefault CheckBox.icon.hoverBorderColor Color optional
|
||||
* @uiDefault CheckBox.icon.hoverBackground Color optional
|
||||
* @uiDefault CheckBox.icon.selectedHoverBackground Color optional
|
||||
* @uiDefault CheckBox.icon.hoverSelectedBorderColor Color optional; CheckBox.icon.hoverBorderColor is used if not specified
|
||||
* @uiDefault CheckBox.icon.hoverSelectedBackground Color optional; CheckBox.icon.hoverBackground is used if not specified
|
||||
* @uiDefault CheckBox.icon.hoverCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified
|
||||
*
|
||||
* @uiDefault CheckBox.icon.pressedBorderColor Color optional
|
||||
* @uiDefault CheckBox.icon.pressedBackground Color optional
|
||||
* @uiDefault CheckBox.icon.selectedPressedBackground Color optional
|
||||
* @uiDefault CheckBox.arc int
|
||||
* @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; CheckBox.icon.pressedBorderColor is used if not specified
|
||||
* @uiDefault CheckBox.icon.pressedSelectedBackground Color optional; CheckBox.icon.pressedBackground is used if not specified
|
||||
* @uiDefault CheckBox.icon.pressedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatCheckBoxIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
protected final String style = UIManager.getString( "CheckBox.icon.style" );
|
||||
public final int focusWidth = getUIInt( "CheckBox.icon.focusWidth",
|
||||
UIManager.getInt( "Component.focusWidth" ), style );
|
||||
protected final Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusColor",
|
||||
UIManager.getColor( "Component.focusColor" ) );
|
||||
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
|
||||
protected final String style = UIManager.getString( getPropertyPrefix() + "icon.style" );
|
||||
@Styleable protected float focusWidth = getUIFloat( "CheckBox.icon.focusWidth", UIManager.getInt( "Component.focusWidth" ), style );
|
||||
@Styleable protected Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusColor", UIManager.getColor( "Component.focusColor" ) );
|
||||
/** @since 2 */ @Styleable protected float borderWidth = getUIFloat( "CheckBox.icon.borderWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ), style );
|
||||
/** @since 2 */ @Styleable protected float selectedBorderWidth = getUIFloat( "CheckBox.icon.selectedBorderWidth", Float.MIN_VALUE, style );
|
||||
/** @since 2 */ @Styleable protected float disabledSelectedBorderWidth = getUIFloat( "CheckBox.icon.disabledSelectedBorderWidth", Float.MIN_VALUE, style );
|
||||
@Styleable protected int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
|
||||
|
||||
// enabled
|
||||
protected final Color borderColor = getUIColor( "CheckBox.icon.borderColor", style );
|
||||
protected final Color background = getUIColor( "CheckBox.icon.background", style );
|
||||
protected final Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
|
||||
protected final Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
|
||||
protected final Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
|
||||
@Styleable protected Color borderColor = getUIColor( "CheckBox.icon.borderColor", style );
|
||||
@Styleable protected Color background = getUIColor( "CheckBox.icon.background", style );
|
||||
@Styleable protected Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
|
||||
@Styleable protected Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
|
||||
@Styleable protected Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
|
||||
|
||||
// disabled
|
||||
protected final Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
|
||||
protected final Color disabledBackground = getUIColor( "CheckBox.icon.disabledBackground", style );
|
||||
protected final Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
|
||||
@Styleable protected Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
|
||||
@Styleable protected Color disabledBackground = getUIColor( "CheckBox.icon.disabledBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color disabledSelectedBorderColor = getUIColor( "CheckBox.icon.disabledSelectedBorderColor", style );
|
||||
/** @since 2 */ @Styleable protected Color disabledSelectedBackground = getUIColor( "CheckBox.icon.disabledSelectedBackground", style );
|
||||
@Styleable protected Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
|
||||
|
||||
// focused
|
||||
protected final Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
|
||||
protected final Color focusedBackground = getUIColor( "CheckBox.icon.focusedBackground", style );
|
||||
protected final Color selectedFocusedBorderColor = getUIColor( "CheckBox.icon.selectedFocusedBorderColor", style );
|
||||
protected final Color selectedFocusedBackground = getUIColor( "CheckBox.icon.selectedFocusedBackground", style );
|
||||
protected final Color selectedFocusedCheckmarkColor = getUIColor( "CheckBox.icon.selectedFocusedCheckmarkColor", style );
|
||||
@Styleable protected Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
|
||||
@Styleable protected Color focusedBackground = getUIColor( "CheckBox.icon.focusedBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color focusedSelectedBorderColor = getUIColor( "CheckBox.icon.focusedSelectedBorderColor", style );
|
||||
/** @since 2 */ @Styleable protected Color focusedSelectedBackground = getUIColor( "CheckBox.icon.focusedSelectedBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color focusedCheckmarkColor = getUIColor( "CheckBox.icon.focusedCheckmarkColor", style );
|
||||
|
||||
// hover
|
||||
protected final Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
|
||||
protected final Color hoverBackground = getUIColor( "CheckBox.icon.hoverBackground", style );
|
||||
protected final Color selectedHoverBackground = getUIColor( "CheckBox.icon.selectedHoverBackground", style );
|
||||
@Styleable protected Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
|
||||
@Styleable protected Color hoverBackground = getUIColor( "CheckBox.icon.hoverBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color hoverSelectedBorderColor = getUIColor( "CheckBox.icon.hoverSelectedBorderColor", style );
|
||||
/** @since 2 */ @Styleable protected Color hoverSelectedBackground = getUIColor( "CheckBox.icon.hoverSelectedBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color hoverCheckmarkColor = getUIColor( "CheckBox.icon.hoverCheckmarkColor", style );
|
||||
|
||||
// pressed
|
||||
protected final Color pressedBackground = getUIColor( "CheckBox.icon.pressedBackground", style );
|
||||
protected final Color selectedPressedBackground = getUIColor( "CheckBox.icon.selectedPressedBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color pressedBorderColor = getUIColor( "CheckBox.icon.pressedBorderColor", style );
|
||||
@Styleable protected Color pressedBackground = getUIColor( "CheckBox.icon.pressedBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color pressedSelectedBorderColor = getUIColor( "CheckBox.icon.pressedSelectedBorderColor", style );
|
||||
/** @since 2 */ @Styleable protected Color pressedSelectedBackground = getUIColor( "CheckBox.icon.pressedSelectedBackground", style );
|
||||
/** @since 2 */ @Styleable protected Color pressedCheckmarkColor = getUIColor( "CheckBox.icon.pressedCheckmarkColor", style );
|
||||
|
||||
protected String getPropertyPrefix() {
|
||||
return "CheckBox.";
|
||||
}
|
||||
|
||||
protected static Color getUIColor( String key, String style ) {
|
||||
if( style != null ) {
|
||||
@@ -109,13 +142,14 @@ public class FlatCheckBoxIcon
|
||||
return UIManager.getColor( key );
|
||||
}
|
||||
|
||||
protected static int getUIInt( String key, int defaultValue, String style ) {
|
||||
/** @since 2 */
|
||||
protected static float getUIFloat( String key, float defaultValue, String style ) {
|
||||
if( style != null ) {
|
||||
Object value = UIManager.get( styleKey( key, style ) );
|
||||
if( value instanceof Integer )
|
||||
return (Integer) value;
|
||||
float value = FlatUIUtils.getUIFloat( styleKey( key, style ), Float.MIN_VALUE );
|
||||
if( value != Float.MIN_VALUE )
|
||||
return value;
|
||||
}
|
||||
return FlatUIUtils.getUIInt( key, defaultValue );
|
||||
return FlatUIUtils.getUIFloat( key, defaultValue );
|
||||
}
|
||||
|
||||
private static String styleKey( String key, String style ) {
|
||||
@@ -128,11 +162,31 @@ public class FlatCheckBoxIcon
|
||||
super( ICON_SIZE, ICON_SIZE, null );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
boolean indeterminate = isIndeterminate( c );
|
||||
boolean selected = indeterminate || isSelected( c );
|
||||
boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||
float bw = selected
|
||||
? (disabledSelectedBorderWidth != Float.MIN_VALUE && !c.isEnabled()
|
||||
? disabledSelectedBorderWidth
|
||||
: (selectedBorderWidth != Float.MIN_VALUE ? selectedBorderWidth : borderWidth))
|
||||
: borderWidth;
|
||||
|
||||
// paint focused border
|
||||
if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) {
|
||||
@@ -142,15 +196,22 @@ public class FlatCheckBoxIcon
|
||||
|
||||
// paint border
|
||||
g.setColor( getBorderColor( c, selected ) );
|
||||
paintBorder( c, g );
|
||||
paintBorder( c, g, bw );
|
||||
|
||||
// paint background
|
||||
g.setColor( FlatUIUtils.deriveColor( getBackground( c, selected ), background ) );
|
||||
paintBackground( c, g );
|
||||
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ),
|
||||
selected ? selectedBackground : background );
|
||||
if( bg.getAlpha() < 255 ) {
|
||||
// fill background with default color before filling with non-opaque background
|
||||
g.setColor( selected ? selectedBackground : background );
|
||||
paintBackground( c, g, bw );
|
||||
}
|
||||
g.setColor( bg );
|
||||
paintBackground( c, g, bw );
|
||||
|
||||
// paint checkmark
|
||||
if( selected || indeterminate ) {
|
||||
g.setColor( getCheckmarkColor( c, selected, isFocused ) );
|
||||
if( selected ) {
|
||||
g.setColor( getCheckmarkColor( c ) );
|
||||
if( indeterminate )
|
||||
paintIndeterminate( c, g );
|
||||
else
|
||||
@@ -159,24 +220,29 @@ public class FlatCheckBoxIcon
|
||||
}
|
||||
|
||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||
// the outline focus border is painted outside of the icon
|
||||
int wh = ICON_SIZE - 1 + (focusWidth * 2);
|
||||
int arcwh = arc + (focusWidth * 2);
|
||||
g.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
|
||||
// the outer focus border is painted outside of the icon
|
||||
float wh = ICON_SIZE - 1 + (focusWidth * 2);
|
||||
float arcwh = arc + (focusWidth * 2);
|
||||
g.fill( new RoundRectangle2D.Float( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh ) );
|
||||
}
|
||||
|
||||
protected void paintBorder( Component c, Graphics2D g ) {
|
||||
protected void paintBorder( Component c, Graphics2D g, float borderWidth ) {
|
||||
if( borderWidth == 0 )
|
||||
return;
|
||||
|
||||
int arcwh = arc;
|
||||
g.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
|
||||
}
|
||||
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
int arcwh = arc - 1;
|
||||
g.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
|
||||
protected void paintBackground( Component c, Graphics2D g, float borderWidth ) {
|
||||
float xy = borderWidth;
|
||||
float wh = 14 - (borderWidth * 2);
|
||||
float arcwh = arc - borderWidth;
|
||||
g.fill( new RoundRectangle2D.Float( 1 + xy, xy, wh, wh, arcwh, arcwh ) );
|
||||
}
|
||||
|
||||
protected void paintCheckmark( Component c, Graphics2D g ) {
|
||||
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 );
|
||||
@@ -197,6 +263,11 @@ public class FlatCheckBoxIcon
|
||||
return c instanceof AbstractButton && ((AbstractButton)c).isSelected();
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public float getFocusWidth() {
|
||||
return focusWidth;
|
||||
}
|
||||
|
||||
protected Color getFocusColor( Component c ) {
|
||||
return focusColor;
|
||||
}
|
||||
@@ -204,26 +275,27 @@ public class FlatCheckBoxIcon
|
||||
protected Color getBorderColor( Component c, boolean selected ) {
|
||||
return FlatButtonUI.buttonStateColor( c,
|
||||
selected ? selectedBorderColor : borderColor,
|
||||
disabledBorderColor,
|
||||
selected && selectedFocusedBorderColor != null ? selectedFocusedBorderColor : focusedBorderColor,
|
||||
hoverBorderColor,
|
||||
null );
|
||||
(selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor,
|
||||
(selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor,
|
||||
(selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor,
|
||||
(selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor );
|
||||
}
|
||||
|
||||
protected Color getBackground( Component c, boolean selected ) {
|
||||
return FlatButtonUI.buttonStateColor( c,
|
||||
selected ? selectedBackground : background,
|
||||
disabledBackground,
|
||||
(selected && selectedFocusedBackground != null) ? selectedFocusedBackground : focusedBackground,
|
||||
(selected && selectedHoverBackground != null) ? selectedHoverBackground : hoverBackground,
|
||||
(selected && selectedPressedBackground != null) ? selectedPressedBackground : pressedBackground );
|
||||
(selected && disabledSelectedBackground != null) ? disabledSelectedBackground : disabledBackground,
|
||||
(selected && focusedSelectedBackground != null) ? focusedSelectedBackground : focusedBackground,
|
||||
(selected && hoverSelectedBackground != null) ? hoverSelectedBackground : hoverBackground,
|
||||
(selected && pressedSelectedBackground != null) ? pressedSelectedBackground : pressedBackground );
|
||||
}
|
||||
|
||||
protected Color getCheckmarkColor( Component c, boolean selected, boolean isFocused ) {
|
||||
return c.isEnabled()
|
||||
? ((selected && isFocused && selectedFocusedCheckmarkColor != null)
|
||||
? selectedFocusedCheckmarkColor
|
||||
: checkmarkColor)
|
||||
: disabledCheckmarkColor;
|
||||
protected Color getCheckmarkColor( Component c ) {
|
||||
return FlatButtonUI.buttonStateColor( c,
|
||||
checkmarkColor,
|
||||
disabledCheckmarkColor,
|
||||
focusedCheckmarkColor,
|
||||
hoverCheckmarkColor,
|
||||
pressedCheckmarkColor );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,18 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
|
||||
/**
|
||||
* Icon for {@link javax.swing.JCheckBoxMenuItem}.
|
||||
*
|
||||
* @uiDefault MenuItemCheckBox.icon.checkmarkColor Color
|
||||
* @uiDefault MenuItemCheckBox.icon.disabledCheckmarkColor Color
|
||||
* @uiDefault CheckBoxMenuItem.icon.checkmarkColor Color
|
||||
* @uiDefault CheckBoxMenuItem.icon.disabledCheckmarkColor Color
|
||||
* @uiDefault MenuItem.selectionForeground Color
|
||||
* @uiDefault MenuItem.selectionType String
|
||||
*
|
||||
@@ -38,14 +41,29 @@ import javax.swing.UIManager;
|
||||
public class FlatCheckBoxMenuItemIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
protected final Color checkmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.checkmarkColor" );
|
||||
protected final Color disabledCheckmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.disabledCheckmarkColor" );
|
||||
protected final Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
||||
@Styleable protected Color checkmarkColor = UIManager.getColor( "CheckBoxMenuItem.icon.checkmarkColor" );
|
||||
@Styleable protected Color disabledCheckmarkColor = UIManager.getColor( "CheckBoxMenuItem.icon.disabledCheckmarkColor" );
|
||||
@Styleable protected Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
||||
|
||||
public FlatCheckBoxMenuItemIcon() {
|
||||
super( 15, 15, null );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||
boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected();
|
||||
@@ -58,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 );
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "clear" icon for search fields.
|
||||
*
|
||||
* @uiDefault SearchField.clearIconColor Color
|
||||
* @uiDefault SearchField.clearIconHoverColor Color
|
||||
* @uiDefault SearchField.clearIconPressedColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 1.5
|
||||
*/
|
||||
public class FlatClearIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
@Styleable protected Color clearIconColor = UIManager.getColor( "SearchField.clearIconColor" );
|
||||
@Styleable protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" );
|
||||
@Styleable protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" );
|
||||
|
||||
private final boolean ignoreButtonState;
|
||||
|
||||
public FlatClearIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatClearIcon( boolean ignoreButtonState ) {
|
||||
super( 16, 16, null );
|
||||
this.ignoreButtonState = ignoreButtonState;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
if( !ignoreButtonState && c instanceof AbstractButton ) {
|
||||
ButtonModel model = ((AbstractButton)c).getModel();
|
||||
if( model.isPressed() || model.isRollover() ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#7F8B91" fill-opacity=".5" fill-rule="evenodd" d="M8,1.75 C11.4517797,1.75 14.25,4.54822031 14.25,8 C14.25,11.4517797 11.4517797,14.25 8,14.25 C4.54822031,14.25 1.75,11.4517797 1.75,8 C1.75,4.54822031 4.54822031,1.75 8,1.75 Z M10.5,4.5 L8,7 L5.5,4.5 L4.5,5.5 L7,8 L4.5,10.5 L5.5,11.5 L8,9 L10.5,11.5 L11.5,10.5 L9,8 L11.5,5.5 L10.5,4.5 Z"/>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
// paint filled circle with cross
|
||||
g.setColor( model.isPressed() ? clearIconPressedColor : clearIconHoverColor );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Ellipse2D.Float( 1.75f, 1.75f, 12.5f, 12.5f ), false );
|
||||
path.append( FlatUIUtils.createPath( 4.5,5.5, 5.5,4.5, 8,7, 10.5,4.5, 11.5,5.5, 9,8, 11.5,10.5, 10.5,11.5, 8,9, 5.5,11.5, 4.5,10.5, 7,8 ), false );
|
||||
g.fill( path );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="none" stroke="#7F8B91" stroke-linecap="square" stroke-opacity=".5" d="M5,5 L11,11 M5,11 L11,5"/>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
// paint cross
|
||||
g.setColor( clearIconColor );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||
path.moveTo( 5, 5 );
|
||||
path.lineTo( 11, 11 );
|
||||
path.moveTo( 5, 11 );
|
||||
path.lineTo( 11, 5 );
|
||||
g.draw( path );
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,9 @@
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
@@ -33,18 +31,14 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatDescendingSortIcon
|
||||
extends FlatAbstractIcon
|
||||
extends FlatAscendingSortIcon
|
||||
{
|
||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
||||
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
||||
|
||||
public FlatDescendingSortIcon() {
|
||||
super( 10, 5, null );
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
g.setColor( sortIconColor );
|
||||
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
|
||||
if( chevron ) {
|
||||
// chevron arrow
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );
|
||||
|
||||
@@ -39,21 +39,25 @@ public class FlatFileChooserDetailsViewIcon
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<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,13 +17,18 @@
|
||||
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;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
@@ -31,6 +36,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
*
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.focusColor Color
|
||||
* @uiDefault HelpButton.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
||||
* @uiDefault HelpButton.borderWidth int optional; default is 1
|
||||
* @uiDefault HelpButton.borderColor Color
|
||||
* @uiDefault HelpButton.disabledBorderColor Color
|
||||
* @uiDefault HelpButton.focusedBorderColor Color
|
||||
@@ -48,27 +55,42 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatHelpButtonIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||
@Styleable protected int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
@Styleable protected Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||
@Styleable protected float innerFocusWidth = FlatUIUtils.getUIFloat( "HelpButton.innerFocusWidth", FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 ) );
|
||||
@Styleable protected int borderWidth = FlatUIUtils.getUIInt( "HelpButton.borderWidth", 1 );
|
||||
|
||||
protected final Color borderColor = UIManager.getColor( "HelpButton.borderColor" );
|
||||
protected final Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" );
|
||||
protected final Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" );
|
||||
protected final Color hoverBorderColor = UIManager.getColor( "HelpButton.hoverBorderColor" );
|
||||
protected final Color background = UIManager.getColor( "HelpButton.background" );
|
||||
protected final Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" );
|
||||
protected final Color focusedBackground = UIManager.getColor( "HelpButton.focusedBackground" );
|
||||
protected final Color hoverBackground = UIManager.getColor( "HelpButton.hoverBackground" );
|
||||
protected final Color pressedBackground = UIManager.getColor( "HelpButton.pressedBackground" );
|
||||
protected final Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" );
|
||||
protected final Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" );
|
||||
|
||||
protected final int iconSize = 22 + (focusWidth * 2);
|
||||
@Styleable protected Color borderColor = UIManager.getColor( "HelpButton.borderColor" );
|
||||
@Styleable protected Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" );
|
||||
@Styleable protected Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" );
|
||||
@Styleable protected Color hoverBorderColor = UIManager.getColor( "HelpButton.hoverBorderColor" );
|
||||
@Styleable protected Color background = UIManager.getColor( "HelpButton.background" );
|
||||
@Styleable protected Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" );
|
||||
@Styleable protected Color focusedBackground = UIManager.getColor( "HelpButton.focusedBackground" );
|
||||
@Styleable protected Color hoverBackground = UIManager.getColor( "HelpButton.hoverBackground" );
|
||||
@Styleable protected Color pressedBackground = UIManager.getColor( "HelpButton.pressedBackground" );
|
||||
@Styleable protected Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" );
|
||||
@Styleable protected Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" );
|
||||
|
||||
public FlatHelpButtonIcon() {
|
||||
super( 0, 0, null );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||
/*
|
||||
@@ -76,20 +98,27 @@ 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 );
|
||||
|
||||
// paint focused border
|
||||
float xy = 0.5f;
|
||||
float wh = iconSize() - 1;
|
||||
|
||||
// paint outer focus border
|
||||
if( focused && FlatButtonUI.isFocusPainted( c ) ) {
|
||||
g2.setColor( focusColor );
|
||||
g2.fill( new Ellipse2D.Float( 0.5f, 0.5f, iconSize - 1, iconSize - 1 ) );
|
||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||
}
|
||||
|
||||
xy += focusWidth;
|
||||
wh -= (focusWidth * 2);
|
||||
|
||||
// paint border
|
||||
g2.setColor( FlatButtonUI.buttonStateColor( c,
|
||||
borderColor,
|
||||
@@ -97,7 +126,19 @@ public class FlatHelpButtonIcon
|
||||
focusedBorderColor,
|
||||
hoverBorderColor,
|
||||
null ) );
|
||||
g2.fill( new Ellipse2D.Float( focusWidth + 0.5f, focusWidth + 0.5f, 21, 21 ) );
|
||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||
|
||||
xy += borderWidth;
|
||||
wh -= (borderWidth * 2);
|
||||
|
||||
// paint inner focus border
|
||||
if( innerFocusWidth > 0 && focused && FlatButtonUI.isFocusPainted( c ) ) {
|
||||
g2.setColor( focusColor );
|
||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||
|
||||
xy += innerFocusWidth;
|
||||
wh -= (innerFocusWidth * 2);
|
||||
}
|
||||
|
||||
// paint background
|
||||
g2.setColor( FlatUIUtils.deriveColor( FlatButtonUI.buttonStateColor( c,
|
||||
@@ -106,34 +147,35 @@ public class FlatHelpButtonIcon
|
||||
focusedBackground,
|
||||
hoverBackground,
|
||||
pressedBackground ), background ) );
|
||||
g2.fill( new Ellipse2D.Float( focusWidth + 1.5f, focusWidth + 1.5f, 19, 19 ) );
|
||||
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
|
||||
public int getIconWidth() {
|
||||
return scale( iconSize );
|
||||
return scale( iconSize() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return scale( iconSize );
|
||||
return scale( iconSize() );
|
||||
}
|
||||
|
||||
private int iconSize() {
|
||||
return 22 + (focusWidth * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.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 );
|
||||
}
|
||||
|
||||
@@ -21,9 +21,12 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
|
||||
/**
|
||||
* "arrow" icon for {@link javax.swing.JMenu}.
|
||||
@@ -39,22 +42,37 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatMenuArrowIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
||||
protected final Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" );
|
||||
protected final Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" );
|
||||
protected final Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
||||
@Styleable protected String arrowType = UIManager.getString( "Component.arrowType" );
|
||||
@Styleable protected Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" );
|
||||
@Styleable protected Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" );
|
||||
@Styleable protected Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
||||
|
||||
public FlatMenuArrowIcon() {
|
||||
super( 6, 10, null );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
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 ) );
|
||||
if( chevron ) {
|
||||
if( FlatUIUtils.isChevron( arrowType ) ) {
|
||||
// chevron arrow
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 1,9 );
|
||||
g.setStroke( new BasicStroke( 1f ) );
|
||||
@@ -69,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,38 +19,51 @@ package com.formdev.flatlaf.icons;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
|
||||
/**
|
||||
* Icon for {@link javax.swing.JRadioButton}.
|
||||
*
|
||||
* Note: If Component.focusWidth is greater than zero, then the outline focus border
|
||||
* <p>
|
||||
* <strong>Note</strong>:
|
||||
* If Component.focusWidth is greater than zero, then the outer focus border
|
||||
* is painted outside of the icon bounds. Make sure that the radiobutton
|
||||
* has margins, which are equal or greater than focusWidth.
|
||||
*
|
||||
* @uiDefault RadioButton.icon.centerDiameter int
|
||||
* @uiDefault RadioButton.icon.style String optional; "outlined"/null (default) or "filled"
|
||||
* @uiDefault RadioButton.icon.centerDiameter int or float
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatRadioButtonIcon
|
||||
extends FlatCheckBoxIcon
|
||||
{
|
||||
protected final int centerDiameter = getUIInt( "RadioButton.icon.centerDiameter", 8, style );
|
||||
@Styleable protected float centerDiameter = getUIFloat( "RadioButton.icon.centerDiameter", 8, style );
|
||||
|
||||
@Override
|
||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||
// the outline focus border is painted outside of the icon
|
||||
int wh = ICON_SIZE + (focusWidth * 2);
|
||||
g.fillOval( -focusWidth, -focusWidth, wh, wh );
|
||||
protected String getPropertyPrefix() {
|
||||
return "RadioButton.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBorder( Component c, Graphics2D g ) {
|
||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||
// the outer focus border is painted outside of the icon
|
||||
float wh = ICON_SIZE + (focusWidth * 2);
|
||||
g.fill( new Ellipse2D.Float( -focusWidth, -focusWidth, wh, wh ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBorder( Component c, Graphics2D g, float borderWidth ) {
|
||||
if( borderWidth == 0 )
|
||||
return;
|
||||
|
||||
g.fillOval( 0, 0, 15, 15 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
g.fillOval( 1, 1, 13, 13 );
|
||||
protected void paintBackground( Component c, Graphics2D g, float borderWidth ) {
|
||||
float xy = borderWidth;
|
||||
float wh = 15 - (borderWidth * 2);
|
||||
g.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* "eye" icon for {@link javax.swing.JPasswordField}.
|
||||
*
|
||||
* @uiDefault PasswordField.revealIconColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public class FlatRevealIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
public FlatRevealIcon() {
|
||||
super( 16, 16, UIManager.getColor( "PasswordField.revealIconColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Ellipse2D.Float( 5.15f, 6.15f, 5.7f, 5.7f ), false );
|
||||
path.append( new Ellipse2D.Float( 6, 7, 4, 4 ), false );
|
||||
g.fill( path );
|
||||
|
||||
Path2D path2 = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path2.append( new Ellipse2D.Float( 2.15f, 4.15f, 11.7f, 11.7f ), false );
|
||||
path2.append( new Ellipse2D.Float( 3, 5, 10, 10 ), false );
|
||||
Area area = new Area( path2 );
|
||||
area.subtract( new Area( new Rectangle2D.Float( 0, 9.5f, 16, 16 ) ) );
|
||||
g.fill( area );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "search" icon for search fields.
|
||||
*
|
||||
* @uiDefault SearchField.searchIconColor Color
|
||||
* @uiDefault SearchField.searchIconHoverColor Color
|
||||
* @uiDefault SearchField.searchIconPressedColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 1.5
|
||||
*/
|
||||
public class FlatSearchIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
@Styleable protected Color searchIconColor = UIManager.getColor( "SearchField.searchIconColor" );
|
||||
@Styleable protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" );
|
||||
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
||||
|
||||
private final boolean ignoreButtonState;
|
||||
private Area area;
|
||||
|
||||
public FlatSearchIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatSearchIcon( boolean ignoreButtonState ) {
|
||||
super( 16, 16, null );
|
||||
this.ignoreButtonState = ignoreButtonState;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
|
||||
<polygon fill="#7F8B91" points="10.813 9.75 14 12.938 12.938 14 9.75 10.813"/>
|
||||
<path fill="#7F8B91" d="M7,2 C9.76142375,2 12,4.23857625 12,7 C12,9.76142375 9.76142375,12 7,12 C4.23857625,12 2,9.76142375 2,7 C2,4.23857625 4.23857625,2 7,2 Z M7,3 C4.790861,3 3,4.790861 3,7 C3,9.209139 4.790861,11 7,11 C9.209139,11 11,9.209139 11,7 C11,4.790861 9.209139,3 7,3 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.setColor( ignoreButtonState
|
||||
? searchIconColor
|
||||
: FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||
|
||||
// paint magnifier
|
||||
if( area == null ) {
|
||||
area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
||||
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) );
|
||||
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) );
|
||||
}
|
||||
g.fill( area );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "search with history" icon for search fields.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 1.5
|
||||
*/
|
||||
public class FlatSearchWithHistoryIcon
|
||||
extends FlatSearchIcon
|
||||
{
|
||||
public FlatSearchWithHistoryIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatSearchWithHistoryIcon( boolean ignoreButtonState ) {
|
||||
super( ignoreButtonState );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
|
||||
<polygon fill="#7F8B91" points="8.813 9.75 12 12.938 10.938 14 7.75 10.813"/>
|
||||
<path fill="#7F8B91" d="M5,2 C7.76142375,2 10,4.23857625 10,7 C10,9.76142375 7.76142375,12 5,12 C2.23857625,12 0,9.76142375 0,7 C0,4.23857625 2.23857625,2 5,2 Z M5,3 C2.790861,3 1,4.790861 1,7 C1,9.209139 2.790861,11 5,11 C7.209139,11 9,9.209139 9,7 C9,4.790861 7.209139,3 5,3 Z"/>
|
||||
<polygon fill="#7F8B91" points="11 7 16 7 13.5 10"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
// paint magnifier
|
||||
g.translate( -2, 0 );
|
||||
super.paintIcon( c, g );
|
||||
g.translate( 2, 0 );
|
||||
|
||||
// paint history arrow
|
||||
g.fill( FlatUIUtils.createPath( 11,7, 16,7, 13.5,10 ) );
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,12 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
@@ -47,44 +49,61 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatTabbedPaneCloseIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
protected final Dimension size = UIManager.getDimension( "TabbedPane.closeSize" );
|
||||
protected final int arc = UIManager.getInt( "TabbedPane.closeArc" );
|
||||
protected final float crossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
||||
protected final float crossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", crossPlainSize );
|
||||
protected final float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
||||
protected final Color background = UIManager.getColor( "TabbedPane.closeBackground" );
|
||||
protected final Color foreground = UIManager.getColor( "TabbedPane.closeForeground" );
|
||||
protected final Color hoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
||||
protected final Color hoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
||||
protected final Color pressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
||||
protected final Color pressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
||||
@Styleable protected Dimension closeSize = UIManager.getDimension( "TabbedPane.closeSize" );
|
||||
@Styleable protected int closeArc = UIManager.getInt( "TabbedPane.closeArc" );
|
||||
@Styleable protected float closeCrossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
||||
@Styleable protected float closeCrossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", closeCrossPlainSize );
|
||||
@Styleable protected float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
||||
@Styleable protected Color closeBackground = UIManager.getColor( "TabbedPane.closeBackground" );
|
||||
@Styleable protected Color closeForeground = UIManager.getColor( "TabbedPane.closeForeground" );
|
||||
@Styleable protected Color closeHoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
||||
@Styleable protected Color closeHoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
||||
@Styleable protected Color closePressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
||||
@Styleable protected Color closePressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
||||
|
||||
public FlatTabbedPaneCloseIcon() {
|
||||
super( 16, 16, null );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
// paint background
|
||||
Color bg = FlatButtonUI.buttonStateColor( c, background, null, null, hoverBackground, pressedBackground );
|
||||
Color bg = FlatButtonUI.buttonStateColor( c, closeBackground, null, null, closeHoverBackground, closePressedBackground );
|
||||
if( bg != null ) {
|
||||
g.setColor( FlatUIUtils.deriveColor( bg, c.getBackground() ) );
|
||||
g.fillRoundRect( (width - size.width) / 2, (height - size.height) / 2,
|
||||
size.width, size.height, arc, arc );
|
||||
g.fillRoundRect( (width - closeSize.width) / 2, (height - closeSize.height) / 2,
|
||||
closeSize.width, closeSize.height, closeArc, closeArc );
|
||||
}
|
||||
|
||||
// set cross color
|
||||
Color fg = FlatButtonUI.buttonStateColor( c, foreground, null, null, hoverForeground, pressedForeground );
|
||||
// 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 r = ((bg != null) ? crossFilledSize : crossPlainSize) / 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,18 +32,26 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatTreeClosedIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatTreeClosedIcon() {
|
||||
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconClosedColor );
|
||||
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<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,10 +16,17 @@
|
||||
|
||||
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;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.TreeUI;
|
||||
import com.formdev.flatlaf.ui.FlatTreeUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
@@ -34,6 +41,7 @@ public class FlatTreeCollapsedIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final boolean chevron;
|
||||
private Path2D path;
|
||||
|
||||
public FlatTreeCollapsedIcon() {
|
||||
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
||||
@@ -46,19 +54,54 @@ public class FlatTreeCollapsedIcon
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
setStyleColorFromTreeUI( c, g );
|
||||
rotate( c, g );
|
||||
|
||||
String arrowType = getStyleFromTreeUI( c, ui -> ui.iconArrowType );
|
||||
boolean chevron = (arrowType != null) ? FlatUIUtils.isChevron( arrowType ) : this.chevron;
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
void setStyleColorFromTreeUI( Component c, Graphics2D g ) {
|
||||
setStyleColorFromTreeUI( c, g, ui -> ui.iconCollapsedColor );
|
||||
}
|
||||
|
||||
void rotate( Component c, Graphics2D g ) {
|
||||
if( !c.getComponentOrientation().isLeftToRight() )
|
||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this icon is always shared for all trees,
|
||||
* get icon specific style from FlatTreeUI.
|
||||
*/
|
||||
static <T> T getStyleFromTreeUI( Component c, Function<FlatTreeUI, T> f ) {
|
||||
JTree tree = (c instanceof JTree)
|
||||
? (JTree) c
|
||||
: (JTree) SwingUtilities.getAncestorOfClass( JTree.class, c );
|
||||
if( tree != null ) {
|
||||
TreeUI ui = tree.getUI();
|
||||
if( ui instanceof FlatTreeUI )
|
||||
return f.apply( (FlatTreeUI) ui );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void setStyleColorFromTreeUI( Component c, Graphics2D g, Function<FlatTreeUI, Color> f ) {
|
||||
Color color = getStyleFromTreeUI( c, f );
|
||||
if( color != null )
|
||||
g.setColor( color );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ public class FlatTreeExpandedIcon
|
||||
super( UIManager.getColor( "Tree.icon.expandedColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
void setStyleColorFromTreeUI( Component c, Graphics2D g ) {
|
||||
setStyleColorFromTreeUI( c, g, ui -> ui.iconExpandedColor );
|
||||
}
|
||||
|
||||
@Override
|
||||
void rotate( Component c, Graphics2D g ) {
|
||||
g.rotate( Math.toRadians( 90 ), width / 2., height / 2. );
|
||||
|
||||
@@ -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}.
|
||||
@@ -37,16 +41,27 @@ public class FlatTreeLeafIcon
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconLeafColor );
|
||||
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<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,22 +34,50 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatTreeOpenIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatTreeOpenIcon() {
|
||||
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconOpenColor );
|
||||
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<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,40 +38,57 @@ 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
paintBackground( c, g );
|
||||
|
||||
g.setColor( getForeground( c ) );
|
||||
HiDPIUtils.paintAtScale1x( g, 0, 0, width, height, this::paintIconAt1x );
|
||||
}
|
||||
|
||||
protected abstract void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
||||
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
/** @since 3.5.2 */
|
||||
@Override
|
||||
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
|
||||
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 );
|
||||
|
||||
// fill background of whole component
|
||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.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 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
|
||||
*/
|
||||
interface EmptyPackage
|
||||
{
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -17,17 +17,15 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicArrowButton;
|
||||
|
||||
@@ -40,52 +38,38 @@ public class FlatArrowButton
|
||||
extends BasicArrowButton
|
||||
implements UIResource
|
||||
{
|
||||
public static final int DEFAULT_ARROW_WIDTH = 8;
|
||||
public static final int DEFAULT_ARROW_WIDTH = 9;
|
||||
|
||||
protected final boolean chevron;
|
||||
protected final Color foreground;
|
||||
protected final Color disabledForeground;
|
||||
protected final Color hoverForeground;
|
||||
protected final Color hoverBackground;
|
||||
protected final Color pressedForeground;
|
||||
protected final Color pressedBackground;
|
||||
protected boolean chevron;
|
||||
protected Color foreground;
|
||||
protected Color disabledForeground;
|
||||
protected Color hoverForeground;
|
||||
protected Color hoverBackground;
|
||||
protected Color pressedForeground;
|
||||
protected Color pressedBackground;
|
||||
|
||||
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
||||
private int xOffset = 0;
|
||||
private int yOffset = 0;
|
||||
private float arrowThickness = 1;
|
||||
private float xOffset = 0;
|
||||
private float yOffset = 0;
|
||||
private boolean roundBorderAutoXOffset = true;
|
||||
|
||||
private boolean hover;
|
||||
private boolean pressed;
|
||||
|
||||
public FlatArrowButton( int direction, String type, Color foreground, Color disabledForeground,
|
||||
Color hoverForeground, Color hoverBackground )
|
||||
{
|
||||
this( direction, type, foreground, disabledForeground, hoverForeground, hoverBackground, null );
|
||||
}
|
||||
|
||||
public FlatArrowButton( int direction, String type, Color foreground, Color disabledForeground,
|
||||
Color hoverForeground, Color hoverBackground, Color pressedBackground )
|
||||
{
|
||||
this( direction, type, foreground, disabledForeground, hoverForeground, hoverBackground, null, pressedBackground );
|
||||
}
|
||||
|
||||
public FlatArrowButton( int direction, String type, Color foreground, Color disabledForeground,
|
||||
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
||||
{
|
||||
super( direction, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE );
|
||||
|
||||
this.chevron = FlatUIUtils.isChevron( type );
|
||||
this.foreground = foreground;
|
||||
this.disabledForeground = disabledForeground;
|
||||
this.hoverForeground = hoverForeground;
|
||||
this.hoverBackground = hoverBackground;
|
||||
this.pressedForeground = pressedForeground;
|
||||
this.pressedBackground = pressedBackground;
|
||||
updateStyle( type, foreground, disabledForeground, hoverForeground, hoverBackground,
|
||||
pressedForeground, pressedBackground );
|
||||
|
||||
setOpaque( false );
|
||||
setBorder( null );
|
||||
|
||||
if( hoverForeground != null || hoverBackground != null || pressedBackground != null ) {
|
||||
if( hoverForeground != null || hoverBackground != null ||
|
||||
pressedForeground != null || pressedBackground != null )
|
||||
{
|
||||
addMouseListener( new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent e ) {
|
||||
@@ -101,19 +85,36 @@ 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();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public void updateStyle( String type, Color foreground, Color disabledForeground,
|
||||
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
||||
{
|
||||
this.chevron = FlatUIUtils.isChevron( type );
|
||||
this.foreground = foreground;
|
||||
this.disabledForeground = disabledForeground;
|
||||
this.hoverForeground = hoverForeground;
|
||||
this.hoverBackground = hoverBackground;
|
||||
this.pressedForeground = pressedForeground;
|
||||
this.pressedBackground = pressedBackground;
|
||||
}
|
||||
|
||||
public int getArrowWidth() {
|
||||
return arrowWidth;
|
||||
}
|
||||
@@ -122,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;
|
||||
}
|
||||
@@ -130,28 +141,53 @@ public class FlatArrowButton
|
||||
return pressed;
|
||||
}
|
||||
|
||||
public int getXOffset() {
|
||||
public float getXOffset() {
|
||||
return xOffset;
|
||||
}
|
||||
|
||||
public void setXOffset( int xOffset ) {
|
||||
public void setXOffset( float xOffset ) {
|
||||
this.xOffset = xOffset;
|
||||
}
|
||||
|
||||
public int getYOffset() {
|
||||
public float getYOffset() {
|
||||
return yOffset;
|
||||
}
|
||||
|
||||
public void setYOffset( int yOffset ) {
|
||||
public void setYOffset( float yOffset ) {
|
||||
this.yOffset = yOffset;
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
public boolean isRoundBorderAutoXOffset() {
|
||||
return roundBorderAutoXOffset;
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
public void setRoundBorderAutoXOffset( boolean roundBorderAutoXOffset ) {
|
||||
this.roundBorderAutoXOffset = roundBorderAutoXOffset;
|
||||
}
|
||||
|
||||
protected Color deriveBackground( Color background ) {
|
||||
return background;
|
||||
}
|
||||
|
||||
protected Color deriveForeground( Color foreground ) {
|
||||
return foreground;
|
||||
return FlatUIUtils.deriveColor( foreground, this.foreground );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color used to paint the arrow.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
protected Color getArrowColor() {
|
||||
return isEnabled()
|
||||
? (pressedForeground != null && isPressed()
|
||||
? pressedForeground
|
||||
: (hoverForeground != null && isHover()
|
||||
? hoverForeground
|
||||
: foreground))
|
||||
: disabledForeground;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,8 +202,7 @@ public class FlatArrowButton
|
||||
|
||||
@Override
|
||||
public void paint( Graphics g ) {
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||
|
||||
// paint hover or pressed background
|
||||
if( isEnabled() ) {
|
||||
@@ -179,19 +214,15 @@ public class FlatArrowButton
|
||||
|
||||
if( background != null ) {
|
||||
g.setColor( deriveBackground( background ) );
|
||||
paintBackground( g2 );
|
||||
paintBackground( (Graphics2D) g );
|
||||
}
|
||||
}
|
||||
|
||||
// paint arrow
|
||||
g.setColor( deriveForeground( isEnabled()
|
||||
? (pressedForeground != null && isPressed()
|
||||
? pressedForeground
|
||||
: (hoverForeground != null && isHover()
|
||||
? hoverForeground
|
||||
: foreground))
|
||||
: disabledForeground ) );
|
||||
paintArrow( g2 );
|
||||
g.setColor( deriveForeground( getArrowColor() ) );
|
||||
paintArrow( (Graphics2D) g );
|
||||
|
||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||
}
|
||||
|
||||
protected void paintBackground( Graphics2D g ) {
|
||||
@@ -199,73 +230,17 @@ public class FlatArrowButton
|
||||
}
|
||||
|
||||
protected void paintArrow( Graphics2D g ) {
|
||||
int direction = getDirection();
|
||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||
|
||||
// compute width/height
|
||||
int w = scale( arrowWidth + (chevron ? 0 : 1) );
|
||||
int h = scale( (arrowWidth / 2) + (chevron ? 0 : 1) );
|
||||
|
||||
// rotate width/height
|
||||
int rw = vert ? w : h;
|
||||
int rh = vert ? h : w;
|
||||
|
||||
// chevron lines end 1px outside of width/height
|
||||
if( chevron ) {
|
||||
// add 1px to width/height for position calculation only
|
||||
rw++;
|
||||
rh++;
|
||||
}
|
||||
|
||||
int x = Math.round( (getWidth() - rw) / 2f + scale( (float) xOffset ) );
|
||||
int y = Math.round( (getHeight() - rh) / 2f + scale( (float) yOffset ) );
|
||||
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 );
|
||||
|
||||
// paint arrow
|
||||
g.translate( x, y );
|
||||
/*debug
|
||||
debugPaint( g, vert, rw, rh );
|
||||
debug*/
|
||||
Shape arrowShape = createArrowShape( direction, chevron, w, h );
|
||||
if( chevron ) {
|
||||
g.setStroke( new BasicStroke( scale( 1f ) ) );
|
||||
g.draw( arrowShape );
|
||||
} else {
|
||||
// triangle
|
||||
g.fill( arrowShape );
|
||||
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 );
|
||||
}
|
||||
g.translate( -x, -y );
|
||||
}
|
||||
|
||||
public static Shape createArrowShape( int direction, boolean chevron, float w, float h ) {
|
||||
switch( direction ) {
|
||||
case NORTH: return FlatUIUtils.createPath( !chevron, 0,h, (w / 2f),0, w,h );
|
||||
case SOUTH: return FlatUIUtils.createPath( !chevron, 0,0, (w / 2f),h, w,0 );
|
||||
case WEST: return FlatUIUtils.createPath( !chevron, h,0, 0,(w / 2f), h,w );
|
||||
case EAST: return FlatUIUtils.createPath( !chevron, 0,0, h,(w / 2f), 0,w );
|
||||
default: return new Path2D.Float();
|
||||
}
|
||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron,
|
||||
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() );
|
||||
}
|
||||
|
||||
/*debug
|
||||
private void debugPaint( Graphics g, boolean vert, int w, int h ) {
|
||||
Color oldColor = g.getColor();
|
||||
g.setColor( Color.red );
|
||||
g.drawRect( 0, 0, w - 1, h - 1 );
|
||||
|
||||
int xy1 = -2;
|
||||
int xy2 = h + 1;
|
||||
for( int i = 0; i < 20; i++ ) {
|
||||
g.drawRect( vert ? 0 : xy1, vert ? xy1 : 0, 0, 0 );
|
||||
g.drawRect( vert ? 0 : xy2, vert ? xy2 : 0, 0, 0 );
|
||||
xy1 -= 2;
|
||||
xy2 += 2;
|
||||
}
|
||||
g.setColor( oldColor );
|
||||
}
|
||||
debug*/
|
||||
}
|
||||
|
||||
@@ -22,35 +22,34 @@ import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Paint;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicBorders;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
|
||||
/**
|
||||
* Border for various components (e.g. {@link javax.swing.JTextField}).
|
||||
*
|
||||
* <p>
|
||||
* There is empty space around the component border, if Component.focusWidth is greater than zero,
|
||||
* which is used to paint outer focus border.
|
||||
*
|
||||
* <p>
|
||||
* Because there is empty space (if outer focus border is not painted),
|
||||
* UI delegates that use this border (or subclasses) must invoke
|
||||
* {@link FlatUIUtils#paintParentBackground} to paint the empty space correctly.
|
||||
* {@link FlatUIUtils#paintParentBackground} to fill the empty space correctly.
|
||||
*
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.innerFocusWidth int or float
|
||||
* @uiDefault Component.innerOutlineWidth int or float
|
||||
* @uiDefault Component.borderWidth int or float
|
||||
*
|
||||
* @uiDefault Component.focusColor Color
|
||||
* @uiDefault Component.borderColor Color
|
||||
* @uiDefault Component.disabledBorderColor Color
|
||||
@@ -66,20 +65,46 @@ import com.formdev.flatlaf.util.DerivedColor;
|
||||
*/
|
||||
public class FlatBorder
|
||||
extends BasicBorders.MarginBorder
|
||||
implements StyleableBorder
|
||||
{
|
||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
||||
protected final float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||
protected final Color borderColor = UIManager.getColor( "Component.borderColor" );
|
||||
protected final Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
||||
protected final Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
||||
@Styleable protected int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
@Styleable protected float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
||||
@Styleable protected float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
||||
/** @since 2 */ @Styleable protected float borderWidth = FlatUIUtils.getUIFloat( "Component.borderWidth", 1 );
|
||||
|
||||
protected final Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
||||
protected final Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||
protected final Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||
protected final Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||
protected final Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||
@Styleable protected Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||
@Styleable protected Color borderColor = UIManager.getColor( "Component.borderColor" );
|
||||
@Styleable protected Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
||||
@Styleable protected Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
||||
|
||||
@Styleable(dot=true) protected Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
||||
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||
|
||||
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||
/** @since 2 */ @Styleable protected String outline;
|
||||
/** @since 2 */ @Styleable protected Color outlineColor;
|
||||
/** @since 2 */ @Styleable protected Color outlineFocusedColor;
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
@@ -88,24 +113,29 @@ public class FlatBorder
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
float focusWidth = scale( (float) getFocusWidth( c ) );
|
||||
float borderWidth = scale( (float) getBorderWidth( c ) );
|
||||
float focusInnerWidth = 0;
|
||||
float borderWidth = scale( getBorderWidth( c ) );
|
||||
float arc = scale( (float) getArc( c ) );
|
||||
Color outlineColor = getOutlineColor( c );
|
||||
Color focusColor = null;
|
||||
|
||||
// paint outer border
|
||||
if( outlineColor != null || isFocused( c ) ) {
|
||||
float innerWidth = !isCellEditor( c ) && !(c instanceof JScrollPane)
|
||||
? (outlineColor != null ? innerOutlineWidth : innerFocusWidth)
|
||||
? (outlineColor != null ? innerOutlineWidth : getInnerFocusWidth( c ))
|
||||
: 0;
|
||||
|
||||
g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) );
|
||||
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height,
|
||||
focusWidth, borderWidth + scale( innerWidth ), arc );
|
||||
if( focusWidth > 0 || innerWidth > 0 ) {
|
||||
focusColor = (outlineColor != null) ? outlineColor : getFocusColor( c );
|
||||
focusInnerWidth = borderWidth + scale( innerWidth );
|
||||
}
|
||||
}
|
||||
|
||||
// paint border
|
||||
g2.setPaint( (outlineColor != null) ? outlineColor : getBorderColor( c ) );
|
||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, focusWidth, borderWidth, arc );
|
||||
Paint borderColor = (outlineColor != null) ? outlineColor : getBorderColor( c );
|
||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||
focusWidth, 1, focusInnerWidth, borderWidth, arc,
|
||||
focusColor, borderColor, null, c instanceof JScrollPane );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
@@ -120,6 +150,17 @@ public class FlatBorder
|
||||
return null;
|
||||
|
||||
Object outline = ((JComponent)c).getClientProperty( FlatClientProperties.OUTLINE );
|
||||
if( outline == null )
|
||||
outline = this.outline;
|
||||
if( outline == null ) {
|
||||
if( outlineColor != null && outlineFocusedColor != null )
|
||||
outline = new Color[] { outlineFocusedColor, outlineColor };
|
||||
else if( outlineColor != null )
|
||||
outline = outlineColor;
|
||||
else if( outlineFocusedColor != null )
|
||||
outline = outlineFocusedColor;
|
||||
}
|
||||
|
||||
if( outline instanceof String ) {
|
||||
switch( (String) outline ) {
|
||||
case FlatClientProperties.OUTLINE_ERROR:
|
||||
@@ -153,47 +194,22 @@ 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;
|
||||
}
|
||||
|
||||
return c.isEnabled() && (!(c instanceof JTextComponent) || ((JTextComponent)c).isEditable());
|
||||
return c.isEnabled();
|
||||
}
|
||||
|
||||
protected boolean isFocused( Component c ) {
|
||||
if( c instanceof JScrollPane ) {
|
||||
JViewport viewport = ((JScrollPane)c).getViewport();
|
||||
Component view = (viewport != null) ? viewport.getView() : null;
|
||||
if( view != null ) {
|
||||
if( FlatUIUtils.isPermanentFocusOwner( view ) )
|
||||
return true;
|
||||
|
||||
if( (view instanceof JTable && ((JTable)view).isEditing()) ||
|
||||
(view instanceof JTree && ((JTree)view).isEditing()) )
|
||||
{
|
||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
if( focusOwner != null )
|
||||
return SwingUtilities.isDescendingFrom( focusOwner, view );
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if( c instanceof JComboBox && ((JComboBox<?>)c).isEditable() ) {
|
||||
Component editorComponent = ((JComboBox<?>)c).getEditor().getEditorComponent();
|
||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
||||
} else if( c instanceof JSpinner ) {
|
||||
if( FlatUIUtils.isPermanentFocusOwner( c ) )
|
||||
return true;
|
||||
|
||||
JComponent editor = ((JSpinner)c).getEditor();
|
||||
if( editor instanceof JSpinner.DefaultEditor ) {
|
||||
JTextField textField = ((JSpinner.DefaultEditor)editor).getTextField();
|
||||
if( textField != null )
|
||||
return FlatUIUtils.isPermanentFocusOwner( textField );
|
||||
}
|
||||
return false;
|
||||
} else
|
||||
if( c instanceof JScrollPane )
|
||||
return FlatScrollPaneUI.isPermanentFocusOwner( (JScrollPane) c );
|
||||
else if( c instanceof JComboBox )
|
||||
return FlatComboBoxUI.isPermanentFocusOwner( (JComboBox<?>) c );
|
||||
else if( c instanceof JSpinner )
|
||||
return FlatSpinnerUI.isPermanentFocusOwner( (JSpinner) c );
|
||||
else
|
||||
return FlatUIUtils.isPermanentFocusOwner( c );
|
||||
}
|
||||
|
||||
@@ -204,13 +220,14 @@ public class FlatBorder
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
float focusWidth = scale( (float) getFocusWidth( c ) );
|
||||
float ow = focusWidth + scale( (float) getLineWidth( c ) );
|
||||
int ow = Math.round( focusWidth + scale( (float) getLineWidth( c ) ) );
|
||||
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
insets.top = Math.round( scale( (float) insets.top ) + ow );
|
||||
insets.left = Math.round( scale( (float) insets.left ) + ow );
|
||||
insets.bottom = Math.round( scale( (float) insets.bottom ) + ow );
|
||||
insets.right = Math.round( scale( (float) insets.right ) + ow );
|
||||
|
||||
insets.top = scale( insets.top ) + ow;
|
||||
insets.left = scale( insets.left ) + ow;
|
||||
insets.bottom = scale( insets.bottom ) + ow;
|
||||
insets.right = scale( insets.right ) + ow;
|
||||
|
||||
if( isCellEditor( c ) ) {
|
||||
// remove top and bottom insets if used as cell editor
|
||||
@@ -236,6 +253,13 @@ public class FlatBorder
|
||||
return focusWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unscaled) thickness of the inner focus border.
|
||||
*/
|
||||
protected float getInnerFocusWidth( Component c ) {
|
||||
return innerFocusWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unscaled) line thickness used to compute the border insets.
|
||||
* This may be different to {@link #getBorderWidth}.
|
||||
@@ -248,12 +272,12 @@ public class FlatBorder
|
||||
* Returns the (unscaled) line thickness used to paint the border.
|
||||
* This may be different to {@link #getLineWidth}.
|
||||
*/
|
||||
protected int getBorderWidth( Component c ) {
|
||||
return getLineWidth( c );
|
||||
protected float getBorderWidth( Component c ) {
|
||||
return borderWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unscaled) arc diameter of the border.
|
||||
* Returns the (unscaled) arc diameter of the border corners.
|
||||
*/
|
||||
protected int getArc( Component c ) {
|
||||
return 0;
|
||||
|
||||
@@ -20,67 +20,131 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Paint;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Border for {@link javax.swing.JButton}.
|
||||
*
|
||||
* @uiDefault Button.arc int
|
||||
* @uiDefault Button.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
||||
* @uiDefault Button.borderWidth int or float optional; defaults to Component.borderWidth
|
||||
*
|
||||
* @uiDefault Button.borderColor Color
|
||||
* @uiDefault Button.startBorderColor Color optional; if set, a gradient paint is used and Button.borderColor is ignored
|
||||
* @uiDefault Button.endBorderColor Color optional; if set, a gradient paint is used
|
||||
* @uiDefault Button.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
|
||||
* @uiDefault Button.default.startBorderColor Color optional; if set, a gradient paint is used and Button.default.borderColor is ignored
|
||||
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
||||
* @uiDefault Button.default.hoverBorderColor Color optional
|
||||
* @uiDefault Button.default.focusedBorderColor Color
|
||||
* @uiDefault Button.default.focusColor Color
|
||||
* @uiDefault Button.borderWidth int
|
||||
* @uiDefault Button.default.borderWidth int
|
||||
* @uiDefault Button.default.pressedBorderColor Color optional
|
||||
* @uiDefault Button.default.hoverBorderColor Color optional
|
||||
*
|
||||
* @uiDefault Button.toolbar.focusWidth int or float optional; default is 1.5
|
||||
* @uiDefault Button.toolbar.focusColor Color optional; defaults to Component.focusColor
|
||||
* @uiDefault Button.toolbar.margin Insets
|
||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||
* @uiDefault Button.arc int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatButtonBorder
|
||||
extends FlatBorder
|
||||
{
|
||||
protected final Color borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
|
||||
protected final Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
||||
protected final Color disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
|
||||
protected final Color focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
|
||||
protected final Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
||||
protected final Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
||||
protected final Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
|
||||
protected final Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
||||
protected final Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
||||
protected final Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
||||
protected final int borderWidth = UIManager.getInt( "Button.borderWidth" );
|
||||
protected final int defaultBorderWidth = UIManager.getInt( "Button.default.borderWidth" );
|
||||
protected final Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
||||
protected final Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||
protected final int arc = UIManager.getInt( "Button.arc" );
|
||||
@Styleable protected int arc = UIManager.getInt( "Button.arc" );
|
||||
|
||||
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" );
|
||||
protected Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
|
||||
@Styleable(dot=true) protected Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
||||
@Styleable(dot=true) protected Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
||||
@Styleable(dot=true) protected Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
||||
/** @since 3.5 */ @Styleable(dot=true) protected Color defaultPressedBorderColor = UIManager.getColor( "Button.default.pressedBorderColor" );
|
||||
|
||||
/** @since 1.4 */ @Styleable(dot=true) protected float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f );
|
||||
/** @since 1.4 */ @Styleable(dot=true) protected Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" );
|
||||
@Styleable(dot=true) protected Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
||||
@Styleable(dot=true) protected Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||
|
||||
public FlatButtonBorder() {
|
||||
innerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth );
|
||||
borderWidth = FlatUIUtils.getUIFloat( "Button.borderWidth", borderWidth );
|
||||
|
||||
borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
|
||||
disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
|
||||
focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( FlatButtonUI.isContentAreaFilled( c ) &&
|
||||
!FlatButtonUI.isToolBarButton( c ) &&
|
||||
(!FlatButtonUI.isBorderlessButton( c ) || FlatUIUtils.isPermanentFocusOwner( c )) &&
|
||||
!FlatButtonUI.isHelpButton( c ) &&
|
||||
!FlatToggleButtonUI.isTabButton( c ) )
|
||||
super.paintBorder( c, g, x, y, width, height );
|
||||
else if( FlatButtonUI.isToolBarButton( c ) && isFocused( c ) )
|
||||
paintToolBarFocus( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
/** @since 1.4 */
|
||||
protected void paintToolBarFocus( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
float focusWidth = UIScale.scale( toolbarFocusWidth );
|
||||
float arc = UIScale.scale( (float) getArc( c ) );
|
||||
Color outlineColor = getOutlineColor( c );
|
||||
|
||||
Insets spacing = UIScale.scale( toolbarSpacingInsets );
|
||||
x += spacing.left;
|
||||
y += spacing.top;
|
||||
width -= spacing.left + spacing.right;
|
||||
height -= spacing.top + spacing.bottom;
|
||||
|
||||
Color color = (outlineColor != null) ? outlineColor : getFocusColor( c );
|
||||
// not using focus border painting of paintOutlinedComponent() here
|
||||
// because its round edges look too "thick"
|
||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height, 0, 0, 0, focusWidth, arc, null, color, null );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color getFocusColor( Component c ) {
|
||||
return FlatButtonUI.isDefaultButton( c ) ? defaultFocusColor : super.getFocusColor( c );
|
||||
return (toolbarFocusColor != null && FlatButtonUI.isToolBarButton( c ))
|
||||
? toolbarFocusColor
|
||||
: (FlatButtonUI.isDefaultButton( c ) ? defaultFocusColor : super.getFocusColor( c ));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,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;
|
||||
@@ -111,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;
|
||||
@@ -135,7 +200,7 @@ public class FlatButtonBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBorderWidth( Component c ) {
|
||||
protected float getBorderWidth( Component c ) {
|
||||
return FlatButtonUI.isDefaultButton( c ) ? defaultBorderWidth : borderWidth;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
@@ -28,22 +29,41 @@ 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;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.AbstractButton;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -65,20 +85,27 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
||||
* @uiDefault Button.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
|
||||
@@ -86,15 +113,21 @@ 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
|
||||
*/
|
||||
public class FlatButtonUI
|
||||
extends BasicButtonUI
|
||||
implements StyleableUI
|
||||
{
|
||||
protected int minimumWidth;
|
||||
@Styleable protected int minimumWidth;
|
||||
protected int iconTextGap;
|
||||
|
||||
protected Color background;
|
||||
@@ -102,38 +135,81 @@ public class FlatButtonUI
|
||||
|
||||
protected Color startBackground;
|
||||
protected Color endBackground;
|
||||
protected Color focusedBackground;
|
||||
protected Color hoverBackground;
|
||||
protected Color pressedBackground;
|
||||
protected Color selectedBackground;
|
||||
protected Color selectedForeground;
|
||||
protected Color disabledBackground;
|
||||
protected Color disabledText;
|
||||
protected Color disabledSelectedBackground;
|
||||
@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;
|
||||
|
||||
protected Color defaultBackground;
|
||||
@Styleable(dot=true) protected Color defaultBackground;
|
||||
protected Color defaultEndBackground;
|
||||
protected Color defaultForeground;
|
||||
protected Color defaultFocusedBackground;
|
||||
protected Color defaultHoverBackground;
|
||||
protected Color defaultPressedBackground;
|
||||
protected boolean defaultBoldText;
|
||||
@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;
|
||||
|
||||
protected int shadowWidth;
|
||||
protected Color shadowColor;
|
||||
protected Color defaultShadowColor;
|
||||
@Styleable protected boolean paintShadow;
|
||||
@Styleable protected int shadowWidth;
|
||||
@Styleable protected Color shadowColor;
|
||||
@Styleable(dot=true) protected Color defaultShadowColor;
|
||||
|
||||
protected Insets toolbarSpacingInsets;
|
||||
protected Color toolbarHoverBackground;
|
||||
protected Color toolbarPressedBackground;
|
||||
protected Color toolbarSelectedBackground;
|
||||
@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;
|
||||
/** @since 2 */ @Styleable protected boolean squareSize;
|
||||
/** @since 2 */ @Styleable protected int minimumHeight;
|
||||
|
||||
private Icon helpButtonIcon;
|
||||
private Insets defaultMargin;
|
||||
|
||||
private final boolean shared;
|
||||
private boolean helpButtonIconShared = true;
|
||||
private boolean defaults_initialized = false;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
private AtomicBoolean borderShared;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.createSharedUI( FlatButtonUI.class, FlatButtonUI::new );
|
||||
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||
? FlatUIUtils.createSharedUI( FlatButtonUI.class, () -> new FlatButtonUI( true ) )
|
||||
: new FlatButtonUI( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected FlatButtonUI( boolean shared ) {
|
||||
this.shared = shared;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
if( FlatUIUtils.needsLightAWTPeer( c ) )
|
||||
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
|
||||
else
|
||||
installUIImpl( c );
|
||||
}
|
||||
|
||||
private void installUIImpl( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installStyle( (AbstractButton) c );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,39 +228,47 @@ 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" );
|
||||
|
||||
if( UIManager.getBoolean( "Button.paintShadow" ) ) {
|
||||
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
|
||||
shadowColor = UIManager.getColor( "Button.shadowColor" );
|
||||
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||
} else {
|
||||
shadowWidth = 0;
|
||||
shadowColor = null;
|
||||
defaultShadowColor = null;
|
||||
}
|
||||
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" );
|
||||
|
||||
toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
|
||||
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
|
||||
shadowColor = UIManager.getColor( "Button.shadowColor" );
|
||||
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||
|
||||
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
||||
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" );
|
||||
|
||||
helpButtonIconShared = true;
|
||||
defaults_initialized = true;
|
||||
}
|
||||
|
||||
@@ -204,6 +288,9 @@ public class FlatButtonUI
|
||||
protected void uninstallDefaults( AbstractButton b ) {
|
||||
super.uninstallDefaults( b );
|
||||
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( b );
|
||||
defaults_initialized = false;
|
||||
}
|
||||
@@ -215,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:
|
||||
@@ -223,11 +314,91 @@ 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 installStyle() from installUI()
|
||||
b.updateUI();
|
||||
} else
|
||||
installStyle( b );
|
||||
b.revalidate();
|
||||
HiDPIUtils.repaint( b );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle( AbstractButton b ) {
|
||||
try {
|
||||
applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
String getStyleType() {
|
||||
return "Button";
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( AbstractButton b, Object style ) {
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style,
|
||||
(key, value) -> applyStyleProperty( b, key, value ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( AbstractButton b, String key, Object value ) {
|
||||
if( key.startsWith( "help." ) ) {
|
||||
if( !(helpButtonIcon instanceof FlatHelpButtonIcon) )
|
||||
return new UnknownStyleException( key );
|
||||
|
||||
if( helpButtonIconShared ) {
|
||||
helpButtonIcon = FlatStylingSupport.cloneIcon( helpButtonIcon );
|
||||
helpButtonIconShared = false;
|
||||
}
|
||||
|
||||
key = key.substring( "help.".length() );
|
||||
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
||||
}
|
||||
|
||||
if( "iconTextGap".equals( key ) && value instanceof Integer )
|
||||
value = UIScale.scale( (Integer) value );
|
||||
|
||||
if( borderShared == null )
|
||||
borderShared = new AtomicBoolean( true );
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, b, borderShared );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
Map<String, Class<?>> infos = FlatStylingSupport.getAnnotatedStyleableInfos( this, c.getBorder() );
|
||||
if( helpButtonIcon instanceof FlatHelpButtonIcon )
|
||||
FlatStylingSupport.putAllPrefixKey( infos, "help.", ((FlatHelpButtonIcon)helpButtonIcon).getStyleableInfos() );
|
||||
return infos;
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
if( key.startsWith( "help." ) ) {
|
||||
return (helpButtonIcon instanceof FlatHelpButtonIcon)
|
||||
? ((FlatHelpButtonIcon)helpButtonIcon).getStyleableValue( key.substring( "help.".length() ) )
|
||||
: null;
|
||||
}
|
||||
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, c.getBorder(), key );
|
||||
}
|
||||
|
||||
static boolean isContentAreaFilled( Component c ) {
|
||||
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
||||
}
|
||||
@@ -242,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) )
|
||||
@@ -251,7 +422,10 @@ public class FlatButtonUI
|
||||
Icon icon = ((AbstractButton)c).getIcon();
|
||||
String text = ((AbstractButton)c).getText();
|
||||
return (icon != null && (text == null || text.isEmpty())) ||
|
||||
(icon == null && text != null && ("...".equals( text ) || text.length() == 1));
|
||||
(icon == null && text != null &&
|
||||
("...".equals( text ) ||
|
||||
text.length() == 1 ||
|
||||
(text.length() == 2 && Character.isSurrogatePair( text.charAt( 0 ), text.charAt( 1 ) ))));
|
||||
}
|
||||
|
||||
static final int TYPE_OTHER = -1;
|
||||
@@ -262,11 +436,11 @@ public class FlatButtonUI
|
||||
if( !(c instanceof AbstractButton) )
|
||||
return TYPE_OTHER;
|
||||
|
||||
Object value = ((AbstractButton)c).getClientProperty( BUTTON_TYPE );
|
||||
if( !(value instanceof String) )
|
||||
String value = getButtonTypeStr( (AbstractButton) c );
|
||||
if( value == null )
|
||||
return TYPE_OTHER;
|
||||
|
||||
switch( (String) value ) {
|
||||
switch( value ) {
|
||||
case BUTTON_TYPE_SQUARE: return TYPE_SQUARE;
|
||||
case BUTTON_TYPE_ROUND_RECT: return TYPE_ROUND_RECT;
|
||||
default: return TYPE_OTHER;
|
||||
@@ -274,12 +448,27 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
static boolean isHelpButton( Component c ) {
|
||||
return c instanceof JButton && clientPropertyEquals( (JButton) c, BUTTON_TYPE, BUTTON_TYPE_HELP );
|
||||
return c instanceof JButton && BUTTON_TYPE_HELP.equals( getButtonTypeStr( (JButton) c ) );
|
||||
}
|
||||
|
||||
static boolean isToolBarButton( Component c ) {
|
||||
return c.getParent() instanceof JToolBar ||
|
||||
(c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON ));
|
||||
(c instanceof AbstractButton && BUTTON_TYPE_TOOLBAR_BUTTON.equals( getButtonTypeStr( (AbstractButton) c ) ));
|
||||
}
|
||||
|
||||
static boolean isBorderlessButton( Component c ) {
|
||||
return c instanceof AbstractButton && BUTTON_TYPE_BORDERLESS.equals( getButtonTypeStr( (AbstractButton) c ) );
|
||||
}
|
||||
|
||||
static String getButtonTypeStr( AbstractButton c ) {
|
||||
// get from client property
|
||||
Object value = c.getClientProperty( BUTTON_TYPE );
|
||||
if( value instanceof String )
|
||||
return (String) value;
|
||||
|
||||
// get from styling property
|
||||
ButtonUI ui = c.getUI();
|
||||
return (ui instanceof FlatButtonUI) ? ((FlatButtonUI)ui).buttonType : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -308,29 +497,48 @@ 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;
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
|
||||
if( isToolBarButton ) {
|
||||
Insets spacing = UIScale.scale( toolbarSpacingInsets );
|
||||
if( isToolBarButton && c.getBorder() instanceof FlatButtonBorder ) {
|
||||
Insets spacing = UIScale.scale( ((FlatButtonBorder)c.getBorder()).toolbarSpacingInsets );
|
||||
x += spacing.left;
|
||||
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( !isToolBarButton && shadowColor != null && shadowWidth > 0 && focusWidth > 0 &&
|
||||
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) && c.isEnabled() )
|
||||
if( paintShadow &&
|
||||
shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
||||
!isToolBarButton && !isBorderlessButton( c ) &&
|
||||
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) )
|
||||
{
|
||||
g2.setColor( shadowColor );
|
||||
g2.fill( new RoundRectangle2D.Float( focusWidth, focusWidth + UIScale.scale( (float) shadowWidth ),
|
||||
@@ -351,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
|
||||
@@ -385,42 +653,47 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
protected Color getBackground( JComponent c ) {
|
||||
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
||||
|
||||
// selected state
|
||||
if( ((AbstractButton)c).isSelected() ) {
|
||||
// in toolbar use same 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
|
||||
boolean toolBarButton = isToolBarButton( c );
|
||||
return buttonStateColor( c,
|
||||
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
||||
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
|
||||
null, null,
|
||||
toolBarButton
|
||||
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
|
||||
: disabledSelectedBackground,
|
||||
null,
|
||||
null,
|
||||
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
||||
}
|
||||
|
||||
if( !c.isEnabled() )
|
||||
return disabledBackground;
|
||||
|
||||
// toolbar button
|
||||
if( isToolBarButton( c ) ) {
|
||||
ButtonModel model = ((AbstractButton)c).getModel();
|
||||
if( model.isPressed() )
|
||||
return toolbarPressedBackground;
|
||||
if( model.isRollover() )
|
||||
return toolbarHoverBackground;
|
||||
|
||||
// use background of toolbar
|
||||
return c.getParent().getBackground();
|
||||
if( toolBarButton ) {
|
||||
Color bg = c.getBackground();
|
||||
return buttonStateColor( c,
|
||||
isCustomBackground( bg ) ? bg : null,
|
||||
null,
|
||||
null,
|
||||
toolbarHoverBackground,
|
||||
toolbarPressedBackground );
|
||||
}
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
return buttonStateColor( c,
|
||||
getBackgroundBase( c, def ),
|
||||
null,
|
||||
disabledBackground,
|
||||
isCustomBackground( c.getBackground() ) ? null : (def ? defaultFocusedBackground : focusedBackground),
|
||||
def ? defaultHoverBackground : hoverBackground,
|
||||
def ? defaultPressedBackground : pressedBackground );
|
||||
}
|
||||
|
||||
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 ) )
|
||||
@@ -436,16 +709,21 @@ public class FlatButtonUI
|
||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||
{
|
||||
AbstractButton b = (c instanceof AbstractButton) ? (AbstractButton) c : null;
|
||||
if( c == null )
|
||||
return enabledColor;
|
||||
|
||||
if( !c.isEnabled() )
|
||||
return disabledColor;
|
||||
|
||||
if( pressedColor != null && b != null && b.getModel().isPressed() )
|
||||
return pressedColor;
|
||||
if( c instanceof AbstractButton ) {
|
||||
ButtonModel model = ((AbstractButton)c).getModel();
|
||||
|
||||
if( hoverColor != null && b != null && b.getModel().isRollover() )
|
||||
return hoverColor;
|
||||
if( pressedColor != null && model.isPressed() )
|
||||
return pressedColor;
|
||||
|
||||
if( hoverColor != null && model.isRollover() )
|
||||
return hoverColor;
|
||||
}
|
||||
|
||||
if( focusedColor != null && isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c ) )
|
||||
return focusedColor;
|
||||
@@ -454,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 ) )
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -482,24 +791,112 @@ 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, false ) ) {
|
||||
if( clientPropertyBoolean( c, SQUARE_SIZE, squareSize ) ) {
|
||||
// make button square (increase width or height so that they are equal)
|
||||
prefSize.width = prefSize.height = Math.max( prefSize.width, prefSize.height );
|
||||
} else if( isIconOnlyOrSingleCharacter && ((AbstractButton)c).getIcon() == null ) {
|
||||
// make single-character-no-icon button square (increase width)
|
||||
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
||||
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
||||
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) &&
|
||||
c.getBorder() instanceof FlatButtonBorder && hasDefaultMargins( c ) )
|
||||
{
|
||||
// apply minimum width/height
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + Math.round( focusWidth * 2 ) );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + Math.round( focusWidth * 2 ) );
|
||||
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, minimumHeight ) ) + fw );
|
||||
}
|
||||
|
||||
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
|
||||
@@ -517,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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,27 @@ package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.DefaultCaret;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.Utilities;
|
||||
|
||||
/**
|
||||
* Caret that can select all text on focus gained.
|
||||
* Also fixes Swing's double-click-and-drag behavior so that dragging after
|
||||
* a double-click extends selection by whole words.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -35,12 +46,19 @@ public class FlatCaret
|
||||
extends DefaultCaret
|
||||
implements UIResource
|
||||
{
|
||||
private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo";
|
||||
|
||||
private final String selectAllOnFocusPolicy;
|
||||
private final boolean selectAllOnMouseClick;
|
||||
|
||||
private boolean inInstall;
|
||||
private boolean wasFocused;
|
||||
private boolean wasTemporaryLost;
|
||||
private boolean isMousePressed;
|
||||
private boolean isWordSelection;
|
||||
private boolean isLineSelection;
|
||||
private int dragSelectionStart;
|
||||
private int dragSelectionEnd;
|
||||
|
||||
public FlatCaret( String selectAllOnFocusPolicy, boolean selectAllOnMouseClick ) {
|
||||
this.selectAllOnFocusPolicy = selectAllOnFocusPolicy;
|
||||
@@ -49,21 +67,82 @@ public class FlatCaret
|
||||
|
||||
@Override
|
||||
public void install( JTextComponent c ) {
|
||||
super.install( c );
|
||||
// get caret info if switched theme
|
||||
long[] ci = (long[]) c.getClientProperty( KEY_CARET_INFO );
|
||||
if( ci != null ) {
|
||||
c.putClientProperty( KEY_CARET_INFO, null );
|
||||
|
||||
// the dot and mark are lost when switching LaF
|
||||
// --> move dot to end of text so that all text may be selected when it gains focus
|
||||
Document doc = c.getDocument();
|
||||
if( doc != null && getDot() == 0 && getMark() == 0 ) {
|
||||
int length = doc.getLength();
|
||||
if( length > 0 )
|
||||
setDot( length );
|
||||
// if caret info is too old assume that switched from FlatLaf
|
||||
// to another Laf and back to FlatLaf
|
||||
if( System.currentTimeMillis() - 500 > ci[3] )
|
||||
ci = null;
|
||||
}
|
||||
if( ci != null ) {
|
||||
// when switching theme, it is necessary to set blink rate before
|
||||
// invoking super.install() otherwise the caret does not blink
|
||||
setBlinkRate( (int) ci[2] );
|
||||
}
|
||||
|
||||
inInstall = true;
|
||||
try {
|
||||
super.install( c );
|
||||
} finally {
|
||||
inInstall = false;
|
||||
}
|
||||
|
||||
if( ci != null ) {
|
||||
// restore selection
|
||||
select( (int) ci[1], (int) ci[0] );
|
||||
|
||||
// if text component is focused, then caret and selection are visible,
|
||||
// but when switching theme, the component does not yet have
|
||||
// a highlighter and the selection is not painted
|
||||
// --> make selection temporary invisible later, then the caret
|
||||
// adds selection highlights to the text component highlighter
|
||||
if( isSelectionVisible() ) {
|
||||
EventQueue.invokeLater( () -> {
|
||||
if( getComponent() == null )
|
||||
return; // was deinstalled
|
||||
|
||||
if( isSelectionVisible() ) {
|
||||
setSelectionVisible( false );
|
||||
setSelectionVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deinstall( JTextComponent c ) {
|
||||
// remember dot and mark (the selection) when switching theme
|
||||
c.putClientProperty( KEY_CARET_INFO, new long[] {
|
||||
getDot(),
|
||||
getMark(),
|
||||
getBlinkRate(),
|
||||
System.currentTimeMillis(),
|
||||
} );
|
||||
|
||||
super.deinstall( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void adjustVisibility( Rectangle nloc ) {
|
||||
JTextComponent c = getComponent();
|
||||
if( c != null && c.getUI() instanceof FlatTextFieldUI ) {
|
||||
// need to fix x location because JTextField.scrollRectToVisible() uses insets.left
|
||||
// (as BasicTextUI.getVisibleEditorRect() does),
|
||||
// but FlatTextFieldUI.getVisibleEditorRect() may add some padding
|
||||
Rectangle r = ((FlatTextFieldUI)c.getUI()).getVisibleEditorRect();
|
||||
if( r != null )
|
||||
nloc.x -= r.x - c.getInsets().left;
|
||||
}
|
||||
super.adjustVisibility( nloc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
if( !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
|
||||
if( !inInstall && !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
|
||||
selectAllOnFocusGained();
|
||||
wasTemporaryLost = false;
|
||||
wasFocused = true;
|
||||
@@ -81,25 +160,83 @@ public class FlatCaret
|
||||
public void mousePressed( MouseEvent e ) {
|
||||
isMousePressed = true;
|
||||
super.mousePressed( e );
|
||||
|
||||
JTextComponent c = getComponent();
|
||||
|
||||
// left double-click starts word selection
|
||||
isWordSelection = e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) && !e.isConsumed();
|
||||
|
||||
// left triple-click starts line selection
|
||||
isLineSelection = e.getClickCount() == 3 && SwingUtilities.isLeftMouseButton( e ) && (!e.isConsumed() || c.getDragEnabled());
|
||||
|
||||
// select line
|
||||
// (this is also done in DefaultCaret.mouseClicked(), but this event is
|
||||
// sent when the mouse is released, which is too late for triple-click-and-drag)
|
||||
if( isLineSelection ) {
|
||||
ActionMap actionMap = c.getActionMap();
|
||||
Action selectLineAction = (actionMap != null)
|
||||
? actionMap.get( DefaultEditorKit.selectLineAction )
|
||||
: null;
|
||||
if( selectLineAction != null ) {
|
||||
selectLineAction.actionPerformed( new ActionEvent( c,
|
||||
ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// remember selection where word/line selection starts to keep it always selected while dragging
|
||||
if( isWordSelection || isLineSelection ) {
|
||||
int mark = getMark();
|
||||
int dot = getDot();
|
||||
dragSelectionStart = Math.min( dot, mark );
|
||||
dragSelectionEnd = Math.max( dot, mark );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
isMousePressed = false;
|
||||
isWordSelection = false;
|
||||
isLineSelection = false;
|
||||
super.mouseReleased( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged( MouseEvent e ) {
|
||||
if( (isWordSelection || isLineSelection) &&
|
||||
!e.isConsumed() && SwingUtilities.isLeftMouseButton( e ) )
|
||||
{
|
||||
// fix Swing's double/triple-click-and-drag behavior so that dragging after
|
||||
// a double/triple-click extends selection by whole words/lines
|
||||
JTextComponent c = getComponent();
|
||||
int pos = c.viewToModel( e.getPoint() );
|
||||
if( pos < 0 )
|
||||
return;
|
||||
|
||||
try {
|
||||
if( pos > dragSelectionEnd )
|
||||
select( dragSelectionStart, isWordSelection ? Utilities.getWordEnd( c, pos ) : Utilities.getRowEnd( c, pos ) );
|
||||
else if( pos < dragSelectionStart )
|
||||
select( dragSelectionEnd, isWordSelection ? Utilities.getWordStart( c, pos ) : Utilities.getRowStart( c, pos ) );
|
||||
else
|
||||
select( dragSelectionStart, dragSelectionEnd );
|
||||
} catch( BadLocationException ex ) {
|
||||
UIManager.getLookAndFeel().provideErrorFeedback( c );
|
||||
}
|
||||
} else
|
||||
super.mouseDragged( e );
|
||||
}
|
||||
|
||||
protected void selectAllOnFocusGained() {
|
||||
JTextComponent c = getComponent();
|
||||
Document doc = c.getDocument();
|
||||
if( doc == null || !c.isEnabled() || !c.isEditable() )
|
||||
if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) )
|
||||
return;
|
||||
|
||||
Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
||||
if( selectAllOnFocusPolicy == null )
|
||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
||||
|
||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
return;
|
||||
|
||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
||||
@@ -119,12 +256,41 @@ public class FlatCaret
|
||||
// select all
|
||||
if( c instanceof JFormattedTextField ) {
|
||||
EventQueue.invokeLater( () -> {
|
||||
setDot( 0 );
|
||||
moveDot( 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 {
|
||||
setDot( 0 );
|
||||
moveDot( doc.getLength() );
|
||||
select( 0, doc.getLength() );
|
||||
}
|
||||
}
|
||||
|
||||
private void select( int mark, int dot ) {
|
||||
if( mark != getMark() )
|
||||
setDot( mark );
|
||||
if( dot != getDot() )
|
||||
moveDot( dot );
|
||||
}
|
||||
|
||||
/** @since 1.4 */
|
||||
public void scrollCaretToVisible() {
|
||||
JTextComponent c = getComponent();
|
||||
if( c == null || c.getUI() == null )
|
||||
return;
|
||||
|
||||
try {
|
||||
Rectangle loc = c.getUI().modelToView( c, getDot(), getDotBias() );
|
||||
if( loc != null ) {
|
||||
adjustVisibility( loc );
|
||||
damage( loc );
|
||||
}
|
||||
} catch( BadLocationException ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,20 @@ package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.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.util.LoggingFacade;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JCheckBoxMenuItem}.
|
||||
@@ -52,15 +61,30 @@ import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||
*
|
||||
* @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, StyleableLookupProvider
|
||||
{
|
||||
private FlatMenuItemRenderer renderer;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatCheckBoxMenuItemUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
@@ -74,13 +98,69 @@ 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 FlatHTML.createPropertyChangeListener(
|
||||
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||
super.createPropertyChangeListener( c ) ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "CheckBoxMenuItem" ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( Object style ) {
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatMenuItemUI.getStyleableInfos( this, renderer );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatMenuItemUI.getStyleableValue( this, renderer, key );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public MethodHandles.Lookup getLookupForStyling() {
|
||||
// MethodHandles.lookup() is caller sensitive and must be invoked in this class,
|
||||
// otherwise it is not possible to access protected fields in JRE superclass
|
||||
return MethodHandles.lookup();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||
return renderer.getPreferredMenuItemSize();
|
||||
|
||||
@@ -43,11 +43,24 @@ public class FlatCheckBoxUI
|
||||
extends FlatRadioButtonUI
|
||||
{
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, FlatCheckBoxUI::new );
|
||||
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||
? FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, () -> new FlatCheckBoxUI( true ) )
|
||||
: new FlatCheckBoxUI( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected FlatCheckBoxUI( boolean shared ) {
|
||||
super( shared );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyPrefix() {
|
||||
return "CheckBox.";
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
String getStyleType() {
|
||||
return "CheckBox";
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
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.Image;
|
||||
import java.awt.Insets;
|
||||
@@ -28,11 +30,13 @@ import java.awt.Point;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyVetoException;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDesktopPane;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import javax.swing.JLabel;
|
||||
@@ -45,6 +49,7 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicDesktopIconUI;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -75,11 +80,21 @@ public class FlatDesktopIconUI
|
||||
private JToolTip titleTip;
|
||||
private ActionListener closeListener;
|
||||
private MouseInputListener mouseInputListener;
|
||||
private PropertyChangeListener ancestorListener;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatDesktopIconUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
// update dock icon preview if already iconified
|
||||
if( c.isDisplayable() )
|
||||
updateDockIconPreviewLater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
@@ -136,6 +151,17 @@ public class FlatDesktopIconUI
|
||||
};
|
||||
closeButton.addActionListener( closeListener );
|
||||
closeButton.addMouseListener( mouseInputListener );
|
||||
|
||||
ancestorListener = e -> {
|
||||
if( e.getNewValue() != null ) {
|
||||
// update dock icon preview if desktopIcon is added to desktop (internal frame was iconified)
|
||||
updateDockIconPreviewLater();
|
||||
} else {
|
||||
// remove preview icon to release memory
|
||||
dockIcon.setIcon( null );
|
||||
}
|
||||
};
|
||||
desktopIcon.addPropertyChangeListener( "ancestor", ancestorListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,6 +172,9 @@ public class FlatDesktopIconUI
|
||||
closeButton.removeMouseListener( mouseInputListener );
|
||||
closeListener = null;
|
||||
mouseInputListener = null;
|
||||
|
||||
desktopIcon.removePropertyChangeListener( "ancestor", ancestorListener );
|
||||
ancestorListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -228,15 +257,30 @@ public class FlatDesktopIconUI
|
||||
return getPreferredSize( c );
|
||||
}
|
||||
|
||||
void updateDockIcon() {
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
if( c.isOpaque() ) {
|
||||
// fill background with color derived from desktop pane
|
||||
Color background = c.getBackground();
|
||||
JDesktopPane desktopPane = desktopIcon.getDesktopPane();
|
||||
g.setColor( (desktopPane != null)
|
||||
? FlatUIUtils.deriveColor( background, desktopPane.getBackground() )
|
||||
: background );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
}
|
||||
|
||||
paint( g, c );
|
||||
}
|
||||
|
||||
private void updateDockIconPreviewLater() {
|
||||
// use invoke later to make sure that components are updated when switching LaF
|
||||
EventQueue.invokeLater( () -> {
|
||||
if( dockIcon != null )
|
||||
updateDockIconLater();
|
||||
updateDockIconPreview();
|
||||
} );
|
||||
}
|
||||
|
||||
private void updateDockIconLater() {
|
||||
protected void updateDockIconPreview() {
|
||||
// make sure that frame is not selected
|
||||
if( frame.isSelected() ) {
|
||||
try {
|
||||
@@ -246,13 +290,22 @@ public class FlatDesktopIconUI
|
||||
}
|
||||
}
|
||||
|
||||
// layout internal frame title pane, which was recreated when switching Laf
|
||||
// (directly invoke doLayout() because frame.validate() does not work here
|
||||
// because frame is not displayable)
|
||||
if( !frame.isValid() )
|
||||
frame.doLayout();
|
||||
for( Component c : frame.getComponents() ) {
|
||||
if( !c.isValid() )
|
||||
c.doLayout();
|
||||
}
|
||||
|
||||
// paint internal frame to buffered image
|
||||
int frameWidth = Math.max( frame.getWidth(), 1 );
|
||||
int frameHeight = Math.max( frame.getHeight(), 1 );
|
||||
BufferedImage frameImage = new BufferedImage( frameWidth, frameHeight, BufferedImage.TYPE_INT_ARGB );
|
||||
Graphics2D g = frameImage.createGraphics();
|
||||
try {
|
||||
//TODO fix missing internal frame header when switching LaF
|
||||
frame.paint( g );
|
||||
} finally {
|
||||
g.dispose();
|
||||
@@ -270,6 +323,27 @@ public class FlatDesktopIconUI
|
||||
|
||||
// scale preview
|
||||
Image previewImage = frameImage.getScaledInstance( previewWidth, previewHeight, Image.SCALE_SMOOTH );
|
||||
if( MultiResolutionImageSupport.isAvailable() ) {
|
||||
// On HiDPI screens, create preview images for 1x, 2x and current scale factor.
|
||||
// The icon then chooses the best resolution for painting, which is usually
|
||||
// the one for the current scale factor. But if changing scale factor or
|
||||
// moving window to another screen with different scale factor, then another
|
||||
// resolution may be used because the preview icon is not updated.
|
||||
Image previewImage2x = frameImage.getScaledInstance( previewWidth * 2, previewHeight * 2, Image.SCALE_SMOOTH );
|
||||
double scaleFactor = UIScale.getSystemScaleFactor( desktopIcon.getGraphicsConfiguration() );
|
||||
if( scaleFactor != 1 && scaleFactor != 2 ) {
|
||||
Image previewImageCurrent = frameImage.getScaledInstance(
|
||||
(int) Math.round( previewWidth * scaleFactor ),
|
||||
(int) Math.round( previewHeight * scaleFactor ),
|
||||
Image.SCALE_SMOOTH );
|
||||
|
||||
// the images must be ordered by resolution
|
||||
previewImage = (scaleFactor < 2)
|
||||
? MultiResolutionImageSupport.create( 0, previewImage, previewImageCurrent, previewImage2x )
|
||||
: MultiResolutionImageSupport.create( 0, previewImage, previewImage2x, previewImageCurrent );
|
||||
} else
|
||||
previewImage = MultiResolutionImageSupport.create( 0, previewImage, previewImage2x );
|
||||
}
|
||||
dockIcon.setIcon( new ImageIcon( previewImage ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import javax.swing.DefaultDesktopManager;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JInternalFrame.JDesktopIcon;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicDesktopPaneUI;
|
||||
|
||||
/**
|
||||
@@ -36,30 +41,96 @@ import javax.swing.plaf.basic.BasicDesktopPaneUI;
|
||||
public class FlatDesktopPaneUI
|
||||
extends BasicDesktopPaneUI
|
||||
{
|
||||
private LayoutDockListener layoutDockListener;
|
||||
private boolean layoutDockPending;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatDesktopPaneUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDesktopManager() {
|
||||
desktopManager = desktop.getDesktopManager();
|
||||
if( desktopManager == null ) {
|
||||
desktopManager = new FlatDesktopManager();
|
||||
desktop.setDesktopManager( desktopManager );
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
layoutDockLaterOnce();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
|
||||
layoutDockListener = new LayoutDockListener();
|
||||
desktop.addContainerListener( layoutDockListener );
|
||||
desktop.addComponentListener( layoutDockListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners() {
|
||||
super.uninstallListeners();
|
||||
|
||||
desktop.removeContainerListener( layoutDockListener );
|
||||
desktop.removeComponentListener( layoutDockListener );
|
||||
layoutDockListener = null;
|
||||
}
|
||||
|
||||
private void layoutDockLaterOnce() {
|
||||
if( layoutDockPending )
|
||||
return;
|
||||
layoutDockPending = true;
|
||||
|
||||
EventQueue.invokeLater( () -> {
|
||||
layoutDockPending = false;
|
||||
if( desktop != null )
|
||||
layoutDock();
|
||||
} );
|
||||
}
|
||||
|
||||
protected void layoutDock() {
|
||||
Dimension desktopSize = desktop.getSize();
|
||||
int x = 0;
|
||||
int y = desktopSize.height;
|
||||
int rowHeight = 0;
|
||||
|
||||
for( Component c : desktop.getComponents() ) {
|
||||
if( !(c instanceof JDesktopIcon) )
|
||||
continue;
|
||||
|
||||
JDesktopIcon icon = (JDesktopIcon) c;
|
||||
Dimension iconSize = icon.getPreferredSize();
|
||||
|
||||
if( x + iconSize.width > desktopSize.width ) {
|
||||
// new row
|
||||
x = 0;
|
||||
y -= rowHeight;
|
||||
rowHeight = 0;
|
||||
}
|
||||
|
||||
icon.setLocation( x, y - iconSize.height );
|
||||
|
||||
x += iconSize.width;
|
||||
rowHeight = Math.max( iconSize.height, rowHeight );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatDesktopManager -------------------------------------------
|
||||
//---- class LayoutDockListener -------------------------------------------
|
||||
|
||||
private class FlatDesktopManager
|
||||
extends DefaultDesktopManager
|
||||
implements UIResource
|
||||
private class LayoutDockListener
|
||||
extends ComponentAdapter
|
||||
implements ContainerListener
|
||||
{
|
||||
@Override
|
||||
public void iconifyFrame( JInternalFrame f ) {
|
||||
super.iconifyFrame( f );
|
||||
public void componentAdded( ContainerEvent e ) {
|
||||
layoutDockLaterOnce();
|
||||
}
|
||||
|
||||
((FlatDesktopIconUI)f.getDesktopIcon().getUI()).updateDockIcon();
|
||||
@Override
|
||||
public void componentRemoved( ContainerEvent e ) {
|
||||
layoutDockLaterOnce();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized( ComponentEvent e ) {
|
||||
layoutDockLaterOnce();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.RadialGradientPaint;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Map;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
@@ -40,14 +43,17 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*/
|
||||
public class FlatDropShadowBorder
|
||||
extends FlatEmptyBorder
|
||||
implements StyleableBorder
|
||||
{
|
||||
private final Color shadowColor;
|
||||
private final Insets shadowInsets;
|
||||
private final float shadowOpacity;
|
||||
@Styleable protected Color shadowColor;
|
||||
@Styleable protected Insets shadowInsets;
|
||||
@Styleable protected float shadowOpacity;
|
||||
|
||||
private final int shadowSize;
|
||||
private int shadowSize;
|
||||
private Image shadowImage;
|
||||
private Color lastShadowColor;
|
||||
private float lastShadowOpacity;
|
||||
private int lastShadowSize;
|
||||
private double lastSystemScaleFactor;
|
||||
private float lastUserScaleFactor;
|
||||
|
||||
@@ -64,17 +70,49 @@ public class FlatDropShadowBorder
|
||||
}
|
||||
|
||||
public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) {
|
||||
super( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ),
|
||||
Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) );
|
||||
super( nonNegativeInsets( shadowInsets ) );
|
||||
|
||||
this.shadowColor = shadowColor;
|
||||
this.shadowInsets = shadowInsets;
|
||||
this.shadowOpacity = shadowOpacity;
|
||||
|
||||
shadowSize = Math.max(
|
||||
shadowSize = maxInset( shadowInsets );
|
||||
}
|
||||
|
||||
private static Insets nonNegativeInsets( Insets shadowInsets ) {
|
||||
return new Insets( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ),
|
||||
Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) );
|
||||
}
|
||||
|
||||
private int maxInset( Insets shadowInsets ) {
|
||||
return Math.max(
|
||||
Math.max( shadowInsets.left, shadowInsets.right ),
|
||||
Math.max( shadowInsets.top, shadowInsets.bottom ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
Object oldValue = FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
if( key.equals( "shadowInsets" ) ) {
|
||||
applyStyleProperty( nonNegativeInsets( shadowInsets ) );
|
||||
shadowSize = maxInset( shadowInsets );
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( shadowSize <= 0 )
|
||||
@@ -91,12 +129,16 @@ public class FlatDropShadowBorder
|
||||
float userScaleFactor = UIScale.getUserScaleFactor();
|
||||
if( shadowImage == null ||
|
||||
!shadowColor.equals( lastShadowColor ) ||
|
||||
lastShadowOpacity != shadowOpacity ||
|
||||
lastShadowSize != shadowSize ||
|
||||
lastSystemScaleFactor != scaleFactor ||
|
||||
lastUserScaleFactor != userScaleFactor )
|
||||
{
|
||||
shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity,
|
||||
(float) (scaleFactor * userScaleFactor) );
|
||||
lastShadowColor = shadowColor;
|
||||
lastShadowOpacity = shadowOpacity;
|
||||
lastShadowSize = shadowSize;
|
||||
lastSystemScaleFactor = scaleFactor;
|
||||
lastUserScaleFactor = userScaleFactor;
|
||||
}
|
||||
|
||||
@@ -17,19 +17,26 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
||||
import javax.swing.text.Caret;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
||||
@@ -37,8 +44,8 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
* <!-- 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
|
||||
@@ -52,28 +59,52 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
* <!-- FlatEditorPaneUI -->
|
||||
*
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault EditorPane.focusedBackground Color optional
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatEditorPaneUI
|
||||
extends BasicEditorPaneUI
|
||||
implements StyleableUI
|
||||
{
|
||||
protected int minimumWidth;
|
||||
protected boolean isIntelliJTheme;
|
||||
@Styleable protected int minimumWidth;
|
||||
private Color background;
|
||||
@Styleable protected Color disabledBackground;
|
||||
@Styleable protected Color inactiveBackground;
|
||||
@Styleable protected Color focusedBackground;
|
||||
|
||||
private Color oldDisabledBackground;
|
||||
private Color oldInactiveBackground;
|
||||
|
||||
private Insets defaultMargin;
|
||||
|
||||
private Object oldHonorDisplayProperties;
|
||||
private FocusListener focusListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatEditorPaneUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
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" );
|
||||
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
|
||||
|
||||
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
||||
|
||||
// use component font and foreground for HTML text
|
||||
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
|
||||
@@ -84,34 +115,124 @@ public class FlatEditorPaneUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
background = null;
|
||||
disabledBackground = null;
|
||||
inactiveBackground = null;
|
||||
focusedBackground = null;
|
||||
|
||||
oldDisabledBackground = null;
|
||||
oldInactiveBackground = null;
|
||||
|
||||
oldStyleValues = null;
|
||||
|
||||
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
propertyChange( getComponent(), e );
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
|
||||
// necessary to update focus background
|
||||
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), c -> focusedBackground != null );
|
||||
getComponent().addFocusListener( focusListener );
|
||||
}
|
||||
|
||||
static void propertyChange( JTextComponent c, PropertyChangeEvent e ) {
|
||||
@Override
|
||||
protected void uninstallListeners() {
|
||||
super.uninstallListeners();
|
||||
|
||||
getComponent().removeFocusListener( focusListener );
|
||||
focusListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Caret createCaret() {
|
||||
return new FlatCaret( null, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void propertyChange( PropertyChangeEvent e ) {
|
||||
// invoke updateBackground() before super.propertyChange()
|
||||
String propertyName = e.getPropertyName();
|
||||
if( "editable".equals( propertyName ) || "enabled".equals( propertyName ) )
|
||||
updateBackground();
|
||||
|
||||
super.propertyChange( e );
|
||||
propertyChange( getComponent(), e, this::installStyle );
|
||||
}
|
||||
|
||||
static void propertyChange( JTextComponent c, PropertyChangeEvent e, Runnable installStyle ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.MINIMUM_WIDTH:
|
||||
c.revalidate();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.STYLE:
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
installStyle.run();
|
||||
c.revalidate();
|
||||
HiDPIUtils.repaint( c );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "EditorPane" ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( Object style ) {
|
||||
oldDisabledBackground = disabledBackground;
|
||||
oldInactiveBackground = inactiveBackground;
|
||||
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||
|
||||
updateBackground();
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, getComponent(), key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
private void updateBackground() {
|
||||
FlatTextFieldUI.updateBackground( getComponent(), background,
|
||||
disabledBackground, inactiveBackground,
|
||||
oldDisabledBackground, oldInactiveBackground );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
|
||||
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth, defaultMargin );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
||||
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth, defaultMargin );
|
||||
}
|
||||
|
||||
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
|
||||
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth, Insets defaultMargin ) {
|
||||
// do not apply minimum width if JTextComponent.margin is set
|
||||
if( !FlatTextFieldUI.hasDefaultMargins( c, defaultMargin ) )
|
||||
return size;
|
||||
|
||||
// Assume that text area is in a scroll pane (that displays the border)
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
@@ -128,14 +249,11 @@ public class FlatEditorPaneUI
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g ) {
|
||||
JTextComponent c = getComponent();
|
||||
paintBackground( g, getComponent(), focusedBackground );
|
||||
}
|
||||
|
||||
// for compatibility with IntelliJ themes
|
||||
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) && (c.getBackground() instanceof UIResource) ) {
|
||||
FlatUIUtils.paintParentBackground( g, c );
|
||||
return;
|
||||
}
|
||||
|
||||
super.paintBackground( g );
|
||||
static void paintBackground( Graphics g, JTextComponent c, Color focusedBackground ) {
|
||||
g.setColor( FlatTextFieldUI.getBackground( c, focusedBackground ) );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,13 @@ public class FlatEmptyBorder
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
boolean leftToRight = left == right || c.getComponentOrientation().isLeftToRight();
|
||||
return scaleInsets( c, insets, top, left, bottom, right );
|
||||
}
|
||||
|
||||
protected static Insets scaleInsets( Component c, Insets insets,
|
||||
int top, int left, int bottom, int right )
|
||||
{
|
||||
boolean leftToRight = left == right || c == null || c.getComponentOrientation().isLeftToRight();
|
||||
insets.left = scale( leftToRight ? left : right );
|
||||
insets.top = scale( top );
|
||||
insets.right = scale( leftToRight ? right : left );
|
||||
@@ -61,4 +67,18 @@ public class FlatEmptyBorder
|
||||
public Insets getUnscaledBorderInsets() {
|
||||
return super.getBorderInsets();
|
||||
}
|
||||
|
||||
public Object applyStyleProperty( Insets insets ) {
|
||||
Insets oldInsets = getUnscaledBorderInsets();
|
||||
top = insets.top;
|
||||
left = insets.left;
|
||||
bottom = insets.bottom;
|
||||
right = insets.right;
|
||||
return oldInsets;
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Insets getStyleableValue() {
|
||||
return new Insets( top, left, bottom, right );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,24 @@ package com.formdev.flatlaf.ui;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.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;
|
||||
@@ -31,13 +44,23 @@ import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFileChooser;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -129,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 );
|
||||
@@ -149,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 ) {
|
||||
@@ -188,11 +244,98 @@ 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
|
||||
protected JPanel createDetailsView( JFileChooser fc ) {
|
||||
JPanel p = super.createDetailsView( fc );
|
||||
|
||||
if( !SystemInfo.isWindows )
|
||||
return p;
|
||||
|
||||
// find scroll pane
|
||||
JScrollPane scrollPane = null;
|
||||
for( Component c : p.getComponents() ) {
|
||||
if( c instanceof JScrollPane ) {
|
||||
scrollPane = (JScrollPane) c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( scrollPane == null )
|
||||
return p;
|
||||
|
||||
// get scroll view, which should be a table
|
||||
Component view = scrollPane.getViewport().getView();
|
||||
if( !(view instanceof JTable) )
|
||||
return p;
|
||||
|
||||
JTable table = (JTable) view;
|
||||
|
||||
// on Windows 10, the date may contain left-to-right (0x200e) and right-to-left (0x200f)
|
||||
// mark characters (see https://en.wikipedia.org/wiki/Left-to-right_mark)
|
||||
// when the "current user" item is selected in the "look in" combobox
|
||||
// --> remove them
|
||||
TableCellRenderer defaultRenderer = table.getDefaultRenderer( Object.class );
|
||||
table.setDefaultRenderer( Object.class, new TableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
|
||||
boolean hasFocus, int row, int column )
|
||||
{
|
||||
// remove left-to-right and right-to-left mark characters
|
||||
if( value instanceof String && ((String)value).startsWith( "\u200e" ) ) {
|
||||
String str = (String) value;
|
||||
char[] buf = new char[str.length()];
|
||||
int j = 0;
|
||||
for( int i = 0; i < buf.length; i++ ) {
|
||||
char ch = str.charAt( i );
|
||||
if( ch != '\u200e' && ch != '\u200f' )
|
||||
buf[j++] = ch;
|
||||
}
|
||||
value = new String( buf, 0, j );
|
||||
}
|
||||
|
||||
return defaultRenderer.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
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
|
||||
@@ -202,12 +345,23 @@ public class FlatFileChooserUI
|
||||
|
||||
@Override
|
||||
public FileView getFileView( JFileChooser fc ) {
|
||||
return fileView;
|
||||
return doNotUseSystemIcons() ? super.getFileView( fc ) : fileView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearIconCache() {
|
||||
fileView.clearIconCache();
|
||||
if( doNotUseSystemIcons() )
|
||||
super.clearIconCache();
|
||||
else
|
||||
fileView.clearIconCache();
|
||||
}
|
||||
|
||||
private static boolean doNotUseSystemIcons() {
|
||||
// Java 17 32bit craches on Windows when using system icons
|
||||
// fixed in Java 18+, fix backported in Java 17.0.3+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
||||
return SystemInfo.isWindows &&
|
||||
SystemInfo.isX86 &&
|
||||
(SystemInfo.isJava_17_orLater && SystemInfo.javaVersion < SystemInfo.toVersion( 17, 0, 3, 0 ));
|
||||
}
|
||||
|
||||
//---- class FlatFileView -------------------------------------------------
|
||||
@@ -224,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 )
|
||||
@@ -245,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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,10 @@ import javax.swing.plaf.ComponentUI;
|
||||
*
|
||||
* <!-- FlatTextFieldUI -->
|
||||
*
|
||||
* @uiDefault TextComponent.arc int
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault FormattedTextField.placeholderForeground Color
|
||||
* @uiDefault FormattedTextField.focusedBackground Color optional
|
||||
* @uiDefault FormattedTextField.iconTextGap int optional, default is 4
|
||||
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
||||
* @uiDefault TextComponent.selectAllOnMouseClick boolean
|
||||
*
|
||||
@@ -60,4 +59,10 @@ public class FlatFormattedTextFieldUI
|
||||
protected String getPropertyPrefix() {
|
||||
return "FormattedTextField";
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
String getStyleType() {
|
||||
return "FormattedTextField";
|
||||
}
|
||||
}
|
||||
|
||||
289
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
289
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JToolTip;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.LabelView;
|
||||
import javax.swing.text.Style;
|
||||
import javax.swing.text.StyleConstants;
|
||||
import javax.swing.text.View;
|
||||
import javax.swing.text.html.CSS;
|
||||
import javax.swing.text.html.HTMLDocument;
|
||||
import javax.swing.text.html.StyleSheet;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
* @since 3.5
|
||||
*/
|
||||
public class FlatHTML
|
||||
{
|
||||
private FlatHTML() {}
|
||||
|
||||
/**
|
||||
* Adds CSS rule BASE_SIZE to the style sheet of the HTML view,
|
||||
* which re-calculates font sizes based on current component font size.
|
||||
* This is necessary for "absolute-size" keywords (e.g. "x-large")
|
||||
* for "font-size" attributes in default style sheet (see javax/swing/text/html/default.css).
|
||||
* See also <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values">CSS font-size</a>.
|
||||
* <p>
|
||||
* This method should be invoked after {@link BasicHTML#updateRenderer(JComponent, String)}.
|
||||
*/
|
||||
public static void updateRendererCSSFontBaseSize( JComponent c ) {
|
||||
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||
if( view == null )
|
||||
return;
|
||||
|
||||
// dumpViews( view, 0 );
|
||||
|
||||
Document doc = view.getDocument();
|
||||
if( !(doc instanceof HTMLDocument) )
|
||||
return;
|
||||
|
||||
// add BASE_SIZE rule if necessary
|
||||
// - if point size at index 7 is not 36, then probably HTML text contains BASE_SIZE rule
|
||||
// - if point size at index 4 is equal to given font size, then it is not necessary to add BASE_SIZE rule
|
||||
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
|
||||
/*debug
|
||||
for( int i = 1; i <= 7; i++ )
|
||||
System.out.println( i+": "+ styleSheet.getPointSize( i ) );
|
||||
debug*/
|
||||
int fontBaseSize = c.getFont().getSize();
|
||||
if( styleSheet.getPointSize( 7 ) != 36f ||
|
||||
styleSheet.getPointSize( 4 ) == fontBaseSize )
|
||||
return;
|
||||
|
||||
// check whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
|
||||
if( !usesAbsoluteSizeKeywordForFontSize( view ) )
|
||||
return;
|
||||
|
||||
// get HTML text from component
|
||||
String text;
|
||||
if( c instanceof JLabel )
|
||||
text = ((JLabel)c).getText();
|
||||
else if( c instanceof AbstractButton )
|
||||
text = ((AbstractButton)c).getText();
|
||||
else if( c instanceof JToolTip )
|
||||
text = ((JToolTip)c).getTipText();
|
||||
else
|
||||
return;
|
||||
if( text == null || !BasicHTML.isHTMLString( text ) )
|
||||
return;
|
||||
|
||||
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
||||
String openTag = "";
|
||||
String closeTag = "";
|
||||
|
||||
int headIndex;
|
||||
int styleIndex;
|
||||
|
||||
int insertIndex;
|
||||
if( (headIndex = indexOfTag( text, "head", true )) >= 0 ) {
|
||||
// there is a <head> tag --> insert after <head> tag
|
||||
insertIndex = headIndex;
|
||||
} else if( (styleIndex = indexOfTag( text, "style", false )) >= 0 ) {
|
||||
// there is a <style> tag --> insert before <style> tag
|
||||
insertIndex = styleIndex;
|
||||
} else {
|
||||
// no <head> or <style> tag --> insert <head> tag after <html> tag
|
||||
insertIndex = "<html>".length();
|
||||
openTag = "<head>";
|
||||
closeTag = "</head>";
|
||||
}
|
||||
|
||||
String newText = text.substring( 0, insertIndex )
|
||||
+ openTag + style + closeTag
|
||||
+ text.substring( insertIndex );
|
||||
|
||||
BasicHTML.updateRenderer( c, newText );
|
||||
|
||||
// for unit tests
|
||||
if( testUpdateRenderer != null )
|
||||
testUpdateRenderer.accept( c, newText );
|
||||
}
|
||||
|
||||
// for unit tests
|
||||
static BiConsumer<JComponent, String> testUpdateRenderer;
|
||||
|
||||
/**
|
||||
* Returns start or end index of a HTML tag.
|
||||
* Checks only for leading '<' character and (case-ignore) tag name.
|
||||
*/
|
||||
private static int indexOfTag( String html, String tag, boolean endIndex ) {
|
||||
int tagLength = tag.length();
|
||||
int maxLength = html.length() - tagLength - 2;
|
||||
char lastTagChar = tag.charAt( tagLength - 1 );
|
||||
|
||||
for( int i = "<html>".length(); i < maxLength; i++ ) {
|
||||
// check for leading '<' and last tag name character
|
||||
if( html.charAt( i ) == '<' && Character.toLowerCase( html.charAt( i + tagLength ) ) == lastTagChar ) {
|
||||
// compare tag characters from last to first
|
||||
for( int j = tagLength - 2; j >= 0; j-- ) {
|
||||
if( Character.toLowerCase( html.charAt( i + 1 + j ) ) != tag.charAt( j ) )
|
||||
break; // not equal
|
||||
|
||||
if( j == 0 ) {
|
||||
// tag found
|
||||
return endIndex ? html.indexOf( '>', i + tagLength ) + 1 : i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static final Set<String> absoluteSizeKeywordsSet = new HashSet<>( Arrays.asList(
|
||||
"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large" ) );
|
||||
|
||||
/**
|
||||
* Checks whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
|
||||
* (see javax/swing/text/html/default.css).
|
||||
*/
|
||||
private static boolean usesAbsoluteSizeKeywordForFontSize( View view ) {
|
||||
AttributeSet attributes = view.getAttributes();
|
||||
if( attributes != null ) {
|
||||
Object fontSize = attributes.getAttribute( CSS.Attribute.FONT_SIZE );
|
||||
if( fontSize != null ) {
|
||||
if( absoluteSizeKeywordsSet.contains( fontSize.toString() ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int viewCount = view.getViewCount();
|
||||
for( int i = 0; i < viewCount; i++ ) {
|
||||
if( usesAbsoluteSizeKeywordForFontSize( view.getView( i ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates foreground in style sheet of the HTML view.
|
||||
* Adds "body { color: #<foreground-hex>; }"
|
||||
*/
|
||||
public static void updateRendererCSSForeground( View view, Color foreground ) {
|
||||
Document doc = view.getDocument();
|
||||
if( !(doc instanceof HTMLDocument) || foreground == null )
|
||||
return;
|
||||
|
||||
// add foreground rule if necessary
|
||||
// - use tag 'body' because BasicHTML.createHTMLView() also uses this tag
|
||||
// to set font and color styles to component font/color
|
||||
// see: SwingUtilities2.displayPropertiesToCSS()
|
||||
// - this color is not used if component is disabled;
|
||||
// JTextComponent.getDisabledTextColor() is used for disabled text components;
|
||||
// UIManager.getColor("textInactiveText") is used for other disabled components
|
||||
// see: javax.swing.text.GlyphView.paint()
|
||||
Style bodyStyle = ((HTMLDocument)doc).getStyle( "body" );
|
||||
if( bodyStyle == null ) {
|
||||
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
|
||||
styleSheet.addRule( String.format( "body { color: #%06x; }", foreground.getRGB() & 0xffffff ) );
|
||||
clearViewCaches( view );
|
||||
} else if( !foreground.equals( bodyStyle.getAttribute( StyleConstants.Foreground ) ) ) {
|
||||
bodyStyle.addAttribute( StyleConstants.Foreground, foreground );
|
||||
clearViewCaches( view );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears cached values in view so that CSS changes take effect.
|
||||
*/
|
||||
private static void clearViewCaches( View view ) {
|
||||
if( view instanceof LabelView )
|
||||
((LabelView)view).changedUpdate( null, null, null );
|
||||
|
||||
int viewCount = view.getViewCount();
|
||||
for( int i = 0; i < viewCount; i++ )
|
||||
clearViewCaches( view.getView( i ) );
|
||||
}
|
||||
|
||||
public static PropertyChangeListener createPropertyChangeListener( PropertyChangeListener superListener ) {
|
||||
return e -> {
|
||||
if( superListener != null )
|
||||
superListener.propertyChange( e );
|
||||
propertyChange( e );
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@link #updateRendererCSSFontBaseSize(JComponent)}
|
||||
* for {@link BasicHTML#propertyKey} property change events,
|
||||
* which are fired when {@link BasicHTML#updateRenderer(JComponent, String)}
|
||||
* updates the HTML view.
|
||||
*/
|
||||
public static void propertyChange( PropertyChangeEvent e ) {
|
||||
if( BasicHTML.propertyKey.equals( e.getPropertyName() ) && e.getNewValue() instanceof View )
|
||||
updateRendererCSSFontBaseSize( (JComponent) e.getSource() );
|
||||
}
|
||||
|
||||
/*debug
|
||||
public static void dumpView( JComponent c ) {
|
||||
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||
if( view != null )
|
||||
dumpViews( view, 0 );
|
||||
}
|
||||
|
||||
public static void dumpViews( View view, int indent ) {
|
||||
for( int i = 0; i < indent; i++ )
|
||||
System.out.print( " " );
|
||||
|
||||
System.out.printf( "%s @%-8x %3d,%2d",
|
||||
view.getClass().isAnonymousClass() ? view.getClass().getName() : view.getClass().getSimpleName(),
|
||||
System.identityHashCode( view ),
|
||||
(int) view.getPreferredSpan( View.X_AXIS ),
|
||||
(int) view.getPreferredSpan( View.Y_AXIS ) );
|
||||
|
||||
AttributeSet attrs = view.getAttributes();
|
||||
if( attrs != null ) {
|
||||
Object fontSize = attrs.getAttribute( CSS.Attribute.FONT_SIZE );
|
||||
System.out.printf( " %-8s", fontSize );
|
||||
}
|
||||
|
||||
if( view instanceof javax.swing.text.GlyphView ) {
|
||||
javax.swing.text.GlyphView gview = ((javax.swing.text.GlyphView)view);
|
||||
java.awt.Font font = gview.getFont();
|
||||
System.out.printf( " %3d-%-3d %s %2d (@%x) #%06x '%s'",
|
||||
gview.getStartOffset(), gview.getEndOffset() - 1,
|
||||
font.getName(), font.getSize(), System.identityHashCode( font ),
|
||||
gview.getForeground().getRGB() & 0xffffff,
|
||||
gview.getText( gview.getStartOffset(), gview.getEndOffset() ) );
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
int viewCount = view.getViewCount();
|
||||
for( int i = 0; i < viewCount; i++ ) {
|
||||
View child = view.getView( i );
|
||||
dumpViews( child, indent + 1 );
|
||||
}
|
||||
}
|
||||
debug*/
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user