mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
Compare commits
933 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
2b1c55ee67 | ||
|
|
925ddaa63a | ||
|
|
2b60b18d47 | ||
|
|
d502406fa2 | ||
|
|
afdbf711f7 | ||
|
|
b4f7b1d71d | ||
|
|
69061cd41c | ||
|
|
8ba7f7f961 | ||
|
|
5e5aa17e14 | ||
|
|
551f5fc929 | ||
|
|
4e7b0d11d0 | ||
|
|
06bc53692a | ||
|
|
007ee38cb4 | ||
|
|
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 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -20,7 +20,9 @@
|
||||
*.gif binary
|
||||
*.jar binary
|
||||
*.lib binary
|
||||
*.otf binary
|
||||
*.png binary
|
||||
*.sketch binary
|
||||
*.so binary
|
||||
*.ttf binary
|
||||
*.zip binary
|
||||
|
||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
custom: https://www.formdev.com/flatlaf/sponsor/
|
||||
114
.github/workflows/ci.yml
vendored
114
.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,6 @@ on:
|
||||
- '*'
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -19,50 +17,46 @@ 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
|
||||
toolchain: [""]
|
||||
include:
|
||||
- java: 17
|
||||
toolchain: 21 # latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
if: matrix.java == '8'
|
||||
|
||||
- name: Setup Java ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: temurin # Java 8, 11 and 17 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@v3
|
||||
if: matrix.java == '11'
|
||||
with:
|
||||
name: FlatLaf-build-artifacts
|
||||
path: |
|
||||
flatlaf-*/build/libs
|
||||
flatlaf-*/flatlaf-*/build/libs
|
||||
!**/*-javadoc.jar
|
||||
!**/*-sources.jar
|
||||
|
||||
@@ -72,36 +66,36 @@ jobs:
|
||||
needs: build
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/main' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) &&
|
||||
github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
distribution: temurin # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Publish snapshot to oss.sonatype.org
|
||||
run: ./gradlew publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
|
||||
- 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:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -112,28 +106,17 @@ jobs:
|
||||
github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
distribution: temurin # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Release a new stable version to Maven Central
|
||||
run: ./gradlew publish :flatlaf-demo:build -Drelease=true
|
||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
@@ -150,3 +133,14 @@ jobs:
|
||||
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"
|
||||
|
||||
60
.github/workflows/fonts.yml
vendored
Normal file
60
.github/workflows/fonts.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
# 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'
|
||||
|
||||
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@v3
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v3
|
||||
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 ) )
|
||||
59
.github/workflows/natives.yml
vendored
59
.github/workflows/natives.yml
vendored
@@ -1,4 +1,5 @@
|
||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||
|
||||
name: Native Libraries
|
||||
|
||||
@@ -9,50 +10,42 @@ on:
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
paths:
|
||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||
- 'flatlaf-natives/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
runs-on: windows-latest
|
||||
Natives:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- windows
|
||||
- macos
|
||||
- ubuntu
|
||||
|
||||
runs-on: ${{ matrix.os }}-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Setup Java 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
!~/.gradle/caches/modules-2/modules-2.lock
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
java-version: 11
|
||||
distribution: temurin
|
||||
cache: gradle
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew :flatlaf-natives-windows:build
|
||||
# --no-daemon is necessary on Windows otherwise caching Gradle would fail with:
|
||||
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
||||
run: ./gradlew build-natives --no-daemon
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: FlatLaf-natives-windows-build-artifacts
|
||||
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||
path: |
|
||||
flatlaf-natives/flatlaf-natives-windows/build
|
||||
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives
|
||||
flatlaf-natives/flatlaf-natives-*/build
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,5 +9,7 @@ out/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.xcuserstate
|
||||
*.xcworkspacedata
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
825
CHANGELOG.md
825
CHANGELOG.md
@@ -1,6 +1,829 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 3.3
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- macOS (10.14+): Popups (`JPopupMenu`, `JComboBox`, `JToolTip`, etc.) now use
|
||||
native macOS rounded borders. (PR #772; issue #715)
|
||||
- Native libraries: Added `libflatlaf-macos-arm64.dylib` and
|
||||
`libflatlaf-macos-x86_64.dylib`. See also
|
||||
https://www.formdev.com/flatlaf/native-libraries/.
|
||||
- ScrollPane: Support rounded border. (PR #713)
|
||||
- SplitPane: Support divider hover and pressed background colors. (PR #788)
|
||||
- TabbedPane: Support vertical tabs. (PR #758, issue #633)
|
||||
- TabbedPane: Paint rounded tab area background for rounded cards. (issue #717)
|
||||
- ToolBar: Added styling properties `separatorWidth` and `separatorColor`.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Button and ToggleButton: Selected buttons did not use explicitly set
|
||||
foreground color. (issue 756)
|
||||
- FileChooser: Catch NPE in Java 21 when getting icon for `.exe` files that use
|
||||
default Windows exe icon. (see
|
||||
[JDK-8320692](https://bugs.openjdk.org/browse/JDK-8320692))
|
||||
- OptionPane: Fixed styling custom panel background in `JOptionPane`. (issue
|
||||
#761)
|
||||
- ScrollPane: Styling ScrollPane border properties did not work if view
|
||||
component is a Table.
|
||||
- Table:
|
||||
- Switching theme looses table grid and intercell spacing. (issues #733 and
|
||||
#750)
|
||||
- Fixed background of `boolean` columns when using alternating row colors.
|
||||
(issue #780)
|
||||
- Fixed border arc of components in complex table cell editors. (issue #786)
|
||||
- TableHeader:
|
||||
- No longer temporary replace header cell renderer while painting. This avoids
|
||||
a `StackOverflowError` in case that custom renderer does this too. (see
|
||||
[NetBeans issue #6835](https://github.com/apache/netbeans/issues/6835)) This
|
||||
also improves compatibility with custom table header implementations.
|
||||
- Header cell renderer background/foreground colors were not restored after
|
||||
hover if renderer uses `null` for background/foreground. (PR #790)
|
||||
- TabbedPane:
|
||||
- Avoid unnecessary repainting whole tabbed pane content area when layouting
|
||||
leading/trailing components.
|
||||
- Avoid unnecessary repainting of selected tab on temporary changes.
|
||||
- Fixed "endless" layouting and repainting when using nested tabbed panes (top
|
||||
and bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping)
|
||||
as tab content. (see
|
||||
[jadx issue #2030](https://github.com/skylot/jadx/issues/2030))
|
||||
- Fixed broken rendering after resizing window to minimum size and then
|
||||
increasing size again. (issue #767)
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Removed support for JetBrains custom decorations, which required
|
||||
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki) (JBR)
|
||||
8 or 11. It did not work for JBR 17. System property
|
||||
`flatlaf.useJetBrainsCustomDecorations` is now ignored. **Note**: FlatLaf
|
||||
window decorations continue to work with JBR.
|
||||
|
||||
|
||||
## 3.2.5
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Popup: Fixed NPE if popup invoker is `null` on Windows 10. (issue #753;
|
||||
regression in 3.2.1 in fix for #626)
|
||||
|
||||
|
||||
## 3.2.4
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Popup: Fixed NPE if popup invoker is `null` on Linux with Wayland and Java 21.
|
||||
(issue #752; regression in 3.2.3)
|
||||
|
||||
|
||||
## 3.2.3
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Popup: Popups that request focus were not shown on Linux with Wayland and Java 21.
|
||||
(issue #752)
|
||||
|
||||
|
||||
## 3.2.2
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Button: Fixed painting icon and text at wrong location when using HTML text,
|
||||
left/right vertical alignment and running in Java 19+. (issue #746)
|
||||
- CheckBox and RadioButton: Fixed cut off right side when border is removed and
|
||||
horizontal alignment is set to `right`. (issue #734)
|
||||
- TabbedPane: Fixed NPE when using focusable component as tab component and
|
||||
switching theme. (issue #745)
|
||||
|
||||
|
||||
## 3.2.1
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Fixed memory leak in
|
||||
`MultiResolutionImageSupport.create(int,Dimension[],Function<Dimension,Image>)`,
|
||||
which caches images created by the producer function. Used by
|
||||
`FlatSVGIcon.getImage()` and `FlatSVGUtils.createWindowIconImages()`. If you
|
||||
use one of these methods, it is **strongly recommended** to upgrade to this
|
||||
version, because if the returned image is larger and painted very often it may
|
||||
result in an out-of-memory situation. (issue #726)
|
||||
- FileChooser: Fixed occasional NPE in `FlatShortcutsPanel` on Windows. (issue
|
||||
#718)
|
||||
- TextField: Fixed placeholder text painting, which did not respect horizontal
|
||||
alignment property of `JTextField`. (issue #721)
|
||||
- Popup: Fixed drop shadow if popup overlaps a heavyweight component. (Windows
|
||||
10 only; issue #626)
|
||||
|
||||
|
||||
## 3.2
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- TabbedPane: Support rounded underline selection and rounded card tabs. (PR
|
||||
#703)
|
||||
- FlatLaf window decorations:
|
||||
- Support for Windows on ARM 64-bit. (issue #443, PR #707)
|
||||
- Support toolbox-style "small" window title bar. (issue #659, PR #702)
|
||||
- Extras: Class `FlatSVGIcon` now uses [JSVG](https://github.com/weisJ/jsvg)
|
||||
library (instead of svgSalamander) for rendering. JSVG provides improved SVG
|
||||
rendering and uses less memory compared to svgSalamander. (PR #684)
|
||||
- ComboBox: Improved location of selected item in popup if list is large and
|
||||
scrollable.
|
||||
- FileChooser: Show localized text for all locales supported by Java's Metal
|
||||
look and feel. (issue #680)
|
||||
- Added system property `flatlaf.useNativeLibrary` to allow disabling loading of
|
||||
FlatLaf native library. (issue #674)
|
||||
- IntelliJ Themes:
|
||||
- Reduced memory footprint by releasing Json data and ignoring IntelliJ UI
|
||||
properties that are not used in FlatLaf.
|
||||
- Updated "Hiberbee Dark" and "Gradianto" themes.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Styling: Fixed scaling of some styling properties (`rowHeight` for Table and
|
||||
Tree; `iconTextGap` for Button, CheckBox and RadioButton). (issue #682)
|
||||
- Fixed `IllegalComponentStateException` when invoker is not showing in
|
||||
`SubMenuUsabilityHelper`. (issue #692)
|
||||
- macOS themes: Changing `@accentColor` variable in FlatLaf properties files did
|
||||
not change all accent related colors for all components.
|
||||
- IntelliJ Themes:
|
||||
- "Light Owl" theme: Fixed wrong (unreadable) text color in selected menu
|
||||
items, selected text in text components, and selection in ComboBox popup
|
||||
list. (issue #687)
|
||||
- "Gradianto Midnight Blue" theme: Fixed color of ScrollBar track, which was
|
||||
not visible. (issue #686)
|
||||
- "Monocai" theme: Fixed unreadable text color of default buttons. (issue
|
||||
#693)
|
||||
- "Vuesion" theme: Fixed foreground colors of disabled text.
|
||||
- "Material UI Lite" themes: Fixed non-editable ComboBox button background.
|
||||
- CheckBox and RadioButton: Fixed unselected icon colors for themes "Atom One
|
||||
Light", "Cyan Light", "GitHub", "Light Owl", "Material Lighter" and
|
||||
"Solarized Light".
|
||||
- TabbedPane: Fixed focused tab background color for themes "Arc *", "Material
|
||||
Design Dark", "Monocai", "One Dark", "Spacegray" and "Xcode-Dark". (issue
|
||||
#697)
|
||||
- TextComponents, ComboBox and Spinner: Fixed background colors of enabled
|
||||
text components, to distinguish from disabled, for themes "Carbon", "Cobalt
|
||||
2", "Gradianto *", "Gruvbox *", "Monocai", "Spacegray", "Vuesion",
|
||||
"Xcode-Dark", "GitHub", and "Light Owl". (issue #528)
|
||||
- Fixed wrong disabled text colors in "Dark Flat", "Hiberbee Dark", "Light
|
||||
Flat", "Nord", "Solarized Dark" and "Solarized Light" themes.
|
||||
- Fixed colors for selection background/foreground, Separator, Slider track
|
||||
and ProgressBar background in various themes.
|
||||
- Native Windows libraries: Fixed crash when running in Java 8 and newer Java
|
||||
version is installed in `PATH` environment variable and using class
|
||||
`SystemInfo` before AWT initialization. (issue #673)
|
||||
- ComboBox: Fixed search in item list for text with spaces. (issue #691)
|
||||
- FormattedTextField: On Linux, fixed `IllegalArgumentException: Invalid
|
||||
location` if `JFormattedTextField.setDocument()` is invoked in a focus gained
|
||||
listener on that formatted text field. (issue #698)
|
||||
- PopupMenu: Make sure that popup menu does not overlap any operating system
|
||||
task bar. (issue #701)
|
||||
- FileChooser: Use system icons on Windows with Java 17.0.3 (and later) 32-bit.
|
||||
Only Java 17 - 17.0.2 32-bit do not use system icons because of a bug in Java
|
||||
32-bit that crashes the application. (PR #709)
|
||||
- FileChooser: Fixed crash on Windows with Java 17 to 17.0.2 32-bit. Java 17
|
||||
64-bit is not affected. (regression since FlatLaf 2.3; PR #522, see also issue
|
||||
#403)
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Extras: Class `FlatSVGIcon` now uses [JSVG](https://github.com/weisJ/jsvg)
|
||||
library for SVG rendering. You need to replace svgSalamander with JSVG in your
|
||||
build scripts and distribute `jsvg.jar` with your application. Also replace
|
||||
`com.kitfox.svg` with `com.github.weisj.jsvg` in `module-info.java` files.
|
||||
- IntelliJ Themes: Removed all "Contrast" themes from "Material UI Lite".
|
||||
|
||||
|
||||
## 3.1.1
|
||||
|
||||
- IntelliJ Themes:
|
||||
- Fixed too large menu item paddings and too large table/tree row heights (all
|
||||
"Material Theme UI Lite" themes; issue #667; regression in FlatLaf 3.1).
|
||||
- Fixed too large tree row height in "Carbon", "Dark Purple", "Gray",
|
||||
"Material Design Dark", "Monokai Pro", "One Dark" and "Spacegray" themes.
|
||||
- Native libraries: Fixed `IllegalArgumentException: URI scheme is not "file"`
|
||||
when using FlatLaf in WebStart. (issue #668; regression in FlatLaf 3.1)
|
||||
|
||||
|
||||
## 3.1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Windows 11: Popups (`JPopupMenu`, `JComboBox`, `JToolTip`, etc.) now use
|
||||
native Windows 11 rounded borders and drop shadows. (PR #643)
|
||||
- Fonts:
|
||||
- Added **Roboto Mono** (https://fonts.google.com/specimen/Roboto+Mono). (PR
|
||||
#639, issue #638)
|
||||
- Updated **JetBrains Mono** to
|
||||
[v2.304](https://github.com/JetBrains/JetBrainsMono/releases/tag/v2.304).
|
||||
- Theme Editor: Support macOS light and dark themes.
|
||||
- TabbedPane: Support hover and focused tab foreground colors. (issue #627)
|
||||
- TabbedPane: `tabbedPane.getBackgroundAt(tabIndex)` now has higher priority
|
||||
than `TabbedPane.focusColor` and `TabbedPane.selectedBackground`. If
|
||||
`tabbedPane.setBackgroundAt(tabIndex)` is used to set a color for a single
|
||||
tab, then this color is now used even if the tab is focused or selected.
|
||||
- TableHeader: Support column hover and pressed background and foreground
|
||||
colors. (issue #636)
|
||||
- Native libraries: Made it easier to distribute FlatLaf native libraries
|
||||
(Windows `.dll` and Linux `.so`) to avoid problems on operating systems with
|
||||
enabled execution restrictions.
|
||||
See https://www.formdev.com/flatlaf/native-libraries/ for more details. (issue #624)
|
||||
- Published native libraries to Maven Central for easy using them as
|
||||
dependencies in Gradle and Maven.
|
||||
- If available, native libraries are now loaded from same location as
|
||||
`flatlaf.jar`, otherwise they are extract from `flatlaf.jar` to temporary
|
||||
folder and loaded from there.
|
||||
- Windows DLLs are now digitally signed with FormDev Software GmbH
|
||||
certificate.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- FlatLaf window decorations:
|
||||
- Fixed inconsistent size of glass pane depending on whether FlatLaf window
|
||||
decorations are used (e.g. Windows 10/11) or not (e.g. macOS). Now the glass
|
||||
pane no longer overlaps the FlatLaf window title bar. (issue #630)
|
||||
- Linux: Fixed broken window resizing on multi-screen setups. (issue #632)
|
||||
- Linux: Fixed behavior of maximize/restore button when tiling window to left
|
||||
or right half of screen. (issue #647)
|
||||
- IntelliJ Themes:
|
||||
- Fixed default button hover background in "Solarized Light" theme. (issue
|
||||
#628)
|
||||
- Avoid that accent color affect some colors in some IntelliJ themes. (issue
|
||||
#625)
|
||||
- Updated "Hiberbee Dark" and "Material Theme UI Lite" themes.
|
||||
- Styling: Fixed resolving of UI variables in styles that use other variables.
|
||||
- MenuItem: Fixed horizontal alignment of icons. (issue #631)
|
||||
- Table: Fixed potential performance issue with paint cell focus indicator
|
||||
border. (issue #654)
|
||||
- Tree: Fixed missing custom closed/opened/leaf icons of a custom
|
||||
`DefaultTreeCellRenderer`. (issue #653; regression since implementing PR #609
|
||||
in FlatLaf 3.0)
|
||||
- Tree: Fixed truncated node text and too small painted non-wide node background
|
||||
if custom cell renderer sets icon, but not disabled icon, and tree is
|
||||
disabled. (issue #640)
|
||||
- Fixed `HiDPIUtils.paintAtScale1x()`, which painted at wrong location if
|
||||
graphics is rotated, is scaled and `x` or `y` parameters are not zero. (issue
|
||||
#646)
|
||||
|
||||
|
||||
## 3.0
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- **macOS light and dark themes**: The two new themes `FlatMacLightLaf` and
|
||||
`FlatMacDarkLaf` use macOS colors and look similar to native macOS controls.
|
||||
(PRs #533, #612 and #607)
|
||||
- **Fonts**: Packaged some fonts into JARs and provide an easy way to use them
|
||||
with FlatLaf. (PRs #545, #614 and #615) At the moment there are three fonts:
|
||||
- **Inter** (https://rsms.me/inter/) - a typeface carefully crafted & designed
|
||||
for computer screens
|
||||
- **Roboto** (https://fonts.google.com/specimen/Roboto) - default font on
|
||||
Android and recommended for Material Design
|
||||
- **JetBrains Mono** (https://www.jetbrains.com/mono) - a monospaced typeface
|
||||
- **Rounded selection**: Optionally use rounded selection in:
|
||||
- Menus (PR #536)
|
||||
- ComboBox (PR #548)
|
||||
- List (PR #547)
|
||||
- Tree (PR #546)
|
||||
- Tree: Hide default closed/opened/leaf icons by default. Set UI value
|
||||
`Tree.showDefaultIcons` to `true` to show them.
|
||||
- ToolBar: Hover effect for button groups. (PR #534)
|
||||
- Icons: New modern **rounded outlined icons** for `JFileChooser`,
|
||||
`JOptionPane`, `JPasswordField` and `JTree`. (PR #577)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- FileChooser: Fixed layout of (optional) accessory component and fixed too
|
||||
large right margin. (issue #604; regression since implementing PR #522 in
|
||||
FlatLaf 2.3)
|
||||
- Tree:
|
||||
- Fixed missing tree lines (if enabled) for wide-selected rows. (issue #598)
|
||||
- Fixed scaling of tree lines and fixed alignment to expand/collapse arrows.
|
||||
- Removed support for dashed tree lines. `Tree.lineTypeDashed` is now ignored.
|
||||
- SwingX: Fonts in `JXHeader`, `JXMonthView`, `JXTaskPane` and `JXTitledPanel`
|
||||
were not updated when changing default font.
|
||||
|
||||
|
||||
## 2.6
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- If value of system property `flatlaf.nativeLibraryPath` is `system`, then
|
||||
`System.loadLibrary(String)` is used to load the native library.
|
||||
- TabbedPane: Switch and close tabs on left mouse click only. (PR #595)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox and Spinner: Fixed missing arrow buttons if preferred height is zero.
|
||||
Minimum width of arrow buttons is 3/4 of default width.
|
||||
- MenuBar: Fixed NPE in `FlatMenuItemRenderer.getTopLevelFont()` if menu item
|
||||
does not have a parent. (issue #600; regression since implementing #589 in
|
||||
FlatLaf 2.5)
|
||||
- ScrollBar: Show "pressed" feedback on track/thumb only for left mouse button.
|
||||
If absolute positioning is enabled (the default), then also for middle mouse
|
||||
button.
|
||||
- Arrow buttons in ComboBox, Spinner, ScrollBar and TabbedPane: Show "pressed"
|
||||
feedback only for left mouse button.
|
||||
- ScaledImageIcon: Do not throw exceptions if image was has invalid size (e.g.
|
||||
not found). Instead, paint a red rectangle (similar to `FlatSVGIcon`).
|
||||
- Fixed NPE in `FlatUIUtils.isCellEditor()`. (issue #601)
|
||||
|
||||
|
||||
## 2.5
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Linux: Use X11 window manager events to move window and to show window menu
|
||||
(right-click on window title bar), if custom window decorations are enabled.
|
||||
This gives FlatLaf windows a more "native" feeling. (issue #482)
|
||||
- MenuBar: Support different menu selection style UI defaults for `MenuBar` and
|
||||
`MenuItem`. (issue #587)
|
||||
- MenuBar: Top level menus now use `MenuBar.font` instead of `Menu.font`. (issue
|
||||
#589)
|
||||
- PasswordField: Reveal button is now hidden (and turned off) if password field
|
||||
is disabled. (issue #501)
|
||||
- TabbedPane: New option to disable tab run rotation in wrap layout. Set UI
|
||||
value `TabbedPane.rotateTabRuns` to `false`. (issue #574)
|
||||
- Window decorations:
|
||||
- Added client property to mark components in embedded menu bar as "caption"
|
||||
(allow moving window). (issue #569)
|
||||
- Option to show window icon only in frames, but not in dialogs. Set UI value
|
||||
`TitlePane.showIconInDialogs` to `false`. (issue #589)
|
||||
- Added UI value `TitlePane.font` to customize window title font. (issue #589)
|
||||
- Added system property `flatlaf.updateUIOnSystemFontChange` to allow disabling
|
||||
automatic UI update when system font changes. (issue #580)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Fixed missing UI value `MenuItem.acceleratorDelimiter` on macOS. (was `null`,
|
||||
is now an empty string)
|
||||
- Fixed possible exception in `FlatUIUtils.resetRenderingHints()`. (issue #575)
|
||||
- Fixed AWT components on macOS, which use Swing components internally. (issue
|
||||
#583)
|
||||
- SwingX: Fixed missing highlighting of "today" in `JXMonthView` and
|
||||
`JXDatePicker`.
|
||||
|
||||
|
||||
## 2.4
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- There is now a small area at top of the embedded menu bar to resize the
|
||||
window.
|
||||
- Improved window title bar layout for small window widths:
|
||||
- Width of iconify/maximize/close buttons is reduced (if necessary) to give
|
||||
more space to embedded menu bar and title.
|
||||
- Window title now has a minimum width to always allow moving window
|
||||
(click-and-drag on window title). Instead, embedded menu bar is made
|
||||
smaller.
|
||||
- Option to show window icon beside window title, if menu bar is embedded or
|
||||
title is centered. Set UI value `TitlePane.showIconBesideTitle` to `true`.
|
||||
- No longer reduce height of window title bar if it has an embedded menu bar
|
||||
and is maximized.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox: Fixed vertical alignment of text in popup list with text in combo
|
||||
box in IntelliJ/Darcula themes.
|
||||
- Menus: Fixed application freeze under very special conditions (invoking
|
||||
`FlatLaf.initialize()` twice in NetBeans GUI builder) and using menu that has
|
||||
submenus. See
|
||||
[NetBeans issue #4231](https://github.com/apache/netbeans/issues/4231#issuecomment-1179611682)
|
||||
for details.
|
||||
- MenuItem: Fixed sometimes wrapped HTML text on HiDPI screens on Windows.
|
||||
- TableHeader: Fixed exception when changing table structure (e.g. removing
|
||||
column) from a table header popup menu action. (issue #532)
|
||||
- `HiDPIUtils.paintAtScale1x()` now supports rotated graphics. (issue #557)
|
||||
- Typography: No longer use `Consolas` or `Courier New` as monospaced font on
|
||||
Windows because they have bad vertically placement.
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- Do not center window title if embedded menu bar is empty or has no menus at
|
||||
left side, but some components at right side. (issue #558)
|
||||
- Do not use window decorations if system property `sun.java2d.opengl` is
|
||||
`true` on Windows 10. (issue #540)
|
||||
- Fixed missing top window border in dark themes if window drop shadows are
|
||||
disabled in system settings. (issue #554; Windows 10 only)
|
||||
- Right-to-left component orientation of title bar was lost when switching
|
||||
theme.
|
||||
|
||||
|
||||
## 2.3
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- FileChooser: Added (optional) shortcuts panel. On Windows it contains "Recent
|
||||
Items", "Desktop", "Documents", "This PC" and "Network". On macOS and Linux it
|
||||
is empty/hidden. (issue #100)
|
||||
- Button and ToggleButton: Added missing foreground colors for hover, pressed,
|
||||
focused and selected states. (issue #535)
|
||||
- Table: Optionally paint alternating rows below table if table is smaller than
|
||||
scroll pane. Set UI value `Table.paintOutsideAlternateRows` to `true`.
|
||||
Requires that `Table.alternateRowColor` is set to a color. (issue #504)
|
||||
- ToggleButton: Made the underline placement of tab-style toggle buttons
|
||||
configurable. (PR #530; issue #529)
|
||||
- Added spanish translation. (PR #525)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- IntelliJ Themes: Fixed `TitledBorder` text color in "Monokai Pro" theme.
|
||||
(issue #524)
|
||||
|
||||
|
||||
## 2.2
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- SplitPane: Allow limiting one-touch expanding to a single side (set client
|
||||
property `JSplitPane.expandableSide` to `"left"` or `"right"`). (issue #355)
|
||||
- TabbedPane: Selected tab underline color now changes depending on whether the
|
||||
focus is within the tab content. (issue #398)
|
||||
- IntelliJ Themes:
|
||||
- Added "Monokai Pro" and "Xcode-Dark" themes.
|
||||
- TabbedPane now use different background color for selected tabs in all "Arc"
|
||||
themes, in "Hiberbee Dark" and in all "Material UI Lite" themes.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Native window decorations (Windows 10/11 only): Fixed wrong window title
|
||||
character encoding used in Windows taskbar. (issue #502)
|
||||
- Button: Fixed icon layout and preferred width of default buttons that use bold
|
||||
font. (issue #506)
|
||||
- FileChooser: Enabled full row selection for details view to fix alternate row
|
||||
coloring. (issue #512)
|
||||
- SplitPane: Fixed `StackOverflowError` caused by layout loop that may occur
|
||||
under special circumstances. (issue #513)
|
||||
- Table: Slightly changed grid colors to make grid better recognizable. (issue
|
||||
#514)
|
||||
- ToolBar: Fixed endless loop in focus navigation that may occur under special
|
||||
circumstances. (issue #505)
|
||||
- IntelliJ Themes: `Component.accentColor` UI property now has useful theme
|
||||
specific values. (issue #507)
|
||||
|
||||
|
||||
## 2.1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Menus: Improved usability of submenus. (PR #490; issue #247)
|
||||
- Menus: Scroll large menus using mouse wheel or up/down arrows. (issue #225)
|
||||
- Linux: Support using custom window decorations. Enable with
|
||||
`JFrame.setDefaultLookAndFeelDecorated(true)` and
|
||||
`JDialog.setDefaultLookAndFeelDecorated(true)` before creating a window.
|
||||
(issue #482)
|
||||
- ScrollBar: Added UI value `ScrollBar.minimumButtonSize` to specify minimum
|
||||
scroll arrow button size (if shown). (issue #493)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- PasswordField: Fixed reveal button appearance in IntelliJ themes. (issue #494)
|
||||
- ScrollBar: Center and scale arrows in scroll up/down buttons (if shown).
|
||||
(issue #493)
|
||||
- TextArea, TextPane and EditorPane: No longer select all text when component is
|
||||
focused for the first time. (issue #498; regression in FlatLaf 2.0)
|
||||
- TabbedPane: Disable all items in "Show Hidden Tabs" popup menu if tabbed pane
|
||||
is disabled.
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Method `FlatUIUtils.paintArrow()` (and class `FlatArrowButton`) now paints
|
||||
arrows one pixel smaller than before. To fix this, increase parameter
|
||||
`arrowSize` by one.
|
||||
|
||||
|
||||
## 2.0.2
|
||||
|
||||
- Native window decorations (Windows 10/11 only): Fixed rendering artifacts on
|
||||
HiDPI screens when dragging window partly offscreen and back into screen
|
||||
bounds. (issue #477)
|
||||
- Repaint component when setting client property `JComponent.outline` (issue
|
||||
#480).
|
||||
- macOS: Fixed NPE when using some icons in main menu items. (issue #483)
|
||||
|
||||
|
||||
## 2.0.1
|
||||
|
||||
- Fixed memory leak in Panel, Separator and ToolBarSeparator. (issue #471;
|
||||
regression in FlatLaf 2.0)
|
||||
- ToolTip: Fixed wrong tooltip location if component overrides
|
||||
`JComponent.getToolTipLocation()` and wants place tooltip under mouse
|
||||
location. (issue #468)
|
||||
- Extras: Added copy constructor to `FlatSVGIcon`. (issue #465)
|
||||
- Moved `module-info.class` from `META-INF\versions\9\` to root folder of JARs.
|
||||
(issue #466)
|
||||
|
||||
|
||||
## 2.0
|
||||
|
||||
- Added system property `flatlaf.nativeLibraryPath` to load native libraries
|
||||
from a directory. (PR #453)
|
||||
- Fixed "endless recursion in font" exception in
|
||||
`FlatLaf$ActiveFont.createValue()` if `UIManager.getFont()` is invoked from
|
||||
multiple threads. (issue #456)
|
||||
- PasswordField: Preserve reveal button state when switching theme. (PR #442;
|
||||
issue #173)
|
||||
- PasswordField: Reveal button did not show password if
|
||||
`JPasswordField.setEchoChar()` was invoked from application. (PR #442; issue
|
||||
#173)
|
||||
- Slider: Fixed/improved focused indicator color when changing accent color. (PR
|
||||
#375)
|
||||
- TextField:
|
||||
- Improved hover/pressed/selected colors of leading/trailing buttons (e.g.
|
||||
"reveal" button in password field). (issue #452)
|
||||
- Clear button no longer paints over round border. (issue #451)
|
||||
- Extras: Fixed concurrent loading of SVG icons on multiple threads. (issue
|
||||
#459)
|
||||
- Use FlatLaf native window decorations by default when running in
|
||||
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki)
|
||||
(instead of using JetBrains custom decorations). System variable
|
||||
`flatlaf.useJetBrainsCustomDecorations` is now `false` by default (was `true`
|
||||
in FlatLaf 1.x). (issue #454)
|
||||
- Native window decorations:
|
||||
- Fixed blurry iconify/maximize/close button hover rectangles at 125%, 150% or
|
||||
175% scaling. (issue #431)
|
||||
- Updated maximize and restore icons for Windows 11 style. (requires Java
|
||||
8u321, 11.0.14, 17.0.2 or 18+)
|
||||
- Updated hover and pressed colors of iconify/maximize/close buttons for
|
||||
Windows 11 style.
|
||||
|
||||
|
||||
## 2.0-rc1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Styling:
|
||||
- Styling individual components using string in CSS syntax or `java.util.Map`.
|
||||
(PR #341)\
|
||||
E.g.: `mySlider.putClientProperty( "FlatLaf.style", "trackWidth: 2" );`
|
||||
- Style classes allow defining style rules at a single place (in UI defaults)
|
||||
and use them in any component. (PR #388)\
|
||||
E.g.: `mySlider.putClientProperty( "FlatLaf.styleClass", "myclass" );`
|
||||
- Typography defines several font styles for headers and various text sizes,
|
||||
which makes it easy to use consistent font styles across the application. (PR
|
||||
#396)
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- Unified backgrounds for window title bar is now enabled by default (window
|
||||
title bar has now same background color as window content). Bottom separator
|
||||
for menu bars is no longer painted (if unified background is enabled).
|
||||
- Show Windows 11 snap layouts menu when hovering the mouse over the maximize
|
||||
button. (issues #397 and #407)
|
||||
- Possibility to hide window title bar icon (for single window set client
|
||||
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
|
||||
value `TitlePane.showIcon` to `false`).
|
||||
- OptionPane: Hide window title bar icon by default. Can be made visibly by
|
||||
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
|
||||
- No longer show the Java "duke/cup" icon if no window icon image is set.
|
||||
(issue #416)
|
||||
- TextField, FormattedTextField and PasswordField:
|
||||
- Support leading and trailing icons (set client property
|
||||
`JTextField.leadingIcon` or `JTextField.trailingIcon` to a
|
||||
`javax.swing.Icon`). (PR #378; issue #368)
|
||||
- Support leading and trailing components (set client property
|
||||
`JTextField.leadingComponent` or `JTextField.trailingComponent` to a
|
||||
`java.awt.Component`). (PR #386)
|
||||
- Support "clear" (or "cancel") button to empty text field. Only shown if text
|
||||
field is not empty, editable and enabled. (set client property
|
||||
`JTextField.showClearButton` to `true`). (PR #442)
|
||||
- PasswordField: Support reveal (or "eye") button to show password. (see UI
|
||||
value `PasswordField.showRevealButton`) (PR #442; issue #173)
|
||||
- TextComponents: Double/triple-click-and-drag now extends selection by whole
|
||||
words/lines.
|
||||
- Theming improvements: Reworks core themes to make it easier to create new
|
||||
themes (e.g. reduced explicit colors by using color functions). **Note**:
|
||||
There are minor incompatible changes in FlatLaf properties files. (PR #390)
|
||||
- ToolBar:
|
||||
- Toolbars are no longer floatable by default (dots on left side of toolbar
|
||||
that allows dragging toolbar). Use `UIManager.put( "ToolBar.floatable", true
|
||||
)` if you want the old behavior.
|
||||
- Skip components with empty input map (e.g. `JLabel`) when using arrow keys
|
||||
to navigate in focusable buttons (if UI value `ToolBar.focusableButtons` is
|
||||
`true`).
|
||||
- Support arrow-keys-only navigation within focusable buttons of toolbar (if
|
||||
UI value `ToolBar.focusableButtons` is `true`):
|
||||
- arrow keys move focus within toolbar
|
||||
- tab-key moves focus out of toolbar
|
||||
- if moving focus into the toolbar, focus recently focused toolbar button
|
||||
- ComboBox, Spinner, TextField and subclasses: Support specifying width of
|
||||
border (see UI value `Component.borderWidth`).
|
||||
- CheckBox and RadioButton:
|
||||
- Made selected icon better recognizable in **FlatLaf Light** (use blue
|
||||
border), **Dark** and **Darcula** (use lighter border) themes. **IntelliJ**
|
||||
theme is not changed.
|
||||
- Support specifying width of icon border (see UI value
|
||||
`CheckBox.icon.borderWidth`).
|
||||
- Reworked icon UI defaults and added missing ones. **Note**: There are minor
|
||||
incompatible changes in FlatLaf properties files.
|
||||
- Slider: Support specifying width of thumb border (see UI value
|
||||
`Slider.thumbBorderWidth`).
|
||||
- TabbedPane: Optionally paint selected tab as card. (PR #343)
|
||||
- MenuItem:
|
||||
- Paint the selected icon when the item is selected. (PR #415)
|
||||
- Vertically align text if icons have different widths. (issue #437)
|
||||
- Panel: Support painting background with rounded corners. (issue #367)
|
||||
- Added more color functions to class `ColorFunctions` for easy use in
|
||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||
`tint()`, `shade()` and `luma()`.
|
||||
- Support defining fonts in FlatLaf properties files. (issue #384)
|
||||
- Added method `FlatLaf.registerCustomDefaultsSource(URL packageUrl)` for JPMS.
|
||||
(issue #325)
|
||||
- Extras:
|
||||
- Added class `FlatDesktop` for easy integration into macOS screen menu
|
||||
(About, Preferences and Quit) when using Java 8.
|
||||
- `FlatSVGIcon`: Support loading SVG from `URL` (for JPMS), `URI`, `File` or
|
||||
`InputStream`. (issues #419 and #325)
|
||||
- `FlatSVGUtils`: Support loading SVG from `URL` (for JPMS). (issue #325)
|
||||
- SwingX:
|
||||
- New "column control" icon for `JXTable` that scales and uses antialiasing.
|
||||
(issue #434)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Native window decorations: Fixed `UnsatisfiedLinkError` on Windows 11 for ARM
|
||||
processors. (issue #443)
|
||||
- MenuBar: Do not fill background if non-opaque and having custom background
|
||||
color. (issue #409)
|
||||
- InternalFrame: Fill background to avoid that parent may shine through internal
|
||||
frame if it contains non-opaque components. (better fix for issue #274)
|
||||
- SwingX: Fixed `NullPointerException` in `FlatCaret` when using
|
||||
`org.jdesktop.swingx.prompt.PromptSupport.setPrompt()` on a text field and
|
||||
then switching theme.
|
||||
|
||||
|
||||
## 1.6.5
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Linux: Fixed font problems when running on Oracle Java (OpenJDK is not
|
||||
affected):
|
||||
- oversized text if system font is "Inter" (issue #427)
|
||||
- missing text if system font is "Cantarell" (on Fedora)
|
||||
- MenuItem: Changed accelerator delimiter from `-` to `+`. (Windows and Linux).
|
||||
- ComboBox: Fixed occasional `StackOverflowError` when modifying combo box not
|
||||
on AWT thread. (issue #432)
|
||||
- macOS: Fixed `NullPointerException` when using AWT component
|
||||
`java.awt.Choice`. (issue #439)
|
||||
- Native window decorations: Do not exit application with `UnsatisfiedLinkError`
|
||||
in case that FlatLaf DLL cannot be executed because of restrictions on
|
||||
temporary directory. Instead, continue with default window decorations. (issue
|
||||
#436)
|
||||
|
||||
|
||||
## 1.6.4
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox: Fixed regression in FlatLaf 1.6.3 that makes selected item invisible
|
||||
in popup list if `DefaultListCellRenderer` is used as renderer. If using
|
||||
default renderer, it works. (issue #426)
|
||||
|
||||
|
||||
## 1.6.3
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (not editable): Fixed regression in FlatLaf 1.6.2 that may display
|
||||
text in non-editable combo boxes in bold. (issue #423)
|
||||
- Tree: Fixed editing cell issue with custom cell renderer and cell editor that
|
||||
use same component for rendering and editing. (issue #385)
|
||||
|
||||
|
||||
## 1.6.2
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (not editable): Fixed background painted outside of border if round
|
||||
edges are enabled (client property `JComponent.roundRect` is `true`). (similar
|
||||
to issue #382; regression since fixing #330 in FlatLaf 1.4)
|
||||
- ComboBox: Fixed `NullPointerException`, which may occur under special
|
||||
circumstances. (issue #408)
|
||||
- Table: Do not select text in cell editor when it gets focus (when
|
||||
`JTable.surrendersFocusOnKeystroke` is `true`) and
|
||||
`TextComponent.selectAllOnFocusPolicy` is `once` (the default) or `always`.
|
||||
(issue #395)
|
||||
- Linux: Fixed NPE when using `java.awt.TrayIcon`. (issue #405)
|
||||
- FileChooser: Workaround for crash on Windows with Java 17 32-bit (disabled
|
||||
Windows icons). Java 17 64-bit is not affected. (issue #403)
|
||||
- Native window decorations: Fixed layout loop, which may occur under special
|
||||
circumstances and slows down the application. (issue #420)
|
||||
|
||||
|
||||
## 1.6.1
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Native window decorations: Catch `UnsatisfiedLinkError` when trying to load
|
||||
`jawt.dll` to avoid an application crash (Java 8 on Windows 10 only).
|
||||
|
||||
|
||||
## 1.6
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- InternalFrame: Double-click on icon in internal frame title bar now closes the
|
||||
internal frame. (issue #374)
|
||||
- IntelliJ Themes: Removed deprecated `install()` methods.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Menus: Fixed missing modifiers flags in `ActionEvent` (e.g. `Ctrl` key
|
||||
pressed) when running in Java 9+ on Linux, macOS. Occurs also on Windows in
|
||||
large popup menus that do not fit into the window. (issue #371; regression
|
||||
since FlatLaf 1.3)
|
||||
- OptionPane: Fixed `OptionPane.sameSizeButtons`, which did not work as expected
|
||||
when setting to `false`.
|
||||
- OptionPane: Fixed rendering of longer HTML text if it is passed as
|
||||
`StringBuilder`, `StringBuffer`, or any other object that returns HTML text in
|
||||
method `toString()`. (similar to issue #12)
|
||||
- ComboBox: Fixed popup border painting on HiDPI screens (e.g. at 150% scaling).
|
||||
- ComboBox: Fixed popup location if shown above of combo box (Java 8 only).
|
||||
- ComboBox (editable): Fixed wrong border of internal text field under special
|
||||
circumstances.
|
||||
- Spinner: Fixed painting of border corners on left side. (issue #382;
|
||||
regression since fixing #330 in FlatLaf 1.4)
|
||||
- TableHeader: Do not show resize cursor for last column if resizing last column
|
||||
is not possible because auto resize mode of table is not off. (issue #332)
|
||||
- TableHeader: Fixed missing trailing vertical separator line if used in upper
|
||||
left corner of scroll pane. (issue #332)
|
||||
- TextField, FormattedTextField, PasswordField and ComboBox: Fixed alignment of
|
||||
placeholder text in right-to-left component orientation.
|
||||
- Slider: Fixed calculation of baseline, which was wrong under some
|
||||
circumstances.
|
||||
|
||||
|
||||
## 1.5
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- SwingX: Added search and clear icons to `JXSearchField`. (issue #359)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Button and TextComponent: Do not apply minimum width/height if margins are
|
||||
set. (issue #364)
|
||||
- ComboBox and Spinner: Limit arrow button width if component has large
|
||||
preferred height. (issue #361)
|
||||
- FileChooser: Fixed missing (localized) texts when FlatLaf is loaded in special
|
||||
classloader (e.g. plugin system in Apache NetBeans).
|
||||
- InternalFrame: Limit internal frame bounds to parent bounds on resize. Also
|
||||
honor maximum size of internal frame. (issue #362)
|
||||
- Popup: Fixed incorrectly placed drop shadow for medium-weight popups in
|
||||
maximized windows. (issue #358)
|
||||
- Native window decorations (Windows 10 only):
|
||||
- Fixed occasional application crash in `flatlaf-windows.dll`. (issue #357)
|
||||
- When window is initially shown, fill background with window background color
|
||||
(instead of white), which avoids flickering in dark themes. (issue 339)
|
||||
- When resizing a window at the right/bottom edge, then first fill the new
|
||||
space with the window background color (instead of black) before the layout
|
||||
is updated.
|
||||
- When resizing a window at the left/top edge, then first fill the new space
|
||||
with the window background color (instead of garbage) before the layout is
|
||||
updated.
|
||||
|
||||
|
||||
## 1.4
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- TextField, FormattedTextField and PasswordField: Support adding extra padding
|
||||
(set client property `JTextField.padding` to an `Insets`).
|
||||
- PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI`
|
||||
(instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier
|
||||
extensibility.
|
||||
- Table and PopupFactory: Use `StackWalker` in Java 9+ for better performance.
|
||||
(issue #334)
|
||||
- ToolBar: Paint focus indicator for focused button in toolbar. (issue #346)
|
||||
- ToolBar: Support focusable buttons in toolbar (set UI value
|
||||
`ToolBar.focusableButtons` to `true`). (issue #346)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (editable) and Spinner: Increased size of internal text field to the
|
||||
component border so that it behaves like plain text field (mouse click to left
|
||||
of text now positions caret to first character instead of opening ComboBox
|
||||
popup; mouse cursor is now of type "text" within the whole component, except
|
||||
for arrow buttons). (issue #330)
|
||||
- ComboBox (not editable): Increased size of internal renderer pane to the
|
||||
component border so that it can paint within the whole component. Also
|
||||
increase combo box size if a custom renderer uses a border with insets that
|
||||
are larger than the default combo box padding (`2,6,2,6`).
|
||||
- Fixed component heights at `1.25x`, `1.75x` and `2.25x` scaling factors (Java
|
||||
8 only) so that Button, ComboBox, Spinner and TextField components (including
|
||||
subclasses) have same heights. This increases heights of Button and TextField
|
||||
components by:
|
||||
- `2px` at `1.75x` in **Light** and **Dark** themes
|
||||
- `2px` at `1.25x` and `2.25x` in **IntelliJ** and **Darcula** themes
|
||||
- OptionPane: Do not make child components, which are derived from `JPanel`,
|
||||
non-opaque. (issue #349)
|
||||
- OptionPane: Align wrapped lines to the right if component orientation is
|
||||
right-to-left. (issue #350)
|
||||
- PasswordField: Caps lock icon no longer painted over long text. (issue #172)
|
||||
- PasswordField: Paint caps lock icon on left side in right-to-left component
|
||||
orientation.
|
||||
- Window decorations: Window title bar width is no longer considered when
|
||||
calculating preferred/minimum width of window. (issue #351)
|
||||
|
||||
|
||||
## 1.3
|
||||
|
||||
#### New features and improvements
|
||||
@@ -10,7 +833,7 @@ FlatLaf Change Log
|
||||
`PasswordField.focusedBackground`, `FormattedTextField.focusedBackground`,
|
||||
`TextArea.focusedBackground`, `TextPane.focusedBackground`,
|
||||
`EditorPane.focusedBackground`, `ComboBox.focusedBackground`,
|
||||
`ComboBox.buttonFocusedBackground`, `ComboBox.popupFocusedBackground` and
|
||||
`ComboBox.buttonFocusedBackground`, `ComboBox.popupBackground` and
|
||||
`Spinner.focusedBackground`). (issue #335)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
302
README.md
302
README.md
@@ -6,14 +6,19 @@ Swing desktop applications.
|
||||
|
||||
It looks almost flat (no shadows or gradients), clean, simple and elegant.
|
||||
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
|
||||
scales on **HiDPI** displays and runs on Java 8 or newer.
|
||||
scales on **HiDPI** displays and runs on Java 8 or newer (LTS and latest).
|
||||
|
||||
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
||||
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

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

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

|
||||
|
||||
|
||||
Sponsors
|
||||
--------
|
||||
|
||||
<a href="https://www.ej-technologies.com/"><img src="https://www.formdev.com/flatlaf/sponsor/ej-technologies.png" width="200" alt="ej-technologies" title="ej-technologies - Java APM, Java Profiler, Java Installer Builder"></a>
|
||||
|
||||
<a href="https://www.dbvis.com/"><img src="https://www.formdev.com/flatlaf/sponsor/dbvisualizer.svg" width="200" alt="DbVisualizer" title="DbVisualizer - SQL Client and Editor"></a>
|
||||
|
||||
<a href="https://www.dscsag.com/"><img src="https://www.formdev.com/flatlaf/sponsor/DSC.png" height="48" alt="DSC Software AG" title="DSC Software AG - Your Companion for Integrative PLM"></a>
|
||||
|
||||
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
|
||||
|
||||
Demo
|
||||
----
|
||||
|
||||
@@ -46,10 +62,15 @@ build script:
|
||||
artifactId: flatlaf
|
||||
version: (see button below)
|
||||
|
||||
Otherwise download `flatlaf-<version>.jar` here:
|
||||
Otherwise, download `flatlaf-<version>.jar` here:
|
||||
|
||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf)
|
||||
|
||||
See also
|
||||
[Native Libraries distribution](https://www.formdev.com/flatlaf/native-libraries/)
|
||||
for instructions on how to redistribute FlatLaf native libraries with your
|
||||
application.
|
||||
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -67,10 +88,15 @@ 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
|
||||
|
||||
|
||||
Getting started
|
||||
@@ -96,14 +122,26 @@ For more information and documentation visit
|
||||
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
||||
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
||||
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
||||
- [Components UI Properties](https://www.formdev.com/flatlaf/components/)
|
||||
- [Typography](https://www.formdev.com/flatlaf/typography/)
|
||||
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
||||
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
||||
|
||||
|
||||
Theme Editor
|
||||
------------
|
||||
|
||||
The Theme Editor that supports editing FlatLaf theme properties files. See
|
||||
[Theme Editor documentation](https://www.formdev.com/flatlaf/theme-editor/) for
|
||||
details and downloads.
|
||||
|
||||

|
||||
|
||||
|
||||
Buzz
|
||||
----
|
||||
|
||||
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
||||
- [FlatLaf 3.1 (and 3.0) announcement on Reddit](https://www.reddit.com/r/java/comments/12xgrsu/flatlaf_31_and_30_swing_look_and_feel/)
|
||||
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
||||
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||
|
||||
@@ -111,89 +149,193 @@ Buzz
|
||||
Applications using FlatLaf
|
||||
--------------------------
|
||||
|
||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
||||
and much more
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
||||
- 
|
||||
### Featured
|
||||
|
||||
-  [JFormDesigner](https://www.formdev.com/)
|
||||
(**commercial**) - Java/Swing GUI Designer (from the FlatLaf creators)
|
||||
- 
|
||||
[JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||
(**commercial**) - the award-winning all-in-one Java profiler
|
||||
- 
|
||||
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
||||
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
||||
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
||||
(**commercial**) - the powerful multi-platform Java installer builder
|
||||
-  [DbVisualizer](https://www.dbvis.com/)
|
||||
(**commercial**) - the universal database tool for developers, analysts and
|
||||
DBAs
|
||||
-  [MagicPlot](https://magicplot.com/) 3.0
|
||||
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
||||
- 
|
||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
||||
(**commercial**) - Thermodynamics and Properties Software
|
||||
- [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds most widely used web
|
||||
app scanner
|
||||
-  [Apache NetBeans](https://netbeans.apache.org/) - IDE
|
||||
for Java, PHP, HTML and much more
|
||||
- 
|
||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) (**commercial**) -
|
||||
Thermodynamics and Properties Software
|
||||
|
||||
### Data
|
||||
|
||||
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
||||
visual query system for relational databases
|
||||
- [Jailer](https://github.com/Wisser/Jailer) - database subsetting and
|
||||
relational data browsing tool
|
||||
-  [MagicPlot](https://magicplot.com/) (**commercial**) -
|
||||
Software for nonlinear fitting, plotting and data analysis
|
||||
-  [Constellation](https://www.constellation-app.com/) -
|
||||
Data Visualization and Analytics (based on NetBeans platform)
|
||||
- 
|
||||
[Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI
|
||||
client
|
||||
|
||||
### Security
|
||||
|
||||
-  [ZAP](https://www.zaproxy.org/) - the world's most
|
||||
widely used web app scanner
|
||||
- 
|
||||
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
||||
2020.11.2 (**commercial**) - the leading software for web security testing
|
||||
(**commercial**) - the leading software for web security testing
|
||||
- 
|
||||
[BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||
[Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
|
||||
reverse engineering (SRE) framework
|
||||
-  [jadx](https://github.com/skylot/jadx) - Dex to Java
|
||||
decompiler
|
||||
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||
FlatLaf themes to Burp Suite
|
||||
- [JOSM](https://josm.openstreetmap.de/) - an extensible editor for
|
||||
[OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf JOSM plugin)
|
||||
- [jAlbum](https://jalbum.net/) 21 (**commercial**) - creates photo album
|
||||
websites
|
||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||
checks your website
|
||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5 - a turn-based sci-fi board
|
||||
game
|
||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||
0.13.b024 - GUI builder for
|
||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
||||
framework for embedded displays
|
||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
||||
gamepad mapping software
|
||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
||||
connections manager
|
||||
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
||||
easy
|
||||
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
|
||||
your website
|
||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||
encryption
|
||||
|
||||
### Software Development
|
||||
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
|
||||
- [KeyStore Explorer](https://keystore-explorer.org/)
|
||||
- 
|
||||
[muCommander](https://github.com/mucommander/mucommander) - lightweight
|
||||
cross-platform file manager
|
||||
-  [Guiffy](https://www.guiffy.com/) (**commercial**) -
|
||||
advanced cross-platform Diff/Merge
|
||||
-  [HashGarten](https://github.com/jonelo/HashGarten) -
|
||||
cross-platform Swing GUI for Jacksum
|
||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||
IDE for Pseudo-Assembler
|
||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
|
||||
language created to learn programming
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform) - information
|
||||
systems development platform
|
||||
|
||||
### Electrical
|
||||
|
||||
- [Antares](https://www.antarescircuit.io/) - a free, powerful platform for
|
||||
designing, simulating and explaining digital circuits
|
||||
- [Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution) -
|
||||
Digital logic design tool and simulator
|
||||
- [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) -
|
||||
for plotters, especially the wall-hanging polargraph
|
||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI
|
||||
builder for [GUIslice](https://github.com/ImpulseAdventure/GUIslice), a
|
||||
lightweight GUI framework for embedded displays
|
||||
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
||||
Arduino-based telescope focuser
|
||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
||||
control software
|
||||
|
||||
### Media
|
||||
|
||||
-  [jAlbum](https://jalbum.net/) (**commercial**) -
|
||||
creates photo album websites
|
||||
-  [MediathekView](https://mediathekview.de/) - search in
|
||||
media libraries of various German broadcasters
|
||||
- [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit
|
||||
sequences
|
||||
- [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a
|
||||
media management tool
|
||||
- [Weasis](https://nroduit.github.io/) - medical DICOM viewer used in healthcare
|
||||
by hospitals, health networks, etc
|
||||
- [Shutter Encoder](https://www.shutterencoder.com/)
|
||||
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
||||
professional video converter and compression tool
|
||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
||||
sound files in time or frequency domain
|
||||
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
||||
from any webnovel and lightnovel site
|
||||
- [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with
|
||||
ease
|
||||
|
||||
### Modelling
|
||||
|
||||
-  [Astah](https://astah.net/) (**commercial**) - create
|
||||
UML, ER Diagram, Flowchart, Data Flow Diagram, Requirement Diagram, SysML
|
||||
diagrams and more
|
||||
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
||||
Application System
|
||||
|
||||
### Documents
|
||||
|
||||
-  [Big Faceless (BFO) PDF Viewer](https://bfo.com/)
|
||||
(**commercial**) - Swing PDF Viewer
|
||||
- [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create,
|
||||
review and edit PDF documents
|
||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**)
|
||||
|
||||
### Geo
|
||||
|
||||
-  [JOSM](https://josm.openstreetmap.de/) - an extensible
|
||||
editor for [OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf
|
||||
JOSM plugin)
|
||||
- [Mapton](https://mapton.org/)
|
||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||
application (based on NetBeans platform)
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) - GIS and scientific
|
||||
computation environment for meteorological community
|
||||
|
||||
### Business / Legal
|
||||
|
||||
- 
|
||||
[j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||
-  [Jeyla Studio](https://www.jeylastudio.com/) -
|
||||
Salon Software
|
||||
- [Fanurio](https://www.fanuriotimetracking.com/) (**commercial**) - time
|
||||
tracking and billing for freelancers and teams
|
||||
- [Jes](https://www.jes-eur.de) - Die Java-EÜR
|
||||
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
||||
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
||||
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||
[AS4](https://mendelson-e-c.com/as4/) and
|
||||
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
||||
-  [IGMAS+](https://www.gfz-potsdam.de/igmas) -
|
||||
Interactive Gravity and Magnetic Application System
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
||||
computation environment for meteorological community
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
||||
systems development platform
|
||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||
encryption
|
||||
- [Jes - Die Java-E<>R](https://www.jes-eur.de)
|
||||
- [Mapton](https://mapton.org/) 2.0
|
||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||
application (based on NetBeans platform)
|
||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||
IDE for Pseudo-Assembler
|
||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) 3.1 - French programming
|
||||
language created to learn programming
|
||||
- [MEKA](https://github.com/Waikato/meka) 1.9.3 - multi-label classifiers and
|
||||
evaluation procedures using the Weka machine learning framework
|
||||
- [Shutter Encoder](https://www.shutterencoder.com/) 14.2
|
||||
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
||||
professional video converter and compression tool (screenshots show **old**
|
||||
look)
|
||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
||||
sound files in time or frequency domain
|
||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
||||
control software
|
||||
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
||||
Arduino-based telescope focuser
|
||||
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
||||
from any webnovel and lightnovel site
|
||||
- [lectureStudio](https://www.lecturestudio.org/) 4.3.1060 - digitize your
|
||||
lectures with ease
|
||||
|
||||
### Messaging
|
||||
|
||||
-  [Spark](https://github.com/igniterealtime/Spark) -
|
||||
cross-platform IM client optimized for businesses and organizations
|
||||
-  [Chatty](https://github.com/chatty/chatty) - Twitch
|
||||
Chat Client
|
||||
|
||||
### Gaming
|
||||
|
||||
-  
|
||||
[BGBlitz](https://www.bgblitz.com/) (**commercial**) - professional Backgammon
|
||||
-  [MapTool](https://github.com/RPTools/maptool) - virtual
|
||||
Tabletop for playing role-playing games
|
||||
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
|
||||
simulator suite handling battles, unit building, and campaigns
|
||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
||||
gamepad mapping software
|
||||
|
||||
### Utilities
|
||||
|
||||
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||
OSHI, to view information about the system and hardware
|
||||
- 
|
||||
[Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
|
||||
GUI for monitoring and managing various aspects of a Linux system
|
||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
||||
connections manager
|
||||
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
||||
easy
|
||||
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
||||
and fastboot commands easier to use
|
||||
- and more...
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- [MEKA](https://github.com/Waikato/meka) - multi-label classifiers and
|
||||
evaluation procedures using the Weka machine learning framework
|
||||
|
||||
@@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "1.3"
|
||||
val developmentVersion = "1.4-SNAPSHOT"
|
||||
import net.ltgt.gradle.errorprone.errorprone
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
|
||||
|
||||
allprojects {
|
||||
version = rootProject.version
|
||||
@@ -37,9 +36,16 @@ println( "----------------------------------------------------------------------
|
||||
println( "FlatLaf Version: ${version}" )
|
||||
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
||||
println( "Java ${System.getProperty( "java.version" )}" )
|
||||
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||
if( !toolchainJavaVersion.isNullOrEmpty() )
|
||||
println( "Java toolchain ${toolchainJavaVersion}" )
|
||||
println()
|
||||
|
||||
|
||||
plugins {
|
||||
alias( libs.plugins.errorprone ) apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
tasks {
|
||||
withType<JavaCompile>().configureEach {
|
||||
@@ -78,4 +84,56 @@ allprojects {
|
||||
isFailOnError = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---- Error Prone ----
|
||||
|
||||
tasks.register( "errorprone" ) {
|
||||
group = "verification"
|
||||
tasks.withType<JavaCompile>().forEach {
|
||||
dependsOn( it )
|
||||
}
|
||||
}
|
||||
|
||||
val useErrorProne = gradle.startParameter.taskNames.contains( "errorprone" )
|
||||
if( useErrorProne ) {
|
||||
plugins.withType<JavaPlugin> {
|
||||
apply( plugin = libs.plugins.errorprone.get().pluginId )
|
||||
|
||||
dependencies {
|
||||
"errorprone"( libs.errorprone )
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.add( "-Werror" )
|
||||
options.errorprone {
|
||||
disable(
|
||||
"ReferenceEquality", // reports usage of '==' for objects
|
||||
"StringSplitter", // reports String.split()
|
||||
"JavaTimeDefaultTimeZone", // reports Year.now()
|
||||
"MissingSummary", // reports `/** @since 2 */`
|
||||
"InvalidBlockTag", // reports @uiDefault in javadoc
|
||||
"AlreadyChecked", // reports false positives
|
||||
"InlineMeSuggester", // suggests using Error Prone annotations for deprecated methods
|
||||
"TypeParameterUnusedInFormals",
|
||||
"UnsynchronizedOverridesSynchronized",
|
||||
"NonApiType", // reports ArrayList/HashSet in parameter or return type
|
||||
)
|
||||
when( project.name ) {
|
||||
"flatlaf-intellij-themes" -> disable(
|
||||
"MutablePublicArray", // reports FlatAllIJThemes.INFOS
|
||||
)
|
||||
"flatlaf-theme-editor" -> disable(
|
||||
"CatchAndPrintStackTrace",
|
||||
)
|
||||
"flatlaf-testing" -> disable(
|
||||
"CatchAndPrintStackTrace",
|
||||
"JdkObsolete", // reports Hashtable used for JSlider.setLabelTable()
|
||||
"JavaUtilDate", // reports usage of class Date
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ReorderJarEntries
|
||||
// 1st pass: copy .properties files
|
||||
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
||||
|
||||
// 2st pass: copy other files
|
||||
// 2nd pass: copy other files
|
||||
copyFiles( zipOutStream, jarFile, name -> !name.endsWith( ".properties" ) );
|
||||
}
|
||||
|
||||
|
||||
46
buildSrc/src/main/kotlin/flatlaf-cpp-library.gradle.kts
Normal file
46
buildSrc/src/main/kotlin/flatlaf-cpp-library.gradle.kts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
`cpp-library`
|
||||
}
|
||||
|
||||
library {
|
||||
// disable debuggable for release builds to make shared libraries smaller
|
||||
binaries.configureEach( CppSharedLibrary::class ) {
|
||||
with( compileTask.get() ) {
|
||||
if( name.contains( "Release" ) )
|
||||
isDebuggable = false
|
||||
}
|
||||
with( linkTask.get() ) {
|
||||
if( name.contains( "Release" ) )
|
||||
debuggable.set( false )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<CppCompile>().configureEach {
|
||||
doFirst {
|
||||
println( "Used Tool Chain:" )
|
||||
println( " - ${toolChain.get()}" )
|
||||
println( "Available Tool Chains:" )
|
||||
toolChains.forEach {
|
||||
println( " - $it" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
add( "java9Compile", sourceSets.main.get().output )
|
||||
add( "java9Implementation", sourceSets.main.get().output )
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
36
buildSrc/src/main/kotlin/flatlaf-jni-headers.gradle.kts
Normal file
36
buildSrc/src/main/kotlin/flatlaf-jni-headers.gradle.kts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
open class JniHeadersExtension {
|
||||
var headers: List<String> = emptyList()
|
||||
}
|
||||
|
||||
val extension = project.extensions.create<JniHeadersExtension>( "flatlafJniHeaders" )
|
||||
|
||||
|
||||
tasks {
|
||||
register<Copy>( "jni-headers" ) {
|
||||
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
||||
dependsOn( ":flatlaf-core:compileJava" )
|
||||
|
||||
from( project( ":flatlaf-core" ).layout.buildDirectory.dir( "generated/jni-headers" ) )
|
||||
into( "src/main/headers" )
|
||||
include( extension.headers )
|
||||
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
||||
"eol" to org.apache.tools.ant.filters.FixCrLfFilter.CrLf.newInstance( "lf" )
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -61,12 +61,8 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest.attributes( "Multi-Release" to "true" )
|
||||
|
||||
into( "META-INF/versions/9" ) {
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
|
||||
|
||||
open class NativeArtifact( val fileName: String, val classifier: String, val type: String ) {}
|
||||
|
||||
open class PublishExtension {
|
||||
var artifactId: String? = null
|
||||
var name: String? = null
|
||||
var description: String? = null
|
||||
var nativeArtifacts: List<NativeArtifact>? = null
|
||||
}
|
||||
|
||||
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
||||
@@ -71,6 +74,15 @@ publishing {
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf/issues" )
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
extension.nativeArtifacts?.forEach {
|
||||
artifact( artifacts.add( "archives", file( it.fileName ) ) {
|
||||
classifier = it.classifier
|
||||
type = it.type
|
||||
} )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +92,7 @@ publishing {
|
||||
|
||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
url = uri( if( java.lang.Boolean.getBoolean( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||
|
||||
credentials {
|
||||
// get from gradle.properties
|
||||
@@ -108,5 +120,13 @@ signing {
|
||||
|
||||
// disable signing of snapshots
|
||||
tasks.withType<Sign>().configureEach {
|
||||
onlyIf { java.lang.Boolean.getBoolean( "release" ) }
|
||||
onlyIf { rootProject.hasProperty( "release" ) }
|
||||
}
|
||||
|
||||
// check whether parallel build is enabled
|
||||
tasks.withType<PublishToMavenRepository>().configureEach {
|
||||
doFirst {
|
||||
if( System.getProperty( "org.gradle.parallel" ) == "true" )
|
||||
throw RuntimeException( "Publishing does not work correctly with enabled parallel build. Disable parallel build with VM option '-Dorg.gradle.parallel=false'." )
|
||||
}
|
||||
}
|
||||
|
||||
26
buildSrc/src/main/kotlin/flatlaf-toolchain.gradle.kts
Normal file
26
buildSrc/src/main/kotlin/flatlaf-toolchain.gradle.kts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||
if( !toolchainJavaVersion.isNullOrEmpty() ) {
|
||||
java.toolchain {
|
||||
languageVersion.set( 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,13 +14,26 @@
|
||||
* 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.bundles.junit )
|
||||
testRuntimeOnly( libs.junit.engine )
|
||||
|
||||
// https://github.com/jtulach/netbeans-apitest
|
||||
sigtest( libs.sigtest )
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
@@ -29,12 +42,7 @@ java {
|
||||
tasks {
|
||||
compileJava {
|
||||
// generate JNI headers
|
||||
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
||||
}
|
||||
|
||||
processResources {
|
||||
// build native libraries
|
||||
dependsOn( ":flatlaf-natives-windows:assemble" )
|
||||
options.headerOutputDirectory.set( layout.buildDirectory.dir( "generated/jni-headers" ) )
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -52,10 +60,78 @@ tasks {
|
||||
named<Jar>( "javadocJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
}
|
||||
|
||||
check {
|
||||
dependsOn( "sigtestCheck" )
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 )
|
||||
jvmArgs( listOf( "--add-opens", "java.desktop/javax.swing.plaf.basic=ALL-UNNAMED" ) )
|
||||
}
|
||||
|
||||
register( "sigtestGenerate" ) {
|
||||
group = "verification"
|
||||
dependsOn( "jar" )
|
||||
|
||||
doLast {
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"(
|
||||
"name" to "sigtest",
|
||||
"classname" to "org.netbeans.apitest.Sigtest",
|
||||
"classpath" to sigtest.asPath )
|
||||
|
||||
"sigtest"(
|
||||
"action" to "generate",
|
||||
"fileName" to "${project.name}-sigtest.txt",
|
||||
"classpath" to jar.get().outputs.files.asPath,
|
||||
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.themes,com.formdev.flatlaf.util",
|
||||
"version" to version,
|
||||
"release" to "1.8", // Java version
|
||||
"failonerror" to "true" )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register( "sigtestCheck" ) {
|
||||
group = "verification"
|
||||
dependsOn( "jar" )
|
||||
|
||||
doLast {
|
||||
ant.withGroovyBuilder {
|
||||
"taskdef"(
|
||||
"name" to "sigtest",
|
||||
"classname" to "org.netbeans.apitest.Sigtest",
|
||||
"classpath" to sigtest.asPath )
|
||||
|
||||
"sigtest"(
|
||||
"action" to "check",
|
||||
"fileName" to "${project.name}-sigtest.txt",
|
||||
"classpath" to jar.get().outputs.files.asPath,
|
||||
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.util",
|
||||
"version" to version,
|
||||
"release" to "1.8", // Java version
|
||||
"failonerror" to "true" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flatlafPublish {
|
||||
artifactId = "flatlaf"
|
||||
name = "FlatLaf"
|
||||
description = "Flat Look and Feel"
|
||||
|
||||
val natives = "src/main/resources/com/formdev/flatlaf/natives"
|
||||
nativeArtifacts = listOf(
|
||||
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" ),
|
||||
)
|
||||
}
|
||||
|
||||
1193
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
1193
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,8 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.IllegalComponentStateException;
|
||||
import java.awt.Window;
|
||||
import java.util.Objects;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingConstants;
|
||||
@@ -31,7 +33,7 @@ public interface FlatClientProperties
|
||||
//---- JButton ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies type of a button.
|
||||
* Specifies type of button.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
@@ -124,8 +126,60 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String SQUARE_SIZE = "JButton.squareSize";
|
||||
|
||||
|
||||
//---- JComponent ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies the style of a component as String in CSS syntax ("key1: value1; key2: value2; ...")
|
||||
* or as {@link java.util.Map}<String, Object> with binary values.
|
||||
* <p>
|
||||
* The keys are the same as used in UI defaults, but without component type prefix.
|
||||
* E.g. for UI default {@code Slider.thumbSize} use key {@code thumbSize}.
|
||||
* <p>
|
||||
* The syntax of the CSS values is the same as used in FlatLaf properties files
|
||||
* (<a href="https://www.formdev.com/flatlaf/properties-files/">https://www.formdev.com/flatlaf/properties-files/</a>),
|
||||
* but some features are not supported (e.g. variables).
|
||||
* When using a map, the values are not parsed from a string. They must be binary.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String} or {@link java.util.Map}<String, Object><br>
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String STYLE = "FlatLaf.style";
|
||||
|
||||
/**
|
||||
* Specifies the style class(es) of a component as String (single class or multiple classes separated by space characters)
|
||||
* or as {@code String[]} or {@link java.util.List}<String> (multiple classes).
|
||||
* <p>
|
||||
* The style rules must be defined in UI defaults either as strings (in CSS syntax)
|
||||
* or as {@link java.util.Map}<String, Object> (with binary values).
|
||||
* The key must be in syntax: {@code [style]type.styleClass}, where the type is optional.
|
||||
* E.g. in FlatLaf properties file:
|
||||
* <pre>{@code
|
||||
* [style]Button.primary = borderColor: #08f; background: #08f; foreground: #fff
|
||||
* [style].secondary = borderColor: #0f8; background: #0f8
|
||||
* }</pre>
|
||||
* or in Java code:
|
||||
* <pre>{@code
|
||||
* UIManager.put( "[style]Button.primary", "borderColor: #08f; background: #08f; foreground: #fff" );
|
||||
* UIManager.put( "[style].secondary", "borderColor: #0f8; background: #0f8" );
|
||||
* }</pre>
|
||||
* The rule "Button.primary" can be applied to buttons only.
|
||||
* The rule ".secondary" can be applied to any component.
|
||||
* <p>
|
||||
* To have similar behavior as in CSS, first the rule without type is applied,
|
||||
* then the rule with type.
|
||||
* E.g. setting style class to "foo" on a {@code JButton} uses rules
|
||||
* from UI default keys "[style].foo" and "[style]Button.foo".
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}, {@code String[]} or {@link java.util.List}<String><br>
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String STYLE_CLASS = "FlatLaf.styleClass";
|
||||
|
||||
/**
|
||||
* Specifies minimum width of a component.
|
||||
* <p>
|
||||
@@ -202,8 +256,60 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
||||
|
||||
/**
|
||||
* Specifies whether a component in an embedded menu bar should behave as caption
|
||||
* (left-click allows moving window, right-click shows window system menu).
|
||||
* The component does not receive mouse pressed/released/clicked/dragged events,
|
||||
* but it gets mouse entered/exited/moved events.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
||||
|
||||
|
||||
//---- Popup --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies the popup border corner radius if the component is shown in a popup
|
||||
* or if the component is the owner of another component that is shown in a popup.
|
||||
* <p>
|
||||
* Note that this is not available on all platforms since it requires special support.
|
||||
* Supported platforms:
|
||||
* <ul>
|
||||
* <li><strong>Windows 11</strong>: Only two corner radiuses are supported
|
||||
* by the OS: {@code DWMWCP_ROUND} is 8px and {@code DWMWCP_ROUNDSMALL} is 4px.
|
||||
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
|
||||
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
|
||||
* <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported.
|
||||
* </ul>
|
||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius";
|
||||
|
||||
/**
|
||||
* Specifies the popup rounded border width if the component is shown in a popup
|
||||
* or if the component is the owner of another component that is shown in a popup.
|
||||
* <p>
|
||||
* Only used if popup uses rounded border.
|
||||
* <p>
|
||||
* Note that this is not available on all platforms since it requires special support.
|
||||
* Supported platforms:
|
||||
* <ul>
|
||||
* <li><strong>macOS</strong> (10.14 and later)
|
||||
* </ul>
|
||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br>
|
||||
*
|
||||
* @since 3.3
|
||||
*/
|
||||
String POPUP_ROUNDED_BORDER_WIDTH = "Popup.roundedBorderWidth";
|
||||
|
||||
/**
|
||||
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
||||
* or if the component is the owner of another component that is shown in a popup.
|
||||
@@ -222,6 +328,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight";
|
||||
|
||||
|
||||
//---- JProgressBar -------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -240,6 +347,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
||||
|
||||
|
||||
//---- JRootPane ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -280,6 +388,80 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
||||
|
||||
/**
|
||||
* Specifies whether the window icon should be shown in the window title bar
|
||||
* (requires enabled window decorations). Default is UI property {@code TitlePane.showIcon}.
|
||||
* <p>
|
||||
* Setting this shows/hides the windows icon
|
||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||
* <p>
|
||||
* This client property has higher priority than UI default {@code TitlePane.showIcon}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon";
|
||||
|
||||
/**
|
||||
* Specifies whether the window title should be shown in the window title bar
|
||||
* (requires enabled window decorations). Default is {@code true}.
|
||||
* <p>
|
||||
* Setting this shows/hides the windows title
|
||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle";
|
||||
|
||||
/**
|
||||
* Specifies whether the "iconify" button should be shown in the window title bar
|
||||
* (requires enabled window decorations). Default is {@code true}.
|
||||
* <p>
|
||||
* Setting this shows/hides the "iconify" button
|
||||
* for the {@code JFrame} that contains the root pane.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.titleBarShowIconify";
|
||||
|
||||
/**
|
||||
* Specifies whether the "maximize/restore" button should be shown in the window title bar
|
||||
* (requires enabled window decorations). Default is {@code true}.
|
||||
* <p>
|
||||
* Setting this shows/hides the "maximize/restore" button
|
||||
* for the {@code JFrame} that contains the root pane.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize";
|
||||
|
||||
/**
|
||||
* Specifies whether the "close" button should be shown in the window title bar
|
||||
* (requires enabled window decorations). Default is {@code true}.
|
||||
* <p>
|
||||
* Setting this shows/hides the "close" button
|
||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
String TITLE_BAR_SHOW_CLOSE = "JRootPane.titleBarShowClose";
|
||||
|
||||
/**
|
||||
* Background color of window title bar (requires enabled window decorations).
|
||||
* <p>
|
||||
@@ -304,6 +486,48 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
|
||||
|
||||
/**
|
||||
* Specifies whether the glass pane should have full height and overlap the title bar,
|
||||
* if FlatLaf window decorations are enabled. Default is {@code false}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight";
|
||||
|
||||
/**
|
||||
* Specifies the style of the window title bar.
|
||||
* Besides the default title bar style, you can use a Utility-style title bar,
|
||||
* which is smaller than the default title bar.
|
||||
* <p>
|
||||
* On Windows 10/11, this requires FlatLaf window decorations.
|
||||
* On macOS, Java supports this out of the box.
|
||||
* <p>
|
||||
* Note that this client property must be set before the window becomes displayable.
|
||||
* Otherwise, an {@link IllegalComponentStateException} is thrown.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #WINDOW_STYLE_SMALL}
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
String WINDOW_STYLE = "Window.style";
|
||||
|
||||
/**
|
||||
* The window has Utility-style title bar, which is smaller than default title bar.
|
||||
* <p>
|
||||
* This is the same as using {@link Window#setType}( {@link Window.Type#UTILITY} ).
|
||||
*
|
||||
* @see #WINDOW_STYLE
|
||||
* @since 3.2
|
||||
*/
|
||||
String WINDOW_STYLE_SMALL = "small";
|
||||
|
||||
|
||||
//---- JScrollBar / JScrollPane -------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -322,8 +546,73 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
||||
|
||||
|
||||
//---- JSplitPane ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies what side of the spilt pane is allowed to expand
|
||||
* via one-touch expanding arrow buttons.
|
||||
* Requires that one-touch expanding is enabled with
|
||||
* {@link javax.swing.JSplitPane#setOneTouchExpandable(boolean)}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JSplitPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_LEFT} or
|
||||
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_RIGHT}
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide";
|
||||
|
||||
/**
|
||||
* Allow expanding only left/top side of the split pane.
|
||||
*
|
||||
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||
* @since 2.2
|
||||
*/
|
||||
String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left";
|
||||
|
||||
/**
|
||||
* Allow expanding only right/bottom side of the split pane.
|
||||
*
|
||||
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||
* @since 2.2
|
||||
*/
|
||||
String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right";
|
||||
|
||||
|
||||
//---- JTabbedPane --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies type of the selected tab.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #TABBED_PANE_TAB_TYPE_UNDERLINED} or
|
||||
* {@link #TABBED_PANE_TAB_TYPE_CARD}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType";
|
||||
|
||||
/**
|
||||
* Paint the selected tab underlined.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined";
|
||||
|
||||
/**
|
||||
* Paint the selected tab as card.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_CARD = "card";
|
||||
|
||||
/**
|
||||
* Specifies whether separators are shown between tabs.
|
||||
* <p>
|
||||
@@ -662,12 +951,65 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement";
|
||||
|
||||
/**
|
||||
* Specifies the rotation of the tabs (title, icon, etc.).
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link SwingConstants#LEFT},
|
||||
* {@link SwingConstants#RIGHT},
|
||||
* {@link #TABBED_PANE_TAB_ROTATION_NONE}, (default)
|
||||
* {@link #TABBED_PANE_TAB_ROTATION_AUTO},
|
||||
* {@link #TABBED_PANE_TAB_ROTATION_LEFT} or
|
||||
* {@link #TABBED_PANE_TAB_ROTATION_RIGHT}
|
||||
*
|
||||
* @since 3.3
|
||||
*/
|
||||
String TABBED_PANE_TAB_ROTATION = "JTabbedPane.tabRotation";
|
||||
|
||||
/**
|
||||
* Tabs are not rotated.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_ROTATION
|
||||
* @since 3.3
|
||||
*/
|
||||
String TABBED_PANE_TAB_ROTATION_NONE = "none";
|
||||
|
||||
/**
|
||||
* Tabs are rotated depending on tab placement.
|
||||
* <p>
|
||||
* For top and bottom tab placement, the tabs are not rotated.<br>
|
||||
* For left tab placement, the tabs are rotated counter-clockwise.<br>
|
||||
* For right tab placement, the tabs are rotated clockwise.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_ROTATION
|
||||
* @since 3.3
|
||||
*/
|
||||
String TABBED_PANE_TAB_ROTATION_AUTO = "auto";
|
||||
|
||||
/**
|
||||
* Tabs are rotated counter-clockwise.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_ROTATION
|
||||
* @since 3.3
|
||||
*/
|
||||
String TABBED_PANE_TAB_ROTATION_LEFT = "left";
|
||||
|
||||
/**
|
||||
* Tabs are rotated clockwise.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_ROTATION
|
||||
* @since 3.3
|
||||
*/
|
||||
String TABBED_PANE_TAB_ROTATION_RIGHT = "right";
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the tabs area.
|
||||
* <p>
|
||||
* For top and bottom tab placement, the layed out component size will be
|
||||
* For top and bottom tab placement, the laid out component size will be
|
||||
* the preferred component width and the tab area height.<br>
|
||||
* For left and right tab placement, the layed out component size will be
|
||||
* For left and right tab placement, the laid out component size will be
|
||||
* the tab area width and the preferred component height.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
@@ -678,9 +1020,9 @@ public interface FlatClientProperties
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
||||
* <p>
|
||||
* For top and bottom tab placement, the layed out component size will be
|
||||
* For top and bottom tab placement, the laid out component size will be
|
||||
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
||||
* For left and right tab placement, the layed out component size will be
|
||||
* For left and right tab placement, the laid out component size will be
|
||||
* the tab area width and the available vertical space (minimum is preferred component height).
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
@@ -688,6 +1030,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
||||
|
||||
|
||||
//---- JTextField ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -733,10 +1076,150 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
|
||||
|
||||
/**
|
||||
* Specifies the padding of the text.
|
||||
* This changes the location and size of the text view within the component bounds,
|
||||
* but does not affect the size of the component.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link java.awt.Insets}
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
String TEXT_FIELD_PADDING = "JTextField.padding";
|
||||
|
||||
/**
|
||||
* Specifies an icon that will be placed at the leading edge of the text field.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.Icon}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_LEADING_ICON = "JTextField.leadingIcon";
|
||||
|
||||
/**
|
||||
* Specifies an icon that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.Icon}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon";
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #OUTLINE}).
|
||||
* <p>
|
||||
* The component is prepared in the following way:
|
||||
* <ul>
|
||||
* <li>Component client property {@link #STYLE_CLASS} is set to {@code inTextField}.
|
||||
* <li>If component is a button or toggle button, client property {@link #BUTTON_TYPE}
|
||||
* is set to {@link #BUTTON_TYPE_TOOLBAR_BUTTON}
|
||||
* and button cursor is set to default cursor (if not set).
|
||||
* <li>If component is a toolbar, client property {@link #STYLE_CLASS}
|
||||
* is set to {@code inTextField} on all toolbar children
|
||||
* and toolbar cursor is set to default cursor (if not set).
|
||||
* </ul>
|
||||
* Because text fields use the text cursor by default and the cursor is inherited by child components,
|
||||
* it may be necessary to explicitly set component cursor if you e.g. need the default arrow cursor.
|
||||
* E.g. {@code comp.setCursor( Cursor.getDefaultCursor() )}.
|
||||
* <p>
|
||||
* Styling is used to modify insets/margins and appearance of buttons and toolbars
|
||||
* so that they fit nicely into the text field and do not increase text field height.
|
||||
* See styles {@code [style]Button.inTextField} and {@code [style]ToolBar.inTextField}
|
||||
* in {@code Flat[Light|Dark]Laf.properties}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent";
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* See {@link #TEXT_FIELD_LEADING_COMPONENT} for details.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent";
|
||||
|
||||
/**
|
||||
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||
* if the text field is not empty, editable and enabled. Default is {@code false}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton";
|
||||
|
||||
/**
|
||||
* Specifies the callback that is invoked when a "clear" (or "cancel") button is clicked.
|
||||
* If a callback is specified than it is responsible for clearing the text field.
|
||||
* Without callback, the text field clears itself.
|
||||
* <p>
|
||||
* Either use a {@link java.lang.Runnable}:
|
||||
* <pre>{@code
|
||||
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||
* (Runnable) () -> {
|
||||
* // clear field here or cancel search
|
||||
* } );
|
||||
* }</pre>
|
||||
* Or use a {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||
* that receives the text field as parameter:
|
||||
* <pre>{@code
|
||||
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||
* (Consumer<JTextComponent>) textField -> {
|
||||
* // clear field here or cancel search
|
||||
* } );
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Runnable}
|
||||
* or {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||
*
|
||||
* @see #TEXT_FIELD_SHOW_CLEAR_BUTTON
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback";
|
||||
|
||||
|
||||
//---- JToggleButton ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||
* Placement of underline if toggle button type is {@link #BUTTON_TYPE_TAB}
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||
* <strong>SupportedValues:</strong>
|
||||
* {@link SwingConstants#BOTTOM} (default)
|
||||
* {@link SwingConstants#TOP},
|
||||
* {@link SwingConstants#LEFT} or
|
||||
* {@link SwingConstants#RIGHT}
|
||||
*
|
||||
* @since 2.3
|
||||
*/
|
||||
String TAB_BUTTON_UNDERLINE_PLACEMENT = "JToggleButton.tab.underlinePlacement";
|
||||
|
||||
/**
|
||||
* Thickness of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||
@@ -759,6 +1242,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
||||
|
||||
|
||||
//---- JTree --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -778,6 +1262,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
||||
|
||||
|
||||
//---- helper methods -----------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -801,8 +1286,7 @@ public interface FlatClientProperties
|
||||
* If the client property is not set, or not a {@link Boolean}, defaultValue is returned.
|
||||
*/
|
||||
static Boolean clientPropertyBooleanStrict( JComponent c, String key, Boolean defaultValue ) {
|
||||
Object value = c.getClientProperty( key );
|
||||
return (value instanceof Boolean) ? (Boolean) value : defaultValue;
|
||||
return clientProperty( c, key, defaultValue, Boolean.class );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -819,7 +1303,18 @@ public interface FlatClientProperties
|
||||
* If the client property is not set, or not a color, defaultValue is returned.
|
||||
*/
|
||||
static Color clientPropertyColor( JComponent c, String key, Color defaultValue ) {
|
||||
return clientProperty( c, key, defaultValue, Color.class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the specified client property if it is an instance of
|
||||
* the specified type. Otherwise, defaultValue is returned.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
@SuppressWarnings( "unchecked" )
|
||||
static <T> T clientProperty( JComponent c, String key, T defaultValue, Class<T> type ) {
|
||||
Object value = c.getClientProperty( key );
|
||||
return (value instanceof Color) ? (Color) value : defaultValue;
|
||||
return type.isInstance( value ) ? (T) value : defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ public class FlatDarculaLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatDarculaLaf() );
|
||||
|
||||
@@ -33,6 +33,8 @@ public class FlatDarkLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatDarkLaf() );
|
||||
|
||||
@@ -26,7 +26,7 @@ import javax.swing.UIDefaults;
|
||||
* Allows loading of additional .properties files from addon JARs.
|
||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||
* <p>
|
||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
||||
* If you extend this class in an addon JAR, you also have to add a text file named
|
||||
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
||||
* to the addon JAR. The file must contain a single line with the class name.
|
||||
* <p>
|
||||
@@ -61,7 +61,7 @@ public abstract class FlatDefaultsAddon
|
||||
|
||||
/**
|
||||
* Returns the priority used to sort addon loading.
|
||||
* The order is only important if you want overwrite UI defaults of other addons.
|
||||
* The order is only important if you want to overwrite UI defaults of other addons.
|
||||
* Lower numbers mean higher priority.
|
||||
* Returns 10000 by default.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf;
|
||||
/**
|
||||
* Default color palette for action icons and object icons.
|
||||
* <p>
|
||||
* The idea is to use only this well defined set of colors in SVG icons and
|
||||
* The idea is to use only this well-defined set of colors in SVG icons, and
|
||||
* then they are replaced at runtime to dark variants or to other theme colors.
|
||||
* Then a single SVG icon (light variant) can be used for dark themes too.
|
||||
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
||||
@@ -35,7 +35,7 @@ package com.formdev.flatlaf;
|
||||
* <p>
|
||||
* You may use these colors also in your application (outside of SVG icons), but do
|
||||
* not use the RGB values defined in this enum.<br>
|
||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
* Instead, use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,8 @@ class FlatInputMaps
|
||||
}
|
||||
|
||||
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
||||
"SPACE", "spacePopup",
|
||||
// Space key still shows popup, but from FlatComboBoxUI.FlatKeySelectionManager
|
||||
// "SPACE", "spacePopup",
|
||||
|
||||
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
||||
"DOWN", mac( "selectNext2", "selectNext" ),
|
||||
@@ -70,7 +71,7 @@ class FlatInputMaps
|
||||
);
|
||||
}
|
||||
|
||||
// join ltr and rtl bindings to fix up/down/etc keys in right-to-left component orientation
|
||||
// join ltr and rtl bindings to fix up/down/etc. keys in right-to-left component orientation
|
||||
Object[] bindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings" );
|
||||
Object[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
||||
if( bindings != null && rtlBindings != null ) {
|
||||
@@ -596,7 +597,7 @@ class FlatInputMaps
|
||||
//---- class LazyInputMapEx -----------------------------------------------
|
||||
|
||||
/**
|
||||
* Lazily creates a input map.
|
||||
* Lazily creates an input map.
|
||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||
*/
|
||||
private static class LazyInputMapEx
|
||||
|
||||
@@ -34,6 +34,8 @@ public class FlatIntelliJLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatIntelliJLaf() );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,8 @@ public class FlatLightLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatLightLaf() );
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -96,7 +97,7 @@ public class FlatPropertiesLaf
|
||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
lafClasses.add( FlatLaf.class );
|
||||
switch( baseTheme.toLowerCase() ) {
|
||||
switch( baseTheme.toLowerCase( Locale.ENGLISH ) ) {
|
||||
default:
|
||||
case "light":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -34,7 +35,7 @@ public interface FlatSystemProperties
|
||||
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
||||
* which has the same syntax as this one.
|
||||
* <p>
|
||||
* Since FlatLaf 1.1.2: Scale factors less then 100% are allowed.
|
||||
* Since FlatLaf 1.1.2: Scale factors less than 100% are allowed.
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
||||
*/
|
||||
@@ -81,7 +82,7 @@ public interface FlatSystemProperties
|
||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||
* UI default {@code TitlePane.useWindowDecorations}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -92,17 +93,20 @@ public interface FlatSystemProperties
|
||||
* Specifies whether JetBrains Runtime custom window decorations should be used
|
||||
* when creating {@code JFrame} or {@code JDialog}.
|
||||
* Requires that the application runs in a
|
||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
|
||||
* <a href="https://github.com/JetBrains/JetBrainsRuntime/wiki">JetBrains Runtime</a>
|
||||
* (based on OpenJDK).
|
||||
* <p>
|
||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||
* Then FlatLaf native window decorations are used.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> {@code true}
|
||||
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
||||
*
|
||||
* @deprecated No longer used since FlatLaf 3.3. Retained for API compatibility.
|
||||
*/
|
||||
@Deprecated
|
||||
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
||||
|
||||
/**
|
||||
@@ -116,7 +120,7 @@ public interface FlatSystemProperties
|
||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -139,6 +143,53 @@ 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 native FlatLaf libraries have been extracted.
|
||||
* 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"}, then {@link System#loadLibrary(String)} is
|
||||
* used to load the native library.
|
||||
* 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}.
|
||||
* (supported since FlatLaf 2.6)
|
||||
* <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.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
|
||||
|
||||
/**
|
||||
* Checks whether a system property is set and returns {@code true} if its value
|
||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||
|
||||
@@ -23,13 +23,17 @@ import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import com.formdev.flatlaf.json.Json;
|
||||
@@ -37,6 +41,7 @@ import com.formdev.flatlaf.json.ParseException;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
||||
@@ -60,9 +65,9 @@ public class IntelliJTheme
|
||||
|
||||
private final boolean isMaterialUILite;
|
||||
|
||||
private final Map<String, String> colors;
|
||||
private final Map<String, Object> ui;
|
||||
private final Map<String, Object> icons;
|
||||
private Map<String, String> colors;
|
||||
private Map<String, Object> ui;
|
||||
private Map<String, Object> icons;
|
||||
|
||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
||||
|
||||
@@ -72,6 +77,8 @@ public class IntelliJTheme
|
||||
*
|
||||
* The input stream is automatically closed.
|
||||
* Using a buffered input stream is not necessary.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup( InputStream in ) {
|
||||
try {
|
||||
@@ -162,8 +169,11 @@ public class IntelliJTheme
|
||||
applyCheckBoxColors( defaults );
|
||||
|
||||
// copy values
|
||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() )
|
||||
defaults.put( e.getKey(), defaults.get( e.getValue() ) );
|
||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
||||
Object value = defaults.get( e.getValue() );
|
||||
if( value != null )
|
||||
defaults.put( e.getKey(), value );
|
||||
}
|
||||
|
||||
// IDEA does not paint button background if disabled, but FlatLaf does
|
||||
Object panelBackground = defaults.get( "Panel.background" );
|
||||
@@ -175,7 +185,7 @@ public class IntelliJTheme
|
||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
|
||||
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||
// IDEA uses an SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||
Object helpButtonBackground = defaults.get( "Button.startBackground" );
|
||||
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
||||
if( helpButtonBackground == null )
|
||||
@@ -190,8 +200,9 @@ public class IntelliJTheme
|
||||
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
|
||||
|
||||
// IDEA uses TextField.background for editable ComboBox and Spinner
|
||||
defaults.put( "ComboBox.editableBackground", defaults.get( "TextField.background" ) );
|
||||
defaults.put( "Spinner.background", defaults.get( "TextField.background" ) );
|
||||
Object textFieldBackground = get( defaults, themeSpecificDefaults, "TextField.background" );
|
||||
defaults.put( "ComboBox.editableBackground", textFieldBackground );
|
||||
defaults.put( "Spinner.background", textFieldBackground );
|
||||
|
||||
// Spinner arrow button always has same colors as ComboBox arrow button
|
||||
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
|
||||
@@ -199,22 +210,41 @@ public class IntelliJTheme
|
||||
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
|
||||
|
||||
// some themes specify colors for TextField.background, but forget to specify it for other components
|
||||
// (probably because those components are not used in IntelliJ)
|
||||
if( uiKeys.contains( "TextField.background" ) ) {
|
||||
Object textFieldBackground = defaults.get( "TextField.background" );
|
||||
if( !uiKeys.contains( "FormattedTextField.background" ) )
|
||||
defaults.put( "FormattedTextField.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "PasswordField.background" ) )
|
||||
defaults.put( "PasswordField.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "EditorPane.background" ) )
|
||||
defaults.put( "EditorPane.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "TextArea.background" ) )
|
||||
defaults.put( "TextArea.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "TextPane.background" ) )
|
||||
defaults.put( "TextPane.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "Spinner.background" ) )
|
||||
defaults.put( "Spinner.background", textFieldBackground );
|
||||
}
|
||||
// (probably because those components are not used in IntelliJ IDEA)
|
||||
putAll( defaults, textFieldBackground,
|
||||
"EditorPane.background",
|
||||
"FormattedTextField.background",
|
||||
"PasswordField.background",
|
||||
"TextArea.background",
|
||||
"TextPane.background"
|
||||
);
|
||||
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionBackground" ),
|
||||
"EditorPane.selectionBackground",
|
||||
"FormattedTextField.selectionBackground",
|
||||
"PasswordField.selectionBackground",
|
||||
"TextArea.selectionBackground",
|
||||
"TextPane.selectionBackground"
|
||||
);
|
||||
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionForeground" ),
|
||||
"EditorPane.selectionForeground",
|
||||
"FormattedTextField.selectionForeground",
|
||||
"PasswordField.selectionForeground",
|
||||
"TextArea.selectionForeground",
|
||||
"TextPane.selectionForeground"
|
||||
);
|
||||
|
||||
// fix disabled and not-editable backgrounds for text components, combobox and spinner
|
||||
// (IntelliJ IDEA does not use those colors; instead it used background color of parent)
|
||||
putAll( defaults, panelBackground,
|
||||
"ComboBox.disabledBackground",
|
||||
"EditorPane.disabledBackground", "EditorPane.inactiveBackground",
|
||||
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
|
||||
"PasswordField.disabledBackground", "PasswordField.inactiveBackground",
|
||||
"Spinner.disabledBackground",
|
||||
"TextArea.disabledBackground", "TextArea.inactiveBackground",
|
||||
"TextField.disabledBackground", "TextField.inactiveBackground",
|
||||
"TextPane.disabledBackground", "TextPane.inactiveBackground"
|
||||
);
|
||||
|
||||
// fix ToggleButton
|
||||
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
||||
@@ -241,15 +271,68 @@ public class IntelliJTheme
|
||||
if( rowHeight > 22 )
|
||||
defaults.put( "Tree.rowHeight", 22 );
|
||||
|
||||
// get (and remove) theme specific wildcard replacements, which override all other defaults that end with same suffix
|
||||
HashMap<String, Object> wildcards = new HashMap<>();
|
||||
Iterator<Entry<Object, Object>> it = themeSpecificDefaults.entrySet().iterator();
|
||||
while( it.hasNext() ) {
|
||||
Entry<Object, Object> e = it.next();
|
||||
String key = (String) e.getKey();
|
||||
if( key.startsWith( "*." ) ) {
|
||||
wildcards.put( key.substring( "*.".length() ), e.getValue() );
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// override UI defaults with theme specific wildcard replacements
|
||||
if( !wildcards.isEmpty() ) {
|
||||
for( Object key : defaults.keySet().toArray() ) {
|
||||
int dot;
|
||||
if( !(key instanceof String) ||
|
||||
(dot = ((String)key).lastIndexOf( '.' )) < 0 )
|
||||
continue;
|
||||
|
||||
String wildcardKey = ((String)key).substring( dot + 1 );
|
||||
Object wildcardValue = wildcards.get( wildcardKey );
|
||||
if( wildcardValue != null )
|
||||
defaults.put( key, wildcardValue );
|
||||
}
|
||||
}
|
||||
|
||||
// apply theme specific UI defaults at the end to allow overwriting
|
||||
defaults.putAll( themeSpecificDefaults );
|
||||
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
||||
Object key = e.getKey();
|
||||
Object value = e.getValue();
|
||||
|
||||
// append styles to existing styles
|
||||
if( key instanceof String && ((String)key).startsWith( "[style]" ) ) {
|
||||
Object oldValue = defaults.get( key );
|
||||
if( oldValue != null )
|
||||
value = oldValue + "; " + value;
|
||||
}
|
||||
|
||||
defaults.put( key, value );
|
||||
}
|
||||
|
||||
// let Java release memory
|
||||
colors = null;
|
||||
ui = null;
|
||||
icons = null;
|
||||
}
|
||||
|
||||
private Object get( UIDefaults defaults, Map<Object, Object> themeSpecificDefaults, String key ) {
|
||||
return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) );
|
||||
}
|
||||
|
||||
private void putAll( UIDefaults defaults, Object value, String... keys ) {
|
||||
for( String key : keys )
|
||||
defaults.put( key, value );
|
||||
}
|
||||
|
||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||
// 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 );
|
||||
}
|
||||
|
||||
@@ -284,7 +367,7 @@ public class IntelliJTheme
|
||||
|
||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
||||
String value = e.getValue();
|
||||
ColorUIResource color = UIDefaultsLoader.parseColor( value );
|
||||
ColorUIResource color = parseColor( value );
|
||||
if( color != null ) {
|
||||
String key = e.getKey();
|
||||
namedColors.put( key, color );
|
||||
@@ -299,23 +382,47 @@ public class IntelliJTheme
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
||||
if( value instanceof Map ) {
|
||||
for( Map.Entry<String, Object> e : ((Map<String, Object>)value).entrySet() )
|
||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
||||
Map<String, Object> map = (Map<String, Object>)value;
|
||||
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
|
||||
String osKey = SystemInfo.isWindows ? "os.windows"
|
||||
: SystemInfo.isMacOS ? "os.mac"
|
||||
: SystemInfo.isLinux ? "os.linux" : null;
|
||||
if( osKey != null && map.containsKey( osKey ) )
|
||||
apply( key, map.get( osKey ), defaults, defaultsKeysCache, uiKeys );
|
||||
else if( map.containsKey( "os.default" ) )
|
||||
apply( key, map.get( "os.default" ), defaults, defaultsKeysCache, uiKeys );
|
||||
} else {
|
||||
for( Map.Entry<String, Object> e : map.entrySet() )
|
||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
||||
}
|
||||
} else {
|
||||
if( "".equals( value ) )
|
||||
return; // ignore empty value
|
||||
|
||||
uiKeys.add( key );
|
||||
|
||||
// fix ComboBox size and Spinner border in all Material UI Lite themes
|
||||
if( isMaterialUILite && (key.equals( "ComboBox.padding" ) || key.equals( "Spinner.border" )) )
|
||||
return; // ignore
|
||||
// ignore some properties that affect sizes
|
||||
if( key.endsWith( ".border" ) ||
|
||||
key.endsWith( ".rowHeight" ) ||
|
||||
key.equals( "ComboBox.padding" ) ||
|
||||
key.equals( "Spinner.padding" ) ||
|
||||
key.equals( "Tree.leftChildIndent" ) ||
|
||||
key.equals( "Tree.rightChildIndent" ) )
|
||||
return; // ignore
|
||||
|
||||
// map keys
|
||||
key = uiKeyMapping.getOrDefault( key, key );
|
||||
if( key.isEmpty() )
|
||||
return; // ignore key
|
||||
|
||||
// exclude properties
|
||||
int dot = key.indexOf( '.' );
|
||||
if( dot > 0 && uiKeyExcludes.contains( key.substring( 0, dot + 1 ) ) )
|
||||
return;
|
||||
|
||||
if( uiKeyDoNotOverride.contains( key ) && uiKeys.contains( key ) )
|
||||
return;
|
||||
|
||||
uiKeys.add( key );
|
||||
|
||||
String valueStr = value.toString();
|
||||
|
||||
// map named colors
|
||||
@@ -338,7 +445,7 @@ public class IntelliJTheme
|
||||
|
||||
// parse value
|
||||
try {
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr );
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr, null );
|
||||
} catch( RuntimeException ex ) {
|
||||
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
||||
return; // ignore invalid value
|
||||
@@ -361,7 +468,8 @@ public class IntelliJTheme
|
||||
// replace all values in UI defaults that match the wildcard key
|
||||
for( Object k : defaultsKeysCache ) {
|
||||
if( k.equals( "Desktop.background" ) ||
|
||||
k.equals( "DesktopIcon.background" ) )
|
||||
k.equals( "DesktopIcon.background" ) ||
|
||||
k.equals( "TabbedPane.focusColor" ) )
|
||||
continue;
|
||||
|
||||
if( k instanceof String ) {
|
||||
@@ -419,12 +527,20 @@ public class IntelliJTheme
|
||||
ColorUIResource color = namedColors.get( value );
|
||||
|
||||
// parse color
|
||||
return (color != null) ? color : UIDefaultsLoader.parseColor( value );
|
||||
return (color != null) ? color : parseColor( value );
|
||||
}
|
||||
|
||||
private ColorUIResource parseColor( String value ) {
|
||||
try {
|
||||
return UIDefaultsLoader.parseColor( value );
|
||||
} catch( IllegalArgumentException ex ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
||||
* this two components are specified in "icons > ColorPalette".
|
||||
* these two components are specified in "icons > ColorPalette".
|
||||
* FlatLaf uses vector icons and expects colors for the two components in UI defaults.
|
||||
*/
|
||||
private void applyCheckBoxColors( UIDefaults defaults ) {
|
||||
@@ -444,18 +560,6 @@ public class IntelliJTheme
|
||||
if( !key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
||||
continue;
|
||||
|
||||
if( key.equals( "Checkbox.Background.Default" ) ||
|
||||
key.equals( "Checkbox.Foreground.Selected" ) )
|
||||
{
|
||||
// This two keys do not work correctly in IDEA because they
|
||||
// map SVG color "#ffffff" to another color, but checkBox.svg and
|
||||
// radio.svg (in package com.intellij.ide.ui.laf.icons.intellij)
|
||||
// use "#fff". So use white to get same appearance as in IDEA.
|
||||
value = "#ffffff";
|
||||
}
|
||||
|
||||
String key2 = checkboxDuplicateColors.get( key );
|
||||
|
||||
if( dark )
|
||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||
|
||||
@@ -469,6 +573,7 @@ public class IntelliJTheme
|
||||
if( color != null ) {
|
||||
defaults.put( newKey, color );
|
||||
|
||||
String key2 = checkboxDuplicateColors.get( key + ".Dark");
|
||||
if( key2 != null ) {
|
||||
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
||||
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
||||
@@ -504,18 +609,18 @@ public class IntelliJTheme
|
||||
// for filled checkbox/radiobutton used in light themes
|
||||
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
||||
defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
||||
defaults.put( "CheckBox.icon[filled].selectedFocusedBackground", defaults.get( "CheckBox.icon[filled].selectedBackground" ) );
|
||||
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 = new String[] {
|
||||
String[] focusedBorderColorKeys = {
|
||||
"CheckBox.icon.focusedBorderColor",
|
||||
"CheckBox.icon.selectedFocusedBorderColor",
|
||||
"CheckBox.icon.focusedSelectedBorderColor",
|
||||
"CheckBox.icon[filled].focusedBorderColor",
|
||||
"CheckBox.icon[filled].selectedFocusedBorderColor",
|
||||
"CheckBox.icon[filled].focusedSelectedBorderColor",
|
||||
};
|
||||
for( String key : focusedBorderColorKeys ) {
|
||||
Color color = defaults.getColor( key );
|
||||
@@ -533,22 +638,66 @@ public class IntelliJTheme
|
||||
defaults.put( destKey, defaults.get( srcKey ) );
|
||||
}
|
||||
|
||||
private static final Set<String> uiKeyExcludes;
|
||||
private static final Set<String> uiKeyDoNotOverride;
|
||||
/** Rename UI default keys (key --> value). */
|
||||
private static Map<String, String> uiKeyMapping = new HashMap<>();
|
||||
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
||||
/** Copy UI default keys (value --> key). */
|
||||
private static Map<String, String> uiKeyCopying = new HashMap<>();
|
||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
private static final Map<String, String> uiKeyCopying = new LinkedHashMap<>();
|
||||
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
|
||||
static {
|
||||
// IntelliJ UI properties that are not used in FlatLaf
|
||||
uiKeyExcludes = new HashSet<>( Arrays.asList(
|
||||
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
||||
"AvailableMnemonic.",
|
||||
"BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
||||
"Canvas.", "CodeWithMe.", "ComboBoxButton.", "CompletionPopup.", "ComplexPopup.", "Content.",
|
||||
"CurrentMnemonic.", "Counter.",
|
||||
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DragAndDrop.",
|
||||
"Editor.", "EditorGroupsTabs.", "EditorTabs.",
|
||||
"FileColor.", "FlameGraph.", "Focus.",
|
||||
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
|
||||
"HeaderColor.", "HelpTooltip.", "Hg.",
|
||||
"IconBadge.", "InformationHint.", "InplaceRefactoringPopup.",
|
||||
"Lesson.", "Link.", "LiveIndicator.",
|
||||
"MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
||||
"OnePixelDivider.", "OptionButton.", "Outline.",
|
||||
"ParameterInfo.", "Plugins.", "ProgressIcon.", "PsiViewer.",
|
||||
"ReviewList.", "RunWidget.",
|
||||
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
|
||||
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
|
||||
"StatusBar.",
|
||||
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.",
|
||||
"UIDesigner.", "UnattendedHostStatus.",
|
||||
"ValidationTooltip.", "VersionControl.",
|
||||
"WelcomeScreen.",
|
||||
|
||||
// lower case
|
||||
"darcula.", "dropArea.", "icons.", "intellijlaf.", "macOSWindow.", "material.", "tooltips.",
|
||||
|
||||
// possible typos in .theme.json files
|
||||
"Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link."
|
||||
) );
|
||||
|
||||
uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
|
||||
"TabbedPane.selectedForeground"
|
||||
) );
|
||||
|
||||
// ComboBox
|
||||
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
||||
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
|
||||
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.background", "ComboBox.buttonEditableBackground" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
||||
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" );
|
||||
@@ -594,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" );
|
||||
@@ -618,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,22 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Toolkit;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.swing.text.StyleContext;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
@@ -67,7 +71,7 @@ class LinuxFontPolicy
|
||||
if( word.endsWith( "," ) )
|
||||
word = word.substring( 0, word.length() - 1 ).trim();
|
||||
|
||||
String lword = word.toLowerCase();
|
||||
String lword = word.toLowerCase( Locale.ENGLISH );
|
||||
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
|
||||
style |= Font.ITALIC;
|
||||
else if( lword.equals( "bold" ) )
|
||||
@@ -103,7 +107,7 @@ class LinuxFontPolicy
|
||||
size = 1;
|
||||
|
||||
// handle logical font names
|
||||
String logicalFamily = mapFcName( family.toLowerCase() );
|
||||
String logicalFamily = mapFcName( family.toLowerCase( Locale.ENGLISH ) );
|
||||
if( logicalFamily != null )
|
||||
family = logicalFamily;
|
||||
|
||||
@@ -121,17 +125,28 @@ class LinuxFontPolicy
|
||||
for(;;) {
|
||||
Font font = createFont( family, style, size, dsize );
|
||||
|
||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||
if( !"Dialog".equals( font.getFamily() ) || "Dialog".equals( family ) )
|
||||
if( Font.DIALOG.equals( family ) )
|
||||
return font;
|
||||
|
||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||
if( !Font.DIALOG.equals( font.getFamily() ) ) {
|
||||
// check for font problems
|
||||
// - font height much larger than expected (e.g. font Inter; Oracle Java 8)
|
||||
// - character width is zero (e.g. font Cantarell; Fedora; Oracle Java 8)
|
||||
FontMetrics fm = StyleContext.getDefaultStyleContext().getFontMetrics( font );
|
||||
if( fm.getHeight() > size * 2 || fm.stringWidth( "a" ) == 0 )
|
||||
return createFont( Font.DIALOG, style, size, dsize );
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
// find last word in family
|
||||
int index = family.lastIndexOf( ' ' );
|
||||
if( index < 0 )
|
||||
return createFont( "Dialog", style, size, dsize );
|
||||
return createFont( Font.DIALOG, style, size, dsize );
|
||||
|
||||
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
||||
String lastWord = family.substring( index + 1 ).toLowerCase();
|
||||
String lastWord = family.substring( index + 1 ).toLowerCase( Locale.ENGLISH );
|
||||
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
|
||||
style |= Font.BOLD;
|
||||
|
||||
@@ -158,7 +173,7 @@ class LinuxFontPolicy
|
||||
|
||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||
if( value instanceof Integer ) {
|
||||
int dpi = ((Integer)value).intValue() / 1024;
|
||||
int dpi = (Integer) value / 1024;
|
||||
if( dpi == -1 )
|
||||
dpi = 96;
|
||||
if( dpi < 50 )
|
||||
@@ -185,10 +200,10 @@ class LinuxFontPolicy
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default font for KDE for KDE configuration files.
|
||||
* Gets the default font for KDE from KDE configuration files.
|
||||
*
|
||||
* The Swing fonts are not updated when the user changes system font size
|
||||
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
||||
* (System Settings > Fonts > Force Font DPI). An application restart is necessary.
|
||||
* This is the same behavior as in native KDE applications.
|
||||
*
|
||||
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
|
||||
@@ -245,6 +260,7 @@ class LinuxFontPolicy
|
||||
return createFont( family, style, size, dsize );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone
|
||||
private static List<String> readConfig( String filename ) {
|
||||
File userHome = new File( System.getProperty( "user.home" ) );
|
||||
|
||||
@@ -265,8 +281,10 @@ class LinuxFontPolicy
|
||||
|
||||
// read config file
|
||||
ArrayList<String> lines = new ArrayList<>( 200 );
|
||||
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
||||
String line = null;
|
||||
try( BufferedReader reader = new BufferedReader( new InputStreamReader(
|
||||
new FileInputStream( file ), StandardCharsets.US_ASCII ) ) )
|
||||
{
|
||||
String line;
|
||||
while( (line = reader.readLine()) != null )
|
||||
lines.add( line );
|
||||
} catch( IOException ex ) {
|
||||
@@ -309,6 +327,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;
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.MouseInfo;
|
||||
import java.awt.Point;
|
||||
import java.awt.PointerInfo;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.RootPaneContainer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* Improves usability of submenus by using a
|
||||
* <a href="https://height.app/blog/guide-to-build-context-menus#safe-triangle">safe triangle</a>
|
||||
* to avoid that the submenu closes while the user moves the mouse to it.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class SubMenuUsabilityHelper
|
||||
implements ChangeListener
|
||||
{
|
||||
private static final String KEY_USE_SAFE_TRIANGLE = "Menu.useSafeTriangle";
|
||||
private static final String KEY_SHOW_SAFE_TRIANGLE = "FlatLaf.debug.menu.showSafeTriangle";
|
||||
|
||||
// Using a static field to ensure that there is only one instance in the system.
|
||||
// Multiple instances would freeze the application.
|
||||
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
|
||||
private static SubMenuUsabilityHelper instance;
|
||||
|
||||
private SubMenuEventQueue subMenuEventQueue;
|
||||
private SafeTrianglePainter safeTrianglePainter;
|
||||
private boolean changePending;
|
||||
|
||||
// mouse location in screen coordinates
|
||||
private int mouseX;
|
||||
private int mouseY;
|
||||
|
||||
// target popup bounds in screen coordinates
|
||||
private int targetX;
|
||||
private int targetTopY;
|
||||
private int targetBottomY;
|
||||
|
||||
private Rectangle invokerBounds;
|
||||
|
||||
static synchronized boolean install() {
|
||||
if( instance != null )
|
||||
return false;
|
||||
|
||||
instance = new SubMenuUsabilityHelper();
|
||||
MenuSelectionManager.defaultManager().addChangeListener( instance );
|
||||
return true;
|
||||
}
|
||||
|
||||
static synchronized void uninstall() {
|
||||
if( instance == null )
|
||||
return;
|
||||
|
||||
MenuSelectionManager.defaultManager().removeChangeListener( instance );
|
||||
instance.uninstallEventQueue();
|
||||
instance = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e ) {
|
||||
if( !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||
return;
|
||||
|
||||
// handle menu selection change later, but only once in case of temporary changes
|
||||
// e.g. moving mouse from one menu item to another one, fires two events:
|
||||
// 1. old menu item is removed from menu selection
|
||||
// 2. new menu item is added to menu selection
|
||||
synchronized( this ) {
|
||||
if( changePending )
|
||||
return;
|
||||
changePending = true;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater( () -> {
|
||||
synchronized( this ) {
|
||||
changePending = false;
|
||||
}
|
||||
menuSelectionChanged();
|
||||
} );
|
||||
}
|
||||
|
||||
private void menuSelectionChanged() {
|
||||
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
|
||||
/*debug
|
||||
System.out.println( "--- " + path.length );
|
||||
for( int i = 0; i < path.length; i++ )
|
||||
System.out.println( " " + i + ": " + path[i].getClass().getName() );
|
||||
debug*/
|
||||
|
||||
// find submenu in menu selection
|
||||
int subMenuIndex = findSubMenu( path );
|
||||
|
||||
// uninstall if there is no submenu in selection
|
||||
if( subMenuIndex < 0 || subMenuIndex != path.length - 1 ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// get current mouse location
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point mouseLocation = (pointerInfo != null) ? pointerInfo.getLocation() : new Point();
|
||||
mouseX = mouseLocation.x;
|
||||
mouseY = mouseLocation.y;
|
||||
|
||||
// check whether popup is showing, which is e.g. not the case if it is empty
|
||||
JPopupMenu popup = (JPopupMenu) path[subMenuIndex];
|
||||
if( !popup.isShowing() ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// get invoker screen bounds
|
||||
Component invoker = popup.getInvoker();
|
||||
invokerBounds = (invoker != null && invoker.isShowing())
|
||||
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
||||
: null;
|
||||
|
||||
// check whether mouse location is within invoker
|
||||
if( invokerBounds != null && !invokerBounds.contains( mouseX, mouseY ) ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// compute top/bottom target locations
|
||||
Point popupLocation = popup.getLocationOnScreen();
|
||||
Dimension popupSize = popup.getSize();
|
||||
targetX = (mouseX < popupLocation.x + (popupSize.width / 2))
|
||||
? popupLocation.x
|
||||
: popupLocation.x + popupSize.width;
|
||||
targetTopY = popupLocation.y;
|
||||
targetBottomY = popupLocation.y + popupSize.height;
|
||||
|
||||
// install own event queue to suppress mouse events when mouse is moved within safe triangle
|
||||
if( subMenuEventQueue == null )
|
||||
subMenuEventQueue = new SubMenuEventQueue();
|
||||
|
||||
// create safe triangle painter
|
||||
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
||||
safeTrianglePainter = new SafeTrianglePainter( popup );
|
||||
}
|
||||
|
||||
private void uninstallEventQueue() {
|
||||
if( subMenuEventQueue != null ) {
|
||||
subMenuEventQueue.uninstall();
|
||||
subMenuEventQueue = null;
|
||||
}
|
||||
|
||||
if( safeTrianglePainter != null ) {
|
||||
safeTrianglePainter.uninstall();
|
||||
safeTrianglePainter = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int findSubMenu( MenuElement[] path ) {
|
||||
for( int i = path.length - 1; i >= 1; i-- ) {
|
||||
if( path[i] instanceof JPopupMenu &&
|
||||
path[i - 1] instanceof JMenu &&
|
||||
!((JMenu)path[i - 1]).isTopLevelMenu() )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Polygon createSafeTriangle() {
|
||||
return new Polygon(
|
||||
new int[] { mouseX, targetX, targetX },
|
||||
new int[] { mouseY, targetTopY, targetBottomY },
|
||||
3 );
|
||||
}
|
||||
|
||||
//---- class SubMenuEventQueue --------------------------------------------
|
||||
|
||||
private class SubMenuEventQueue
|
||||
extends EventQueue
|
||||
{
|
||||
private Timer mouseUpdateTimer;
|
||||
private Timer timeoutTimer;
|
||||
|
||||
private int newMouseX;
|
||||
private int newMouseY;
|
||||
private AWTEvent lastMouseEvent;
|
||||
|
||||
SubMenuEventQueue() {
|
||||
// timer used to slightly delay update of mouse location used for safe triangle
|
||||
mouseUpdateTimer = new Timer( 50, e -> {
|
||||
mouseX = newMouseX;
|
||||
mouseY = newMouseY;
|
||||
|
||||
if( safeTrianglePainter != null )
|
||||
safeTrianglePainter.repaint();
|
||||
} );
|
||||
mouseUpdateTimer.setRepeats( false );
|
||||
|
||||
// timer used to timeout safe triangle when mouse stops moving
|
||||
timeoutTimer = new Timer( 200, e -> {
|
||||
if( invokerBounds != null && !invokerBounds.contains( newMouseX, newMouseY ) ) {
|
||||
// post last mouse event, which selects menu item at mouse location
|
||||
if( lastMouseEvent != null ) {
|
||||
postEvent( lastMouseEvent );
|
||||
lastMouseEvent = null;
|
||||
}
|
||||
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
} );
|
||||
timeoutTimer.setRepeats( false );
|
||||
|
||||
Toolkit.getDefaultToolkit().getSystemEventQueue().push( this );
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
mouseUpdateTimer.stop();
|
||||
mouseUpdateTimer = null;
|
||||
|
||||
timeoutTimer.stop();
|
||||
timeoutTimer = null;
|
||||
|
||||
lastMouseEvent = null;
|
||||
|
||||
super.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchEvent( AWTEvent e ) {
|
||||
int id = e.getID();
|
||||
|
||||
if( e instanceof MouseEvent &&
|
||||
(id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED) )
|
||||
{
|
||||
newMouseX = ((MouseEvent)e).getXOnScreen();
|
||||
newMouseY = ((MouseEvent)e).getYOnScreen();
|
||||
|
||||
if( safeTrianglePainter != null )
|
||||
safeTrianglePainter.repaint();
|
||||
|
||||
mouseUpdateTimer.stop();
|
||||
timeoutTimer.stop();
|
||||
|
||||
// check whether mouse moved within safe triangle
|
||||
if( createSafeTriangle().contains( newMouseX, newMouseY ) ) {
|
||||
// update mouse location delayed (this changes the safe triangle)
|
||||
mouseUpdateTimer.start();
|
||||
|
||||
timeoutTimer.start();
|
||||
|
||||
// remember last mouse event, which will be posted if the mouse stops moving
|
||||
lastMouseEvent = e;
|
||||
|
||||
// ignore mouse event
|
||||
return;
|
||||
}
|
||||
|
||||
// update mouse location immediately (this changes the safe triangle)
|
||||
mouseX = newMouseX;
|
||||
mouseY = newMouseY;
|
||||
}
|
||||
|
||||
super.dispatchEvent( e );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class SafeTrianglePainter ------------------------------------------
|
||||
|
||||
private class SafeTrianglePainter
|
||||
extends JComponent
|
||||
{
|
||||
SafeTrianglePainter( JPopupMenu popup ) {
|
||||
Window window = SwingUtilities.windowForComponent( popup.getInvoker() );
|
||||
if( window instanceof RootPaneContainer ) {
|
||||
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
|
||||
setSize( layeredPane.getSize() );
|
||||
layeredPane.add( this, Integer.valueOf( JLayeredPane.POPUP_LAYER + 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
Container parent = getParent();
|
||||
if( parent != null ) {
|
||||
parent.remove( this );
|
||||
parent.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
Point locationOnScreen = getLocationOnScreen();
|
||||
g.translate( -locationOnScreen.x, -locationOnScreen.y );
|
||||
|
||||
g.setColor( Color.red );
|
||||
((Graphics2D)g).draw( createSafeTriangle() );
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -23,13 +23,13 @@ import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||
|
||||
/**
|
||||
* Base class for animated icons that scales width and height, creates and initializes
|
||||
* Base class for animated icons that scale width and height, creates and initializes
|
||||
* a scaled graphics context for icon painting.
|
||||
* <p>
|
||||
* Subclasses do not need to scale icon painting.
|
||||
* <p>
|
||||
* This class does not store any state information (needed for animation) in its instance.
|
||||
* Instead a client property is set on the painted component.
|
||||
* Instead, a client property is set on the painted component.
|
||||
* This makes it possible to use a share icon instance for multiple components.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
|
||||
@@ -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,83 +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 optional
|
||||
* @uiDefault CheckBox.icon.focusedBackground Color optional
|
||||
* @uiDefault CheckBox.icon.selectedFocusedBorderColor Color optional; CheckBox.icon.focusedBorderColor is used if not specified
|
||||
* @uiDefault CheckBox.icon.selectedFocusedBackground Color optional; CheckBox.icon.focusedBackground is used if not specified
|
||||
* @uiDefault CheckBox.icon.selectedFocusedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified
|
||||
* @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; CheckBox.icon.hoverBackground is used if not specified
|
||||
* @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; CheckBox.icon.pressedBackground is used if not specified
|
||||
* @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 ) {
|
||||
@@ -110,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 ) {
|
||||
@@ -129,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 ) ) {
|
||||
@@ -143,7 +196,7 @@ public class FlatCheckBoxIcon
|
||||
|
||||
// paint border
|
||||
g.setColor( getBorderColor( c, selected ) );
|
||||
paintBorder( c, g );
|
||||
paintBorder( c, g, bw );
|
||||
|
||||
// paint background
|
||||
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ),
|
||||
@@ -151,14 +204,14 @@ public class FlatCheckBoxIcon
|
||||
if( bg.getAlpha() < 255 ) {
|
||||
// fill background with default color before filling with non-opaque background
|
||||
g.setColor( selected ? selectedBackground : background );
|
||||
paintBackground( c, g );
|
||||
paintBackground( c, g, bw );
|
||||
}
|
||||
g.setColor( bg );
|
||||
paintBackground( c, g );
|
||||
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
|
||||
@@ -167,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 );
|
||||
@@ -205,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;
|
||||
}
|
||||
@@ -212,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;
|
||||
|
||||
/**
|
||||
@@ -50,29 +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" );
|
||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "HelpButton.innerFocusWidth", FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 ) );
|
||||
protected final int borderWidth = FlatUIUtils.getUIInt( "HelpButton.borderWidth", 1 );
|
||||
@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 ) {
|
||||
/*
|
||||
@@ -80,16 +98,17 @@ public class FlatHelpButtonIcon
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
||||
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
||||
<path fill="#6E6E6E" d="M10,17 L12,17 L12,15 L10,15 L10,17 Z M11,5 C8.8,5 7,6.8 7,9 L9,9 C9,7.9 9.9,7 11,7 C12.1,7 13,7.9 13,9 C13,11 10,10.75 10,14 L12,14 C12,11.75 15,11.5 15,9 C15,6.8 13.2,5 11,5 Z"/>
|
||||
<path stroke="#6E6E6E" stroke-linecap="round" stroke-width="2" d="M8,8.5 C8.25,7 9.66585007,6 11,6 C12.5,6 14,7 14,8.5 C14,10.5 11,11 11,13"/>
|
||||
<circle cx="11" cy="16" r="1.2" fill="#6E6E6E"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
boolean enabled = c.isEnabled();
|
||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||
boolean enabled = c == null || c.isEnabled();
|
||||
boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
|
||||
|
||||
float xy = 0.5f;
|
||||
float wh = iconSize - 1;
|
||||
float wh = iconSize() - 1;
|
||||
|
||||
// paint outer focus border
|
||||
if( focused && FlatButtonUI.isFocusPainted( c ) ) {
|
||||
@@ -131,31 +150,32 @@ public class FlatHelpButtonIcon
|
||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||
|
||||
// paint question mark
|
||||
Path2D q = new Path2D.Float();
|
||||
q.moveTo( 11, 5 );
|
||||
q.curveTo( 8.8,5, 7,6.8, 7,9 );
|
||||
q.lineTo( 9, 9 );
|
||||
q.curveTo( 9,7.9, 9.9,7, 11,7 );
|
||||
q.curveTo( 12.1,7, 13,7.9, 13,9 );
|
||||
q.curveTo( 13,11, 10,10.75, 10,14 );
|
||||
q.lineTo( 12, 14 );
|
||||
q.curveTo( 12,11.75, 15,11.5, 15,9 );
|
||||
q.curveTo( 15,6.8, 13.2,5, 11,5 );
|
||||
q.closePath();
|
||||
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||
q.moveTo( 8,8.5 );
|
||||
q.curveTo( 8.25,7, 9.66585007,6, 11,6 );
|
||||
q.curveTo( 12.5,6, 14,7, 14,8.5 );
|
||||
q.curveTo( 14,10.5, 11,11, 11,13 );
|
||||
|
||||
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||
|
||||
g2.translate( focusWidth, focusWidth );
|
||||
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
||||
g2.fill( q );
|
||||
g2.fillRect( 10, 15, 2, 2 );
|
||||
g2.draw( q );
|
||||
g2.fill( new Ellipse2D.Float( 9.8f, 14.8f, 2.4f, 2.4f ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
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,17 +38,22 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
public abstract class FlatWindowAbstractIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final int symbolHeight;
|
||||
private final Color hoverBackground;
|
||||
private final Color pressedBackground;
|
||||
|
||||
public FlatWindowAbstractIcon() {
|
||||
this( UIManager.getDimension( "TitlePane.buttonSize" ),
|
||||
UIManager.getColor( "TitlePane.buttonHoverBackground" ),
|
||||
UIManager.getColor( "TitlePane.buttonPressedBackground" ) );
|
||||
/** @since 3.2 */
|
||||
protected FlatWindowAbstractIcon( String windowStyle ) {
|
||||
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ) );
|
||||
}
|
||||
|
||||
public FlatWindowAbstractIcon( Dimension size, Color hoverBackground, Color pressedBackground ) {
|
||||
/** @since 3.2 */
|
||||
protected FlatWindowAbstractIcon( Dimension size, int symbolHeight, Color hoverBackground, Color pressedBackground ) {
|
||||
super( size.width, size.height, null );
|
||||
this.symbolHeight = symbolHeight;
|
||||
this.hoverBackground = hoverBackground;
|
||||
this.pressedBackground = pressedBackground;
|
||||
}
|
||||
@@ -65,12 +71,23 @@ public abstract class FlatWindowAbstractIcon
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||
if( background != null ) {
|
||||
// disable antialiasing for background rectangle painting to avoid blurry edges when scaled (e.g. at 125% or 175%)
|
||||
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
||||
|
||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
||||
}
|
||||
}
|
||||
|
||||
protected Color getForeground( Component c ) {
|
||||
return c.getForeground();
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
protected int getSymbolHeight() {
|
||||
return symbolHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "close" icon for windows (frames and dialogs).
|
||||
@@ -38,27 +38,38 @@ import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
public class FlatWindowCloseIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
private final Color hoverForeground = UIManager.getColor( "TitlePane.closeHoverForeground" );
|
||||
private final Color pressedForeground = UIManager.getColor( "TitlePane.closePressedForeground" );
|
||||
private final Color hoverForeground;
|
||||
private final Color pressedForeground;
|
||||
|
||||
public FlatWindowCloseIcon() {
|
||||
super( UIManager.getDimension( "TitlePane.buttonSize" ),
|
||||
UIManager.getColor( "TitlePane.closeHoverBackground" ),
|
||||
UIManager.getColor( "TitlePane.closePressedBackground" ) );
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowCloseIcon( String windowStyle ) {
|
||||
super( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ) );
|
||||
|
||||
hoverForeground = FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle );
|
||||
pressedForeground = FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int ix2 = ix + iwh - 1;
|
||||
int iy2 = iy + iwh - 1;
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
||||
path.append( new Line2D.Float( ix, iy2, ix2, iy ), false );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||
path.moveTo( ix, iy );
|
||||
path.lineTo( ix2, iy2 );
|
||||
path.moveTo( ix, iy2 );
|
||||
path.lineTo( ix2, iy );
|
||||
g.setStroke( new BasicStroke( thickness ) );
|
||||
g.draw( path );
|
||||
}
|
||||
|
||||
@@ -27,11 +27,17 @@ public class FlatWindowIconifyIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
public FlatWindowIconifyIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowIconifyIcon( String windowStyle ) {
|
||||
super( windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iw = (int) (10 * scaleFactor);
|
||||
int iw = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ih = (int) scaleFactor;
|
||||
int ix = x + ((width - iw) / 2);
|
||||
int iy = y + ((height - ih) / 2);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "maximize" icon for windows (frames and dialogs).
|
||||
@@ -28,15 +29,24 @@ public class FlatWindowMaximizeIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
public FlatWindowMaximizeIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowMaximizeIcon( String windowStyle ) {
|
||||
super( windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
|
||||
g.fill( FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
||||
g.fill( SystemInfo.isWindows_11_orLater
|
||||
? FlatUIUtils.createRoundRectangle( ix, iy, iwh, iwh, thickness, arc, arc, arc, arc )
|
||||
: FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.geom.Area;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "restore" icon for windows (frames and dialogs).
|
||||
@@ -31,25 +32,46 @@ public class FlatWindowRestoreIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
public FlatWindowRestoreIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowRestoreIcon( String windowStyle ) {
|
||||
super( windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||
|
||||
int rwh = (int) (8 * scaleFactor);
|
||||
int rwh = (int) ((getSymbolHeight() - 2) * scaleFactor);
|
||||
int ro2 = iwh - rwh;
|
||||
|
||||
Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||
Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||
// upper-right rectangle
|
||||
Path2D r1 = SystemInfo.isWindows_11_orLater
|
||||
? FlatUIUtils.createRoundRectangle( ix + ro2, iy, rwh, rwh, thickness, arc, arcOuter, arc, arc )
|
||||
: FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||
|
||||
// lower-left rectangle
|
||||
Path2D r2 = SystemInfo.isWindows_11_orLater
|
||||
? FlatUIUtils.createRoundRectangle( ix, iy + ro2, rwh, rwh, thickness, arc, arc, arc, arc )
|
||||
: FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||
|
||||
// paint upper-right rectangle
|
||||
Area area = new Area( r1 );
|
||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||
if( SystemInfo.isWindows_11_orLater ) {
|
||||
area.subtract( new Area( new Rectangle2D.Float( ix, (float) (iy + scaleFactor), rwh, rwh ) ) );
|
||||
area.subtract( new Area( new Rectangle2D.Float( (float) (ix + scaleFactor), iy + ro2, rwh, rwh ) ) );
|
||||
} else
|
||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||
g.fill( area );
|
||||
|
||||
// paint lower-left rectangle
|
||||
g.fill( r2 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,9 +502,9 @@ class JsonParser {
|
||||
}
|
||||
|
||||
private boolean isHexDigit() {
|
||||
return current >= '0' && current <= '9'
|
||||
|| current >= 'a' && current <= 'f'
|
||||
|| current >= 'A' && current <= 'F';
|
||||
return (current >= '0' && current <= '9')
|
||||
|| (current >= 'a' && current <= 'f')
|
||||
|| (current >= 'A' && current <= 'F');
|
||||
}
|
||||
|
||||
private boolean isEndOfText() {
|
||||
|
||||
@@ -69,7 +69,7 @@ public class Location {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
if (!(obj instanceof Location)) {
|
||||
return false;
|
||||
}
|
||||
Location other = (Location)obj;
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.resources;
|
||||
|
||||
/**
|
||||
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
||||
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
|
||||
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||
* Otherwise, the compiler outputs a warning because this package is opened in module-info.java.
|
||||
* Also, when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.themes;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.FlatDarkLaf;
|
||||
|
||||
/**
|
||||
* A Flat LaF that imitates macOS dark look.
|
||||
* <p>
|
||||
* The UI defaults are loaded from {@code FlatMacDarkLaf.properties},
|
||||
* {@code FlatDarkLaf.properties} and {@code FlatLaf.properties}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 3
|
||||
*/
|
||||
public class FlatMacDarkLaf
|
||||
extends FlatDarkLaf
|
||||
{
|
||||
public static final String NAME = "FlatLaf macOS Dark";
|
||||
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatMacDarkLaf() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds this look and feel to the set of available look and feels.
|
||||
* <p>
|
||||
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||
* to query available LaFs and display them to the user in a combobox.
|
||||
*/
|
||||
public static void installLafInfo() {
|
||||
installLafInfo( NAME, FlatMacDarkLaf.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "FlatLaf macOS Dark Look and Feel";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDark() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.themes;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
|
||||
/**
|
||||
* A Flat LaF that imitates macOS light look.
|
||||
* <p>
|
||||
* The UI defaults are loaded from {@code FlatMacLightLaf.properties},
|
||||
* {@code FlatLightLaf.properties} and {@code FlatLaf.properties}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 3
|
||||
*/
|
||||
public class FlatMacLightLaf
|
||||
extends FlatLightLaf
|
||||
{
|
||||
public static final String NAME = "FlatLaf macOS Light";
|
||||
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatMacLightLaf() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds this look and feel to the set of available look and feels.
|
||||
* <p>
|
||||
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||
* to query available LaFs and display them to the user in a combobox.
|
||||
*/
|
||||
public static void installLafInfo() {
|
||||
installLafInfo( NAME, FlatMacLightLaf.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "FlatLaf macOS Light Look and Feel";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDark() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.awt.Graphics2D;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicArrowButton;
|
||||
|
||||
@@ -37,19 +38,21 @@ 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 float arrowThickness = 1;
|
||||
private float xOffset = 0;
|
||||
private float yOffset = 0;
|
||||
private boolean roundBorderAutoXOffset = true;
|
||||
|
||||
private boolean hover;
|
||||
private boolean pressed;
|
||||
@@ -58,14 +61,8 @@ public class FlatArrowButton
|
||||
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 );
|
||||
@@ -88,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;
|
||||
}
|
||||
@@ -109,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;
|
||||
}
|
||||
@@ -133,6 +157,16 @@ public class FlatArrowButton
|
||||
this.yOffset = yOffset;
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
public boolean isRoundBorderAutoXOffset() {
|
||||
return roundBorderAutoXOffset;
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
public void setRoundBorderAutoXOffset( boolean roundBorderAutoXOffset ) {
|
||||
this.roundBorderAutoXOffset = roundBorderAutoXOffset;
|
||||
}
|
||||
|
||||
protected Color deriveBackground( Color background ) {
|
||||
return background;
|
||||
}
|
||||
@@ -196,14 +230,17 @@ public class FlatArrowButton
|
||||
}
|
||||
|
||||
protected void paintArrow( Graphics2D g ) {
|
||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||
int x = 0;
|
||||
|
||||
// move arrow for round borders
|
||||
Container parent = getParent();
|
||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||
if( isRoundBorderAutoXOffset() ) {
|
||||
Container parent = getParent();
|
||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||
}
|
||||
|
||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, arrowWidth, xOffset, yOffset );
|
||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron,
|
||||
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,28 +23,33 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
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.JViewport;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicBorders;
|
||||
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
|
||||
@@ -60,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 ) {
|
||||
@@ -82,9 +113,11 @@ 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 ) ) {
|
||||
@@ -93,15 +126,16 @@ public class FlatBorder
|
||||
: 0;
|
||||
|
||||
if( focusWidth > 0 || innerWidth > 0 ) {
|
||||
g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) );
|
||||
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height,
|
||||
focusWidth, borderWidth + scale( innerWidth ), arc );
|
||||
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 );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
@@ -116,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:
|
||||
@@ -149,8 +194,7 @@ public class FlatBorder
|
||||
protected boolean isEnabled( Component c ) {
|
||||
if( c instanceof JScrollPane ) {
|
||||
// check whether view component is disabled
|
||||
JViewport viewport = ((JScrollPane)c).getViewport();
|
||||
Component view = (viewport != null) ? viewport.getView() : null;
|
||||
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
|
||||
if( view != null && !isEnabled( view ) )
|
||||
return false;
|
||||
}
|
||||
@@ -176,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
|
||||
@@ -227,8 +272,8 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,56 +20,72 @@ 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.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.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
||||
* @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 float buttonInnerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth );
|
||||
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" );
|
||||
|
||||
@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 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 ) {
|
||||
@@ -79,11 +95,40 @@ public class FlatButtonBorder
|
||||
!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
|
||||
@@ -114,7 +159,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;
|
||||
@@ -138,12 +183,7 @@ public class FlatButtonBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getInnerFocusWidth( Component c ) {
|
||||
return buttonInnerFocusWidth;
|
||||
}
|
||||
|
||||
@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;
|
||||
@@ -30,20 +31,37 @@ import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
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.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -65,20 +83,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 +111,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 +133,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 +226,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 +286,9 @@ public class FlatButtonUI
|
||||
protected void uninstallDefaults( AbstractButton b ) {
|
||||
super.uninstallDefaults( b );
|
||||
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( b );
|
||||
defaults_initialized = false;
|
||||
}
|
||||
@@ -225,9 +310,89 @@ public class FlatButtonUI
|
||||
b.revalidate();
|
||||
b.repaint();
|
||||
break;
|
||||
|
||||
case OUTLINE:
|
||||
b.repaint();
|
||||
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();
|
||||
b.repaint();
|
||||
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 +407,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) )
|
||||
@@ -265,11 +430,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;
|
||||
@@ -277,16 +442,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 && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_BORDERLESS );
|
||||
return c instanceof AbstractButton && BUTTON_TYPE_BORDERLESS.equals( getButtonTypeStr( (AbstractButton) c ) );
|
||||
}
|
||||
|
||||
static String getButtonTypeStr( AbstractButton c ) {
|
||||
// get from client property
|
||||
Object value = c.getClientProperty( BUTTON_TYPE );
|
||||
if( value instanceof String )
|
||||
return (String) value;
|
||||
|
||||
// get from styling property
|
||||
ButtonUI ui = c.getUI();
|
||||
return (ui instanceof FlatButtonUI) ? ((FlatButtonUI)ui).buttonType : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -315,28 +491,46 @@ 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( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
||||
if( paintShadow &&
|
||||
shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
||||
!isToolBarButton && !isBorderlessButton( c ) &&
|
||||
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) )
|
||||
{
|
||||
@@ -359,9 +553,62 @@ 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 )
|
||||
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
|
||||
@@ -384,6 +631,8 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
|
||||
if(foreground == null)
|
||||
foreground=Color.red;
|
||||
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
||||
|
||||
@@ -397,11 +646,14 @@ public class FlatButtonUI
|
||||
|
||||
// selected state
|
||||
if( ((AbstractButton)c).isSelected() ) {
|
||||
// in toolbar use same background colors for disabled and enabled because
|
||||
// in toolbar, if toolbarDisabledSelectedBackground is null,
|
||||
// use same background colors for disabled and enabled because
|
||||
// we assume that toolbar icon is shown disabled
|
||||
return buttonStateColor( c,
|
||||
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
||||
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
|
||||
toolBarButton
|
||||
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
|
||||
: disabledSelectedBackground,
|
||||
null,
|
||||
null,
|
||||
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
||||
@@ -428,6 +680,9 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
protected Color getBackgroundBase( JComponent c, boolean def ) {
|
||||
if( FlatUIUtils.isAWTPeer( c ) )
|
||||
return background;
|
||||
|
||||
// use component background if explicitly set
|
||||
Color bg = c.getBackground();
|
||||
if( isCustomBackground( bg ) )
|
||||
@@ -443,6 +698,9 @@ public class FlatButtonUI
|
||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||
{
|
||||
if( c == null )
|
||||
return enabledColor;
|
||||
|
||||
if( !c.isEnabled() )
|
||||
return disabledColor;
|
||||
|
||||
@@ -463,18 +721,49 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
protected Color getForeground( JComponent c ) {
|
||||
if( !c.isEnabled() )
|
||||
return disabledText;
|
||||
Color fg = c.getForeground();
|
||||
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
||||
|
||||
if( ((AbstractButton)c).isSelected() && !(isToolBarButton( c ) || isBorderlessButton( c )) )
|
||||
return selectedForeground;
|
||||
// selected state
|
||||
if( ((AbstractButton)c).isSelected() ) {
|
||||
return buttonStateColor( c,
|
||||
toolBarButton
|
||||
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : fg)
|
||||
: (isCustomForeground( fg ) ? fg : selectedForeground),
|
||||
toolBarButton
|
||||
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
|
||||
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
|
||||
null,
|
||||
null,
|
||||
toolBarButton ? toolbarPressedForeground : pressedForeground );
|
||||
}
|
||||
|
||||
// toolbar button
|
||||
if( toolBarButton ) {
|
||||
return buttonStateColor( c,
|
||||
fg,
|
||||
disabledText,
|
||||
null,
|
||||
toolbarHoverForeground,
|
||||
toolbarPressedForeground );
|
||||
}
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
return buttonStateColor( c,
|
||||
getForegroundBase( c, def ),
|
||||
disabledText,
|
||||
isCustomForeground( fg ) ? null : (def ? defaultFocusedForeground : focusedForeground),
|
||||
def ? defaultHoverForeground : hoverForeground,
|
||||
def ? defaultPressedForeground : pressedForeground );
|
||||
}
|
||||
|
||||
/** @since 2.3 */
|
||||
protected Color getForegroundBase( JComponent c, boolean def ) {
|
||||
// use component foreground if explicitly set
|
||||
Color fg = c.getForeground();
|
||||
if( isCustomForeground( fg ) )
|
||||
return fg;
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
return def ? defaultForeground : fg;
|
||||
}
|
||||
|
||||
@@ -491,24 +780,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
|
||||
@@ -526,5 +903,20 @@ public class FlatButtonUI
|
||||
super.propertyChange( e );
|
||||
FlatButtonUI.this.propertyChange( b, e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e ) {
|
||||
super.stateChanged( e );
|
||||
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,19 @@ 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.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 +60,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 +97,59 @@ public class FlatCheckBoxMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
protected FlatMenuItemRenderer createRenderer() {
|
||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
||||
}
|
||||
|
||||
/** @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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -21,16 +21,22 @@ 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.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}.
|
||||
@@ -38,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
|
||||
@@ -53,34 +59,53 @@ 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;
|
||||
protected Color focusedBackground;
|
||||
@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 );
|
||||
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
|
||||
@@ -90,8 +115,16 @@ 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 );
|
||||
}
|
||||
|
||||
@@ -113,30 +146,93 @@ public class FlatEditorPaneUI
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
propertyChange( getComponent(), e );
|
||||
protected Caret createCaret() {
|
||||
return new FlatCaret( null, false );
|
||||
}
|
||||
|
||||
static void propertyChange( JTextComponent c, PropertyChangeEvent e ) {
|
||||
@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();
|
||||
c.repaint();
|
||||
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
|
||||
@@ -153,11 +249,11 @@ public class FlatEditorPaneUI
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g ) {
|
||||
paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
|
||||
paintBackground( g, getComponent(), focusedBackground );
|
||||
}
|
||||
|
||||
static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
|
||||
g.setColor( FlatTextFieldUI.getBackground( c, isIntelliJTheme, focusedBackground ) );
|
||||
static void paintBackground( Graphics g, JTextComponent c, Color focusedBackground ) {
|
||||
g.setColor( FlatTextFieldUI.getBackground( c, focusedBackground ) );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,22 @@ 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.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.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
@@ -34,12 +45,17 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import javax.swing.filechooser.FileView;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.metal.MetalFileChooserUI;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.icons.FlatFileViewDirectoryIcon;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -133,12 +149,21 @@ 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;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatFileChooserUI( (JFileChooser) c );
|
||||
@@ -153,6 +178,25 @@ 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;
|
||||
fc.add( shortcutsPanel, BorderLayout.LINE_START );
|
||||
fc.addPropertyChangeListener( shortcutsPanel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallComponents( JFileChooser fc ) {
|
||||
super.uninstallComponents( fc );
|
||||
|
||||
if( shortcutsPanel != null ) {
|
||||
fc.removePropertyChangeListener( shortcutsPanel );
|
||||
shortcutsPanel = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void patchUI( JFileChooser fc ) {
|
||||
@@ -192,6 +236,27 @@ public class FlatFileChooserUI
|
||||
} catch( ArrayIndexOutOfBoundsException ex ) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// put north, center and south components into a new panel so that
|
||||
// the shortcuts panel (at west) gets full height
|
||||
LayoutManager layout = fc.getLayout();
|
||||
if( layout instanceof BorderLayout ) {
|
||||
BorderLayout borderLayout = (BorderLayout) layout;
|
||||
borderLayout.setHgap( 8 );
|
||||
|
||||
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
|
||||
Component lineEnd = borderLayout.getLayoutComponent( BorderLayout.LINE_END );
|
||||
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
|
||||
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
|
||||
if( north != null && lineEnd != null && center != null && south != null ) {
|
||||
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
|
||||
p.add( north, BorderLayout.NORTH );
|
||||
p.add( lineEnd, BorderLayout.LINE_END );
|
||||
p.add( center, BorderLayout.CENTER );
|
||||
p.add( south, BorderLayout.SOUTH );
|
||||
fc.add( p, BorderLayout.CENTER );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -250,9 +315,19 @@ public class FlatFileChooserUI
|
||||
return p;
|
||||
}
|
||||
|
||||
/** @since 2.3 */
|
||||
protected FlatShortcutsPanel createShortcutsPanel( JFileChooser fc ) {
|
||||
return new FlatShortcutsPanel( fc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return UIScale.scale( super.getPreferredSize( c ) );
|
||||
Dimension prefSize = super.getPreferredSize( c );
|
||||
Dimension minSize = getMinimumSize( c );
|
||||
int shortcutsPanelWidth = (shortcutsPanel != null) ? shortcutsPanel.getPreferredSize().width : 0;
|
||||
return new Dimension(
|
||||
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
|
||||
Math.max( prefSize.height, minSize.height ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -262,12 +337,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 -------------------------------------------------
|
||||
@@ -284,7 +370,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 )
|
||||
@@ -305,4 +395,253 @@ public class FlatFileChooserUI
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatShortcutsPanel -------------------------------------------
|
||||
|
||||
/** @since 2.3 */
|
||||
public static class FlatShortcutsPanel
|
||||
extends JToolBar
|
||||
implements PropertyChangeListener
|
||||
{
|
||||
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 );
|
||||
|
||||
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 = 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 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;
|
||||
}
|
||||
|
||||
protected JToggleButton createButton( String name, Icon icon ) {
|
||||
JToggleButton button = new JToggleButton( name, icon );
|
||||
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 File[] getChooserShortcutPanelFiles( FileSystemView fsv ) {
|
||||
try {
|
||||
if( SystemInfo.isJava_12_orLater ) {
|
||||
Method m = fsv.getClass().getMethod( "getChooserShortcutPanelFiles" );
|
||||
File[] files = (File[]) m.invoke( fsv );
|
||||
|
||||
// on macOS and Linux, files consists only of the user home directory
|
||||
if( files.length == 1 && files[0].equals( new File( System.getProperty( "user.home" ) ) ) )
|
||||
files = new File[0];
|
||||
|
||||
return files;
|
||||
} else if( SystemInfo.isWindows ) {
|
||||
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||
Method m = cls.getMethod( "get", String.class );
|
||||
return (File[]) m.invoke( null, "fileChooserShortcutPanelFolders" );
|
||||
}
|
||||
} catch( IllegalAccessException ex ) {
|
||||
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||
} catch( Exception ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
|
||||
// fallback
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case JFileChooser.DIRECTORY_CHANGED_PROPERTY:
|
||||
directoryChanged( fc.getCurrentDirectory() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- 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,12 +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
|
||||
*
|
||||
@@ -61,4 +59,10 @@ public class FlatFormattedTextFieldUI
|
||||
protected String getPropertyPrefix() {
|
||||
return "FormattedTextField";
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
String getStyleType() {
|
||||
return "FormattedTextField";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.BorderFactory;
|
||||
@@ -146,6 +147,19 @@ public class FlatInternalFrameTitlePane
|
||||
closeButton.setVisible( frame.isClosable() );
|
||||
}
|
||||
|
||||
Rectangle getFrameIconBounds() {
|
||||
Icon icon = titleLabel.getIcon();
|
||||
if( icon == null )
|
||||
return null;
|
||||
|
||||
int iconWidth = icon.getIconWidth();
|
||||
int iconHeight = icon.getIconHeight();
|
||||
boolean leftToRight = titleLabel.getComponentOrientation().isLeftToRight();
|
||||
int x = titleLabel.getX() + (leftToRight ? 0 : (titleLabel.getWidth() - iconWidth));
|
||||
int y = titleLabel.getY() + ((titleLabel.getHeight() - iconHeight) / 2);
|
||||
return new Rectangle( x, y, iconWidth, iconHeight );
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing because FlatLaf internal frames do not have system menus.
|
||||
*/
|
||||
@@ -199,6 +213,13 @@ public class FlatInternalFrameTitlePane
|
||||
case "componentOrientation":
|
||||
applyComponentOrientation( frame.getComponentOrientation() );
|
||||
break;
|
||||
|
||||
case "opaque":
|
||||
// Do not invoke super.propertyChange() here because it always
|
||||
// invokes repaint(), which would cause endless repainting.
|
||||
// The opaque flag is temporary changed in FlatUIUtils.hasOpaqueBeenExplicitlySet(),
|
||||
// invoked from FlatInternalFrameUI.update().
|
||||
return;
|
||||
}
|
||||
|
||||
super.propertyChange( e );
|
||||
|
||||
@@ -22,12 +22,22 @@ import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
|
||||
@@ -83,9 +93,13 @@ import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||
*/
|
||||
public class FlatInternalFrameUI
|
||||
extends BasicInternalFrameUI
|
||||
implements StyleableUI
|
||||
{
|
||||
protected FlatWindowResizer windowResizer;
|
||||
|
||||
private Map<String, Object> oldStyleValues;
|
||||
private AtomicBoolean borderShared;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatInternalFrameUI( (JInternalFrame) c );
|
||||
}
|
||||
@@ -101,6 +115,8 @@ public class FlatInternalFrameUI
|
||||
LookAndFeel.installProperty( frame, "opaque", false );
|
||||
|
||||
windowResizer = createWindowResizer();
|
||||
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,6 +127,9 @@ public class FlatInternalFrameUI
|
||||
windowResizer.uninstall();
|
||||
windowResizer = null;
|
||||
}
|
||||
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,15 +141,80 @@ public class FlatInternalFrameUI
|
||||
return new FlatWindowResizer.InternalFrameResizer( frame, this::getDesktopManager );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MouseInputAdapter createBorderListener( JInternalFrame w ) {
|
||||
return new FlatBorderListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
return FlatStylingSupport.createPropertyChangeListener( frame, this::installStyle,
|
||||
super.createPropertyChangeListener() );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
applyStyle( FlatStylingSupport.getResolvedStyle( frame, "InternalFrame" ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( Object style ) {
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
if( borderShared == null )
|
||||
borderShared = new AtomicBoolean( true );
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, frame, borderShared );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, frame.getBorder() );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, frame.getBorder(), key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
// The internal frame actually should be opaque and fill its background,
|
||||
// but it must be non-opaque to allow translucent resize handles (outside of visual bounds).
|
||||
// To avoid that parent may shine through internal frame (e.g. if menu bar is non-opaque),
|
||||
// fill background excluding insets (translucent resize handles),
|
||||
// but only if opaque was not set explicitly by application to false.
|
||||
// If applications has set internal frame opacity to false, do not fill background (for compatibility).
|
||||
if( !c.isOpaque() && !FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) ) {
|
||||
Insets insets = c.getInsets();
|
||||
|
||||
g.setColor( c.getBackground() );
|
||||
g.fillRect( insets.left, insets.top,
|
||||
c.getWidth() - insets.left - insets.right,
|
||||
c.getHeight() - insets.top - insets.bottom );
|
||||
}
|
||||
|
||||
super.update( g, c );
|
||||
}
|
||||
|
||||
//---- class FlatInternalFrameBorder --------------------------------------
|
||||
|
||||
public static class FlatInternalFrameBorder
|
||||
extends FlatEmptyBorder
|
||||
implements StyleableBorder
|
||||
{
|
||||
private final Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
||||
private final Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
||||
private final int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
||||
private final boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
||||
@Styleable protected Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
||||
@Styleable protected Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
||||
@Styleable protected int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
||||
@Styleable protected boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
||||
|
||||
private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder(
|
||||
UIManager.getColor( "InternalFrame.activeDropShadowColor" ),
|
||||
@@ -145,6 +229,53 @@ public class FlatInternalFrameUI
|
||||
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object applyStyleProperty( String key, Object value ) {
|
||||
switch( key ) {
|
||||
case "borderMargins": return applyStyleProperty( (Insets) value );
|
||||
|
||||
case "activeDropShadowColor": return activeDropShadowBorder.applyStyleProperty( "shadowColor", value );
|
||||
case "activeDropShadowInsets": return activeDropShadowBorder.applyStyleProperty( "shadowInsets", value );
|
||||
case "activeDropShadowOpacity": return activeDropShadowBorder.applyStyleProperty( "shadowOpacity", value );
|
||||
case "inactiveDropShadowColor": return inactiveDropShadowBorder.applyStyleProperty( "shadowColor", value );
|
||||
case "inactiveDropShadowInsets": return inactiveDropShadowBorder.applyStyleProperty( "shadowInsets", value );
|
||||
case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.applyStyleProperty( "shadowOpacity", value );
|
||||
}
|
||||
|
||||
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos() {
|
||||
Map<String, Class<?>> infos = new FlatStylingSupport.StyleableInfosMap<>();
|
||||
FlatStylingSupport.collectAnnotatedStyleableInfos( this, infos );
|
||||
infos.put( "borderMargins", Insets.class );
|
||||
infos.put( "activeDropShadowColor", Color.class );
|
||||
infos.put( "activeDropShadowInsets", Insets.class );
|
||||
infos.put( "activeDropShadowOpacity", float.class );
|
||||
infos.put( "inactiveDropShadowColor", Color.class );
|
||||
infos.put( "inactiveDropShadowInsets", Insets.class );
|
||||
infos.put( "inactiveDropShadowOpacity", float.class );
|
||||
return infos;
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( String key ) {
|
||||
switch( key ) {
|
||||
case "borderMargins": return getStyleableValue();
|
||||
|
||||
case "activeDropShadowColor": return activeDropShadowBorder.getStyleableValue( "shadowColor" );
|
||||
case "activeDropShadowInsets": return activeDropShadowBorder.getStyleableValue( "shadowInsets" );
|
||||
case "activeDropShadowOpacity": return activeDropShadowBorder.getStyleableValue( "shadowOpacity" );
|
||||
case "inactiveDropShadowColor": return inactiveDropShadowBorder.getStyleableValue( "shadowColor" );
|
||||
case "inactiveDropShadowInsets": return inactiveDropShadowBorder.getStyleableValue( "shadowInsets" );
|
||||
case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.getStyleableValue( "shadowOpacity" );
|
||||
}
|
||||
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
||||
@@ -195,4 +326,27 @@ public class FlatInternalFrameUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatBorderListener -------------------------------------------
|
||||
|
||||
/** @since 1.6 */
|
||||
protected class FlatBorderListener
|
||||
extends BorderListener
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e ) {
|
||||
if( e.getClickCount() == 2 && !frame.isIcon() &&
|
||||
e.getSource() instanceof FlatInternalFrameTitlePane )
|
||||
{
|
||||
Rectangle iconBounds = ((FlatInternalFrameTitlePane)e.getSource()).getFrameIconBounds();
|
||||
if( iconBounds != null && iconBounds.contains( e.getX(), e.getY() ) ) {
|
||||
if( frame.isClosable() )
|
||||
frame.doDefaultCloseAction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
super.mouseClicked( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
@@ -33,8 +35,12 @@ import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.plaf.basic.BasicLabelUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
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;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -54,13 +60,30 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*/
|
||||
public class FlatLabelUI
|
||||
extends BasicLabelUI
|
||||
implements StyleableUI
|
||||
{
|
||||
private Color disabledForeground;
|
||||
@Styleable protected Color disabledForeground;
|
||||
|
||||
private final boolean shared;
|
||||
private boolean defaults_initialized = false;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.createSharedUI( FlatLabelUI.class, FlatLabelUI::new );
|
||||
return FlatUIUtils.canUseSharedUI( c )
|
||||
? FlatUIUtils.createSharedUI( FlatLabelUI.class, () -> new FlatLabelUI( true ) )
|
||||
: new FlatLabelUI( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected FlatLabelUI( boolean shared ) {
|
||||
this.shared = shared;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installStyle( (JLabel) c );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,7 +100,9 @@ public class FlatLabelUI
|
||||
@Override
|
||||
protected void uninstallDefaults( JLabel c ) {
|
||||
super.uninstallDefaults( c );
|
||||
|
||||
defaults_initialized = false;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,10 +119,52 @@ public class FlatLabelUI
|
||||
if( name == "text" || name == "font" || name == "foreground" ) {
|
||||
JLabel label = (JLabel) e.getSource();
|
||||
updateHTMLRenderer( label, label.getText(), true );
|
||||
} else if( name.equals( FlatClientProperties.STYLE ) || name.equals( FlatClientProperties.STYLE_CLASS ) ) {
|
||||
JLabel label = (JLabel) e.getSource();
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( label ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
label.updateUI();
|
||||
} else
|
||||
installStyle( label );
|
||||
label.revalidate();
|
||||
label.repaint();
|
||||
} else
|
||||
super.propertyChange( e );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle( JLabel c ) {
|
||||
try {
|
||||
applyStyle( c, FlatStylingSupport.getResolvedStyle( c, "Label" ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( JLabel c, Object style ) {
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style,
|
||||
(key, value) -> applyStyleProperty( c, key, value ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( JLabel c, String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, c, 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether text contains HTML tags that use "absolute-size" keywords
|
||||
* (e.g. "x-large") for font-size in default style sheet
|
||||
@@ -113,7 +180,7 @@ public class FlatLabelUI
|
||||
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
||||
|
||||
String lowerText = text.toLowerCase();
|
||||
String lowerText = text.toLowerCase( Locale.ENGLISH );
|
||||
int headIndex;
|
||||
int styleIndex;
|
||||
|
||||
@@ -162,7 +229,7 @@ public class FlatLabelUI
|
||||
int tagBegin = i + 1;
|
||||
for( i += 2; i < textLength; i++ ) {
|
||||
if( !Character.isLetterOrDigit( text.charAt( i ) ) ) {
|
||||
String tag = text.substring( tagBegin, i ).toLowerCase();
|
||||
String tag = text.substring( tagBegin, i ).toLowerCase( Locale.ENGLISH );
|
||||
if( tagsUseFontSizeSet.contains( tag ) )
|
||||
return true;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
/**
|
||||
* Line border for various components.
|
||||
@@ -37,15 +38,18 @@ public class FlatLineBorder
|
||||
{
|
||||
private final Color lineColor;
|
||||
private final float lineThickness;
|
||||
/** @since 2 */ private final int arc;
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
||||
this( insets, lineColor, 1f );
|
||||
this( insets, lineColor, 1f, 0 );
|
||||
}
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness ) {
|
||||
/** @since 2 */
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness, int arc ) {
|
||||
super( insets );
|
||||
this.lineColor = lineColor;
|
||||
this.lineThickness = lineThickness;
|
||||
this.arc = arc;
|
||||
}
|
||||
|
||||
public Color getLineColor() {
|
||||
@@ -56,13 +60,21 @@ public class FlatLineBorder
|
||||
return lineThickness;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public int getArc() {
|
||||
return arc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( c instanceof JComponent && ((JComponent)c).getClientProperty( FlatPopupFactory.KEY_POPUP_USES_NATIVE_BORDER ) != null )
|
||||
return;
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
g2.setColor( lineColor );
|
||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0f, scale( lineThickness ), 0f );
|
||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||
0, 0, 0, scale( getLineThickness() ), scale( getArc() ), null, getLineColor(), null );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@@ -16,11 +16,15 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ListUI;
|
||||
|
||||
/**
|
||||
* Cell border for {@link javax.swing.DefaultListCellRenderer}
|
||||
@@ -33,12 +37,54 @@ import javax.swing.UIManager;
|
||||
public class FlatListCellBorder
|
||||
extends FlatLineBorder
|
||||
{
|
||||
final boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
/** @since 2 */ protected boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
|
||||
private Component c;
|
||||
|
||||
protected FlatListCellBorder() {
|
||||
super( UIManager.getInsets( "List.cellMargins" ), UIManager.getColor( "List.cellFocusColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
Insets m = getStyleFromListUI( c, ui -> ui.cellMargins );
|
||||
if( m != null )
|
||||
return scaleInsets( c, insets, m.top, m.left, m.bottom, m.right );
|
||||
|
||||
return super.getBorderInsets( c, insets );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getLineColor() {
|
||||
if( c != null ) {
|
||||
Color color = getStyleFromListUI( c, ui -> ui.cellFocusColor );
|
||||
if( color != null )
|
||||
return color;
|
||||
}
|
||||
return super.getLineColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
this.c = c;
|
||||
super.paintBorder( c, g, x, y, width, height );
|
||||
this.c = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this border is always shared for all lists,
|
||||
* get border specific style from FlatListUI.
|
||||
*/
|
||||
static <T> T getStyleFromListUI( Component c, Function<FlatListUI, T> f ) {
|
||||
JList<?> list = (JList<?>) SwingUtilities.getAncestorOfClass( JList.class, c );
|
||||
if( list != null ) {
|
||||
ListUI ui = list.getUI();
|
||||
if( ui instanceof FlatListUI )
|
||||
return f.apply( (FlatListUI) ui );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//---- class Default ------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -67,17 +113,19 @@ public class FlatListCellBorder
|
||||
|
||||
/**
|
||||
* Border for selected cell that uses margins and paints focus indicator border
|
||||
* if enabled (List.showCellFocusIndicator=true) and exactly one item is selected.
|
||||
* if enabled (List.showCellFocusIndicator=true) and multiple items are selected.
|
||||
*/
|
||||
public static class Selected
|
||||
extends FlatListCellBorder
|
||||
{
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Boolean b = getStyleFromListUI( c, ui -> ui.showCellFocusIndicator );
|
||||
boolean showCellFocusIndicator = (b != null) ? b : this.showCellFocusIndicator;
|
||||
if( !showCellFocusIndicator )
|
||||
return;
|
||||
|
||||
// paint focus indicator border only if exactly one item is selected
|
||||
// paint focus indicator border only if multiple items are selected
|
||||
JList<?> list = (JList<?>) SwingUtilities.getAncestorOfClass( JList.class, c );
|
||||
if( list != null && list.getMinSelectionIndex() == list.getMaxSelectionIndex() )
|
||||
return;
|
||||
|
||||
@@ -17,13 +17,34 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||
import javax.swing.plaf.basic.BasicListUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JList}.
|
||||
@@ -52,6 +73,8 @@ import javax.swing.plaf.basic.BasicListUI;
|
||||
*
|
||||
* @uiDefault List.selectionInactiveBackground Color
|
||||
* @uiDefault List.selectionInactiveForeground Color
|
||||
* @uiDefault List.selectionInsets Insets
|
||||
* @uiDefault List.selectionArc int
|
||||
*
|
||||
* <!-- FlatListCellBorder -->
|
||||
*
|
||||
@@ -63,16 +86,40 @@ import javax.swing.plaf.basic.BasicListUI;
|
||||
*/
|
||||
public class FlatListUI
|
||||
extends BasicListUI
|
||||
implements StyleableUI
|
||||
{
|
||||
protected Color selectionBackground;
|
||||
protected Color selectionForeground;
|
||||
protected Color selectionInactiveBackground;
|
||||
protected Color selectionInactiveForeground;
|
||||
@Styleable protected Color selectionBackground;
|
||||
@Styleable protected Color selectionForeground;
|
||||
@Styleable protected Color selectionInactiveBackground;
|
||||
@Styleable protected Color selectionInactiveForeground;
|
||||
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||
/** @since 3 */ @Styleable protected int selectionArc;
|
||||
|
||||
// for FlatListCellBorder
|
||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||
/** @since 2 */ @Styleable protected Color cellFocusColor;
|
||||
/** @since 2 */ @Styleable protected Boolean showCellFocusIndicator;
|
||||
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatListUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
if( FlatUIUtils.needsLightAWTPeer( c ) )
|
||||
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
|
||||
else
|
||||
installUIImpl( c );
|
||||
}
|
||||
|
||||
private void installUIImpl( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
@@ -81,6 +128,8 @@ public class FlatListUI
|
||||
selectionForeground = UIManager.getColor( "List.selectionForeground" );
|
||||
selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" );
|
||||
selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" );
|
||||
selectionInsets = UIManager.getInsets( "List.selectionInsets" );
|
||||
selectionArc = UIManager.getInt( "List.selectionArc" );
|
||||
|
||||
toggleSelectionColors();
|
||||
}
|
||||
@@ -93,6 +142,8 @@ public class FlatListUI
|
||||
selectionForeground = null;
|
||||
selectionInactiveBackground = null;
|
||||
selectionInactiveForeground = null;
|
||||
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,10 +167,108 @@ public class FlatListUI
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.COMPONENT_FOCUS_OWNER:
|
||||
toggleSelectionColors();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.STYLE:
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
installStyle();
|
||||
list.revalidate();
|
||||
list.repaint();
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListSelectionListener createListSelectionListener() {
|
||||
ListSelectionListener superListener = super.createListSelectionListener();
|
||||
return e -> {
|
||||
superListener.valueChanged( e );
|
||||
|
||||
// for united rounded selection, repaint parts of the rows/columns that adjoin to the changed rows/columns
|
||||
if( useUnitedRoundedSelection( true, true ) &&
|
||||
!list.isSelectionEmpty() &&
|
||||
(list.getMaxSelectionIndex() - list.getMinSelectionIndex()) >= 1 )
|
||||
{
|
||||
int size = list.getModel().getSize();
|
||||
int firstIndex = Math.min( Math.max( e.getFirstIndex(), 0 ), size - 1 );
|
||||
int lastIndex = Math.min( Math.max( e.getLastIndex(), 0 ), size - 1 );
|
||||
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
||||
if( r != null ) {
|
||||
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
||||
list.repaint( r.x - arc, r.y - arc, r.width + (arc * 2), r.height + (arc * 2) );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
applyStyle( FlatStylingSupport.getResolvedStyle( list, "List" ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( Object style ) {
|
||||
Color oldSelectionBackground = selectionBackground;
|
||||
Color oldSelectionForeground = selectionForeground;
|
||||
Color oldSelectionInactiveBackground = selectionInactiveBackground;
|
||||
Color oldSelectionInactiveForeground = selectionInactiveForeground;
|
||||
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||
|
||||
// update selection background
|
||||
if( selectionBackground != oldSelectionBackground ) {
|
||||
Color selBg = list.getSelectionBackground();
|
||||
if( selBg == oldSelectionBackground )
|
||||
list.setSelectionBackground( selectionBackground );
|
||||
else if( selBg == oldSelectionInactiveBackground )
|
||||
list.setSelectionBackground( selectionInactiveBackground );
|
||||
}
|
||||
|
||||
// update selection foreground
|
||||
if( selectionForeground != oldSelectionForeground ) {
|
||||
Color selFg = list.getSelectionForeground();
|
||||
if( selFg == oldSelectionForeground )
|
||||
list.setSelectionForeground( selectionForeground );
|
||||
else if( selFg == oldSelectionInactiveForeground )
|
||||
list.setSelectionForeground( selectionInactiveForeground );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, list, 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle selection colors from focused to inactive and vice versa.
|
||||
*
|
||||
* This is not a optimal solution but much easier than rewriting the whole paint methods.
|
||||
* This is not an optimal solution but much easier than rewriting the whole paint methods.
|
||||
*
|
||||
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||
* already used in applications. Then either the inactive colors are not used,
|
||||
@@ -141,4 +290,165 @@ public class FlatListUI
|
||||
list.setSelectionForeground( selectionInactiveForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( "rawtypes" )
|
||||
@Override
|
||||
protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRenderer cellRenderer,
|
||||
ListModel dataModel, ListSelectionModel selModel, int leadIndex )
|
||||
{
|
||||
boolean isSelected = selModel.isSelectedIndex( row );
|
||||
|
||||
// get renderer component
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
|
||||
dataModel.getElementAt( row ), row, isSelected,
|
||||
FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) );
|
||||
|
||||
//
|
||||
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
|
||||
int cx, cw;
|
||||
if( isFileList ) {
|
||||
// see BasicListUI.paintCell()
|
||||
cw = Math.min( rowBounds.width, rendererComponent.getPreferredSize().width + 4 );
|
||||
cx = list.getComponentOrientation().isLeftToRight()
|
||||
? rowBounds.x
|
||||
: rowBounds.x + (rowBounds.width - cw);
|
||||
} else {
|
||||
cx = rowBounds.x;
|
||||
cw = rowBounds.width;
|
||||
}
|
||||
|
||||
// rounded selection or selection insets
|
||||
if( isSelected &&
|
||||
!isFileList && // rounded selection is not supported for file list
|
||||
(rendererComponent instanceof DefaultListCellRenderer ||
|
||||
rendererComponent instanceof BasicComboBoxRenderer) &&
|
||||
(selectionArc > 0 ||
|
||||
(selectionInsets != null &&
|
||||
(selectionInsets.top != 0 || selectionInsets.left != 0 || selectionInsets.bottom != 0 || selectionInsets.right != 0))) )
|
||||
{
|
||||
// Because selection painting is done in the cell renderer, it would be
|
||||
// necessary to require a FlatLaf specific renderer to implement rounded selection.
|
||||
// Using a LaF specific renderer was avoided because often a custom renderer is
|
||||
// already used in applications. Then either the rounded selection is not used,
|
||||
// or the application has to be changed to extend a FlatLaf renderer.
|
||||
//
|
||||
// To solve this, a graphics proxy is used that paints rounded selection
|
||||
// if row is selected and the renderer wants to fill the background.
|
||||
class RoundedSelectionGraphics extends Graphics2DProxy {
|
||||
// used to avoid endless loop in case that paintCellSelection() invokes
|
||||
// g.fillRect() with full bounds (selectionInsets is 0,0,0,0)
|
||||
private boolean inPaintSelection;
|
||||
|
||||
RoundedSelectionGraphics( Graphics delegate ) {
|
||||
super( (Graphics2D) delegate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return new RoundedSelectionGraphics( super.create() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create( int x, int y, int width, int height ) {
|
||||
return new RoundedSelectionGraphics( super.create( x, y, width, height ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect( int x, int y, int width, int height ) {
|
||||
if( !inPaintSelection &&
|
||||
x == 0 && y == 0 && width == rowBounds.width && height == rowBounds.height &&
|
||||
this.getColor() == rendererComponent.getBackground() )
|
||||
{
|
||||
inPaintSelection = true;
|
||||
paintCellSelection( this, row, x, y, width, height );
|
||||
inPaintSelection = false;
|
||||
} else
|
||||
super.fillRect( x, y, width, height );
|
||||
}
|
||||
}
|
||||
g = new RoundedSelectionGraphics( g );
|
||||
}
|
||||
|
||||
// paint renderer
|
||||
rendererPane.paintComponent( g, rendererComponent, list, cx, rowBounds.y, cw, rowBounds.height, true );
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
||||
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||
|
||||
if( list.getLayoutOrientation() == JList.VERTICAL ) {
|
||||
// layout orientation: VERTICAL
|
||||
if( useUnitedRoundedSelection( true, false ) ) {
|
||||
if( row > 0 && list.isSelectedIndex( row - 1 ) )
|
||||
arcTopLeft = arcTopRight = 0;
|
||||
if( row < list.getModel().getSize() - 1 && list.isSelectedIndex( row + 1 ) )
|
||||
arcBottomLeft = arcBottomRight = 0;
|
||||
}
|
||||
} else {
|
||||
// layout orientation: VERTICAL_WRAP or HORIZONTAL_WRAP
|
||||
Rectangle r = null;
|
||||
if( useUnitedRoundedSelection( true, false ) ) {
|
||||
// vertical: check whether cells above or below are selected
|
||||
r = getCellBounds( list, row, row );
|
||||
|
||||
int topIndex = locationToIndex( list, new Point( r.x, r.y - 1 ) );
|
||||
int bottomIndex = locationToIndex( list, new Point( r.x, r.y + r.height ) );
|
||||
|
||||
if( topIndex >= 0 && topIndex != row && list.isSelectedIndex( topIndex ) )
|
||||
arcTopLeft = arcTopRight = 0;
|
||||
if( bottomIndex >= 0 && bottomIndex != row && list.isSelectedIndex( bottomIndex ) )
|
||||
arcBottomLeft = arcBottomRight = 0;
|
||||
}
|
||||
|
||||
if( useUnitedRoundedSelection( false, true ) ) {
|
||||
// horizontal: check whether cells left or right are selected
|
||||
if( r == null )
|
||||
r = getCellBounds( list, row, row );
|
||||
|
||||
int leftIndex = locationToIndex( list, new Point( r.x - 1, r.y ) );
|
||||
int rightIndex = locationToIndex( list, new Point( r.x + r.width, r.y ) );
|
||||
|
||||
// special handling for the case that last column contains fewer cells than the other columns
|
||||
boolean ltr = list.getComponentOrientation().isLeftToRight();
|
||||
if( !ltr && leftIndex >= 0 && leftIndex != row && leftIndex == locationToIndex( list, new Point( r.x - 1, r.y - 1 ) ) )
|
||||
leftIndex = -1;
|
||||
if( ltr && rightIndex >= 0 && rightIndex != row && rightIndex == locationToIndex( list, new Point( r.x + r.width, r.y - 1 ) ) )
|
||||
rightIndex = -1;
|
||||
|
||||
if( leftIndex >= 0 && leftIndex != row && list.isSelectedIndex( leftIndex ) )
|
||||
arcTopLeft = arcBottomLeft = 0;
|
||||
if( rightIndex >= 0 && rightIndex != row && list.isSelectedIndex( rightIndex ) )
|
||||
arcTopRight = arcBottomRight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
||||
UIScale.scale( selectionInsets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||
}
|
||||
|
||||
private boolean useUnitedRoundedSelection( boolean vertical, boolean horizontal ) {
|
||||
return selectionArc > 0 &&
|
||||
(selectionInsets == null ||
|
||||
(vertical && selectionInsets.top == 0 && selectionInsets.bottom == 0) ||
|
||||
(horizontal && selectionInsets.left == 0 && selectionInsets.right == 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints a cell selection at the given coordinates.
|
||||
* The selection color must be set on the graphics context.
|
||||
* <p>
|
||||
* This method is intended for use in custom cell renderers.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void paintCellSelection( JList<?> list, Graphics g, int row, int x, int y, int width, int height ) {
|
||||
if( !(list.getUI() instanceof FlatListUI) )
|
||||
return;
|
||||
|
||||
FlatListUI ui = (FlatListUI) list.getUI();
|
||||
ui.paintCellSelection( g, row, x, y, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import javax.swing.plaf.basic.BasicBorders;
|
||||
public class FlatMarginBorder
|
||||
extends BasicBorders.MarginBorder
|
||||
{
|
||||
private final int left, right, top, bottom;
|
||||
protected int left, right, top, bottom;
|
||||
|
||||
public FlatMarginBorder() {
|
||||
left = right = top = bottom = 0;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user