mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-09 16:25:10 +03:00
Compare commits
688 Commits
1.5
...
fonts/robo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
299bd67151 | ||
|
|
4d4bb3fd7f | ||
|
|
7fd64a1b73 | ||
|
|
e3e8765b91 | ||
|
|
435cf05f9f | ||
|
|
943dfe0619 | ||
|
|
be7114d3e6 | ||
|
|
713a01bfa9 | ||
|
|
ac291b688d | ||
|
|
84f7e244f2 | ||
|
|
4a8207f367 | ||
|
|
9cfd4d27e9 | ||
|
|
1b23cfd747 | ||
|
|
5801bf3bdf | ||
|
|
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
|
*.gif binary
|
||||||
*.jar binary
|
*.jar binary
|
||||||
*.lib binary
|
*.lib binary
|
||||||
|
*.otf binary
|
||||||
*.png binary
|
*.png binary
|
||||||
*.sketch binary
|
*.sketch binary
|
||||||
*.so binary
|
*.so binary
|
||||||
|
*.ttf binary
|
||||||
*.zip binary
|
*.zip binary
|
||||||
|
|||||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
custom: https://www.formdev.com/flatlaf/sponsor/
|
||||||
110
.github/workflows/ci.yml
vendored
110
.github/workflows/ci.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
@@ -8,9 +9,6 @@ on:
|
|||||||
- '*'
|
- '*'
|
||||||
tags:
|
tags:
|
||||||
- '[0-9]*'
|
- '[0-9]*'
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -19,50 +17,42 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# test against
|
# test against
|
||||||
# - Java 1.8 (minimum requirement)
|
# - Java 8 (minimum requirement)
|
||||||
# - Java 9 (first version with JPMS)
|
|
||||||
# - Java LTS versions (11, 17, ...)
|
# - Java LTS versions (11, 17, ...)
|
||||||
# - lastest Java version(s)
|
# - lastest Java version(s)
|
||||||
java:
|
java:
|
||||||
- 1.8
|
- 8
|
||||||
- 9
|
|
||||||
- 11 # LTS
|
- 11 # LTS
|
||||||
- 14
|
- 17 # LTS
|
||||||
- 15
|
toolchain: [""]
|
||||||
|
include:
|
||||||
|
- java: 17
|
||||||
|
toolchain: 19 # latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
|
if: matrix.java == '8'
|
||||||
|
|
||||||
- name: Setup Java ${{ matrix.java }}
|
- name: Setup Java ${{ matrix.java }}
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
|
distribution: adopt # Java 8 and 11 are pre-installed on ubuntu-latest
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew build
|
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: matrix.java == '11'
|
if: matrix.java == '11'
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-build-artifacts
|
name: FlatLaf-build-artifacts
|
||||||
path: |
|
path: |
|
||||||
flatlaf-*/build/libs
|
flatlaf-*/build/libs
|
||||||
|
flatlaf-*/flatlaf-*/build/libs
|
||||||
!**/*-javadoc.jar
|
!**/*-javadoc.jar
|
||||||
!**/*-sources.jar
|
!**/*-sources.jar
|
||||||
|
|
||||||
@@ -72,36 +62,36 @@ jobs:
|
|||||||
needs: build
|
needs: build
|
||||||
if: |
|
if: |
|
||||||
github.event_name == 'push' &&
|
github.event_name == 'push' &&
|
||||||
github.ref == 'refs/heads/main' &&
|
(github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) &&
|
||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
distribution: adopt # pre-installed on ubuntu-latest
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
- 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
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
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:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -112,28 +102,17 @@ jobs:
|
|||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
distribution: adopt # pre-installed on ubuntu-latest
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Release a new stable version to Maven Central
|
- name: Release a new stable version to Maven Central
|
||||||
run: ./gradlew publish :flatlaf-demo:build -Drelease=true
|
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
@@ -150,3 +129,14 @@ jobs:
|
|||||||
localDir: "flatlaf-demo/build/libs"
|
localDir: "flatlaf-demo/build/libs"
|
||||||
remoteDir: "."
|
remoteDir: "."
|
||||||
options: "--only-newer --no-recursion --verbose=1"
|
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"
|
||||||
|
|||||||
59
.github/workflows/fonts.yml
vendored
Normal file
59
.github/workflows/fonts.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
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: adopt # 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 ) )
|
||||||
58
.github/workflows/natives.yml
vendored
58
.github/workflows/natives.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
name: Native Libraries
|
name: Native Libraries
|
||||||
|
|
||||||
@@ -9,50 +10,41 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- '[0-9]*'
|
- '[0-9]*'
|
||||||
paths:
|
paths:
|
||||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
- 'flatlaf-natives/**'
|
||||||
- '.github/workflows/natives.yml'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
paths:
|
|
||||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
|
||||||
- '.github/workflows/natives.yml'
|
- '.github/workflows/natives.yml'
|
||||||
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Windows:
|
Natives:
|
||||||
runs-on: windows-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- windows
|
||||||
|
- ubuntu
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
|
|
||||||
- name: Setup Java 1.8
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 1.8
|
java-version: 11
|
||||||
|
distribution: adopt
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
!~/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew :flatlaf-natives-windows:build
|
# --no-daemon is necessary on Windows otherwise caching Gradle would fail with:
|
||||||
|
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
||||||
|
run: ./gradlew build-natives --no-daemon
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-natives-windows-build-artifacts
|
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||||
path: |
|
path: |
|
||||||
flatlaf-natives/flatlaf-natives-windows/build
|
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives
|
||||||
|
flatlaf-natives/flatlaf-natives-*/build
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,5 +9,7 @@ out/
|
|||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
|
*.xcuserstate
|
||||||
|
*.xcworkspacedata
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
489
CHANGELOG.md
489
CHANGELOG.md
@@ -1,13 +1,496 @@
|
|||||||
FlatLaf Change Log
|
FlatLaf Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
## 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
|
## 1.5
|
||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
|
|
||||||
- SwingX: Added search and clear icons to `JXSearchField`. (issue #359)
|
- SwingX: Added search and clear icons to `JXSearchField`. (issue #359)
|
||||||
|
|
||||||
|
|
||||||
#### Fixed bugs
|
#### Fixed bugs
|
||||||
|
|
||||||
- Button and TextComponent: Do not apply minimum width/height if margins are
|
- Button and TextComponent: Do not apply minimum width/height if margins are
|
||||||
@@ -36,8 +519,8 @@ FlatLaf Change Log
|
|||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
|
|
||||||
- TextField, FormattedTextField and PasswordField: Support adding extra padding.
|
- TextField, FormattedTextField and PasswordField: Support adding extra padding
|
||||||
(set client property `JTextField.padding` to `Insets`).
|
(set client property `JTextField.padding` to an `Insets`).
|
||||||
- PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI`
|
- PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI`
|
||||||
(instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier
|
(instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier
|
||||||
extensibility.
|
extensibility.
|
||||||
|
|||||||
103
README.md
103
README.md
@@ -11,9 +11,9 @@ scales on **HiDPI** displays and runs on Java 8 or newer.
|
|||||||
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
||||||
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||||
|
|
||||||

|

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

|

|
||||||
|
|
||||||
|
|
||||||
IntelliJ Platform Themes
|
IntelliJ Platform Themes
|
||||||
@@ -25,6 +25,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
|
Demo
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -74,6 +85,8 @@ Addons
|
|||||||
- [SwingX](flatlaf-swingx) - support for SwingX components
|
- [SwingX](flatlaf-swingx) - support for SwingX components
|
||||||
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
|
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
|
||||||
components
|
components
|
||||||
|
- [Fonts](flatlaf-fonts) - some font families bundled in easy-to-use and
|
||||||
|
redistributable JARs
|
||||||
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
@@ -99,10 +112,22 @@ For more information and documentation visit
|
|||||||
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
||||||
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
||||||
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
||||||
|
- [Components UI Properties](https://www.formdev.com/flatlaf/components/)
|
||||||
|
- [Typography](https://www.formdev.com/flatlaf/typography/)
|
||||||
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
||||||
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
||||||
|
|
||||||
|
|
||||||
|
Theme Editor
|
||||||
|
------------
|
||||||
|
|
||||||
|
The Theme Editor that supports editing FlatLaf theme properties files. See
|
||||||
|
[Theme Editor documentation](https://www.formdev.com/flatlaf/theme-editor/) for
|
||||||
|
details and downloads.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
Buzz
|
Buzz
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -114,40 +139,72 @@ Buzz
|
|||||||
Applications using FlatLaf
|
Applications using FlatLaf
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
- 
|
||||||
and much more
|
[JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||||
|
12 (**commercial**) - the award-winning all-in-one Java profiler
|
||||||
|
-  [JFormDesigner](https://www.formdev.com/) 8
|
||||||
|
(**commercial**) - Java/Swing GUI Designer
|
||||||
|
-  [Jeyla Studio](https://www.jeylastudio.com/) - Salon
|
||||||
|
Software
|
||||||
|
-  [Fanurio](https://www.fanuriotimetracking.com/) 3.3.2
|
||||||
|
(**commercial**) - time tracking and billing for freelancers and teams
|
||||||
|
-  [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)
|
||||||
|
3.6 - Digital logic design tool and simulator
|
||||||
|
-  [Cinecred](https://loadingbyte.com/cinecred/) - create
|
||||||
|
beautiful film credit sequences
|
||||||
|
-  [tinyMediaManager](https://www.tinymediamanager.org/)
|
||||||
|
v4 (**commercial**) - a media management tool
|
||||||
|
-  [Weasis](https://nroduit.github.io/) - medical DICOM
|
||||||
|
viewer used in healthcare by hospitals, health networks, etc
|
||||||
|
- 
|
||||||
|
[Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software)
|
||||||
|
7.3.0 - for plotters, especially the wall-hanging polargraph
|
||||||
|
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
||||||
|
visual query system for relational databases
|
||||||
|
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||||
|
OSHI, to view information about the system and hardware
|
||||||
|
- [Jailer](https://github.com/Wisser/Jailer) 11.2 - database subsetting and
|
||||||
|
relational data browsing tool
|
||||||
|
-  [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
|
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
||||||
- 
|
- 
|
||||||
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
||||||
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
||||||
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
||||||
(**commercial**) - the universal database tool for developers, analysts and
|
(**commercial**) - the universal database tool for developers, analysts and
|
||||||
DBAs
|
DBAs
|
||||||
-  [MagicPlot](https://magicplot.com/) 3.0
|
-  [MagicPlot](https://magicplot.com/) 3.0
|
||||||
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
||||||
- 
|
- 
|
||||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
||||||
(**commercial**) - Thermodynamics and Properties Software
|
(**commercial**) - Thermodynamics and Properties Software
|
||||||
- [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds most widely used web
|
-  [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds
|
||||||
app scanner
|
most widely used web app scanner
|
||||||
- 
|
- 
|
||||||
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
||||||
2020.11.2 (**commercial**) - the leading software for web security testing
|
2020.11.2 (**commercial**) - the leading software for web security testing
|
||||||
- 
|
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||||
[BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
|
||||||
FlatLaf themes to Burp Suite
|
FlatLaf themes to Burp Suite
|
||||||
- [JOSM](https://josm.openstreetmap.de/) - an extensible editor for
|
-  [JOSM](https://josm.openstreetmap.de/) - an extensible
|
||||||
[OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf JOSM plugin)
|
editor for [OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf
|
||||||
- [jAlbum](https://jalbum.net/) 21 (**commercial**) - creates photo album
|
JOSM plugin)
|
||||||
websites
|
-  [jAlbum](https://jalbum.net/) 21 (**commercial**) -
|
||||||
|
creates photo album websites
|
||||||
|
- [PDF Studio](https://www.qoppa.com/pdfstudio/) 2021 (**commercial**) - create,
|
||||||
|
review and edit PDF documents
|
||||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
||||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||||
checks your website
|
checks your website
|
||||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5 - a turn-based sci-fi board
|
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||||
game
|
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5+ - a sci-fi tabletop
|
||||||
|
BattleTech simulator suite handling battles, unit building, and campaigns
|
||||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||||
0.13.b024 - GUI builder for
|
0.13.b024 - GUI builder for
|
||||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
||||||
@@ -165,15 +222,15 @@ Applications using FlatLaf
|
|||||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||||
[AS4](https://mendelson-e-c.com/as4/) and
|
[AS4](https://mendelson-e-c.com/as4/) and
|
||||||
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
||||||
-  [IGMAS+](https://www.gfz-potsdam.de/igmas) -
|
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
||||||
Interactive Gravity and Magnetic Application System
|
Application System
|
||||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
||||||
computation environment for meteorological community
|
computation environment for meteorological community
|
||||||
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
||||||
systems development platform
|
systems development platform
|
||||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||||
encryption
|
encryption
|
||||||
- [Jes - Die Java-E<EFBFBD>R](https://www.jes-eur.de)
|
- [Jes - Die Java-EÜR](https://www.jes-eur.de)
|
||||||
- [Mapton](https://mapton.org/) 2.0
|
- [Mapton](https://mapton.org/) 2.0
|
||||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||||
application (based on NetBeans platform)
|
application (based on NetBeans platform)
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val releaseVersion = "1.5"
|
val releaseVersion = "3.0"
|
||||||
val developmentVersion = "1.6-SNAPSHOT"
|
val developmentVersion = "3.1-SNAPSHOT"
|
||||||
|
|
||||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
version = if( rootProject.hasProperty( "release" ) ) releaseVersion else developmentVersion
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
@@ -37,6 +37,9 @@ println( "----------------------------------------------------------------------
|
|||||||
println( "FlatLaf Version: ${version}" )
|
println( "FlatLaf Version: ${version}" )
|
||||||
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
||||||
println( "Java ${System.getProperty( "java.version" )}" )
|
println( "Java ${System.getProperty( "java.version" )}" )
|
||||||
|
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||||
|
if( !toolchainJavaVersion.isNullOrEmpty() )
|
||||||
|
println( "Java toolchain ${toolchainJavaVersion}" )
|
||||||
println()
|
println()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
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 {
|
dependencies {
|
||||||
add( "java9Compile", sourceSets.main.get().output )
|
add( "java9Implementation", sourceSets.main.get().output )
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|||||||
36
buildSrc/src/main/kotlin/flatlaf-jni-headers.gradle.kts
Normal file
36
buildSrc/src/main/kotlin/flatlaf-jni-headers.gradle.kts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class JniHeadersExtension {
|
||||||
|
var headers: List<String> = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val extension = project.extensions.create<JniHeadersExtension>( "flatlafJniHeaders" )
|
||||||
|
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
register<Copy>( "jni-headers" ) {
|
||||||
|
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
||||||
|
dependsOn( ":flatlaf-core:compileJava" )
|
||||||
|
|
||||||
|
from( project( ":flatlaf-core" ).buildDir.resolve( "generated/jni-headers" ) )
|
||||||
|
into( "src/main/headers" )
|
||||||
|
include( extension.headers )
|
||||||
|
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
||||||
|
"eol" to org.apache.tools.ant.filters.FixCrLfFilter.CrLf.newInstance( "lf" )
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,12 +61,8 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest.attributes( "Multi-Release" to "true" )
|
from( sourceSets["module-info"].output ) {
|
||||||
|
include( "module-info.class" )
|
||||||
into( "META-INF/versions/9" ) {
|
|
||||||
from( sourceSets["module-info"].output ) {
|
|
||||||
include( "module-info.class" )
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ publishing {
|
|||||||
|
|
||||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
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 {
|
credentials {
|
||||||
// get from gradle.properties
|
// get from gradle.properties
|
||||||
@@ -108,5 +108,5 @@ signing {
|
|||||||
|
|
||||||
// disable signing of snapshots
|
// disable signing of snapshots
|
||||||
tasks.withType<Sign>().configureEach {
|
tasks.withType<Sign>().configureEach {
|
||||||
onlyIf { java.lang.Boolean.getBoolean( "release" ) }
|
onlyIf { rootProject.hasProperty( "release" ) }
|
||||||
}
|
}
|
||||||
|
|||||||
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 ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,15 +16,21 @@
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
|
`flatlaf-toolchain`
|
||||||
`flatlaf-module-info`
|
`flatlaf-module-info`
|
||||||
`flatlaf-java9`
|
`flatlaf-java9`
|
||||||
`flatlaf-publish`
|
`flatlaf-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sigtest = configurations.create( "sigtest" )
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
|
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
|
||||||
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
|
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
|
||||||
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
|
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
|
||||||
|
|
||||||
|
// https://github.com/jtulach/netbeans-apitest
|
||||||
|
sigtest( "org.netbeans.tools:sigtest-maven-plugin:1.7" )
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -38,11 +44,6 @@ tasks {
|
|||||||
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
|
||||||
// build native libraries
|
|
||||||
dependsOn( ":flatlaf-natives-windows:assemble" )
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName.set( "flatlaf" )
|
||||||
|
|
||||||
@@ -59,9 +60,62 @@ tasks {
|
|||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName.set( "flatlaf" )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check {
|
||||||
|
dependsOn( "sigtestCheck" )
|
||||||
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
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" )
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1135
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
1135
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -126,6 +126,57 @@ public interface FlatClientProperties
|
|||||||
|
|
||||||
//---- JComponent ---------------------------------------------------------
|
//---- JComponent ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style of a component as String in CSS syntax ("key1: value1; key2: value2; ...")
|
||||||
|
* or as {@link java.util.Map}<String, Object> with binary values.
|
||||||
|
* <p>
|
||||||
|
* The keys are the same as used in UI defaults, but without component type prefix.
|
||||||
|
* E.g. for UI default {@code Slider.thumbSize} use key {@code thumbSize}.
|
||||||
|
* <p>
|
||||||
|
* The syntax of the CSS values is the same as used in FlatLaf properties files
|
||||||
|
* (<a href="https://www.formdev.com/flatlaf/properties-files/">https://www.formdev.com/flatlaf/properties-files/</a>),
|
||||||
|
* but some features are not supported (e.g. variables).
|
||||||
|
* When using a map, the values are not parsed from a string. They must be binary.
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String} or {@link java.util.Map}<String, Object><br>
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String STYLE = "FlatLaf.style";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style class(es) of a component as String (single class or multiple classes separated by space characters)
|
||||||
|
* or as {@code String[]} or {@link java.util.List}<String> (multiple classes).
|
||||||
|
* <p>
|
||||||
|
* The style rules must be defined in UI defaults either as strings (in CSS syntax)
|
||||||
|
* or as {@link java.util.Map}<String, Object> (with binary values).
|
||||||
|
* The key must be in syntax: {@code [style]type.styleClass}, where the type is optional.
|
||||||
|
* E.g. in FlatLaf properties file:
|
||||||
|
* <pre>{@code
|
||||||
|
* [style]Button.primary = borderColor: #08f; background: #08f; foreground: #fff
|
||||||
|
* [style].secondary = borderColor: #0f8; background: #0f8
|
||||||
|
* }</pre>
|
||||||
|
* or in Java code:
|
||||||
|
* <pre>{@code
|
||||||
|
* UIManager.put( "[style]Button.primary", "borderColor: #08f; background: #08f; foreground: #fff" );
|
||||||
|
* UIManager.put( "[style].secondary", "borderColor: #0f8; background: #0f8" );
|
||||||
|
* }</pre>
|
||||||
|
* The rule "Button.primary" can be applied to buttons only.
|
||||||
|
* The rule ".secondary" can be applied to any component.
|
||||||
|
* <p>
|
||||||
|
* To have similar behavior as in CSS, first the rule without type is applied,
|
||||||
|
* then the rule with type.
|
||||||
|
* E.g. setting style class to "foo" on a {@code JButton} uses rules
|
||||||
|
* from UI default keys "[style].foo" and "[style]Button.foo".
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}, {@code String[]} or {@link java.util.List}<String><br>
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String STYLE_CLASS = "FlatLaf.styleClass";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies minimum width of a component.
|
* Specifies minimum width of a component.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -202,6 +253,19 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
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 --------------------------------------------------------------
|
//---- Popup --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,6 +344,80 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
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 "iconfify" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "iconfify" 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).
|
* Background color of window title bar (requires enabled window decorations).
|
||||||
* <p>
|
* <p>
|
||||||
@@ -322,8 +460,71 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
||||||
|
|
||||||
|
//---- JSplitPane ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies what side of the spilt pane is allowed to expand
|
||||||
|
* via one-touch expanding arrow buttons.
|
||||||
|
* Requires that one-touch expanding is enabled with
|
||||||
|
* {@link javax.swing.JSplitPane#setOneTouchExpandable(boolean)}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JSplitPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_LEFT} or
|
||||||
|
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_RIGHT}
|
||||||
|
*
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow expanding only left/top side of the split pane.
|
||||||
|
*
|
||||||
|
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow expanding only right/bottom side of the split pane.
|
||||||
|
*
|
||||||
|
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right";
|
||||||
|
|
||||||
//---- JTabbedPane --------------------------------------------------------
|
//---- JTabbedPane --------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies type of the selected tab.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #TABBED_PANE_TAB_TYPE_UNDERLINED} or
|
||||||
|
* {@link #TABBED_PANE_TAB_TYPE_CARD}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint the selected tab underlined.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_TYPE
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint the selected tab as card.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_TYPE
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_TYPE_CARD = "card";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether separators are shown between tabs.
|
* Specifies whether separators are shown between tabs.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -665,9 +866,9 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the leading edge of the tabs area.
|
* Specifies a component that will be placed at the leading edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
* For top and bottom tab placement, the layed out component size will be
|
* For top and bottom tab placement, the laid out component size will be
|
||||||
* the preferred component width and the tab area height.<br>
|
* the preferred component width and the tab area height.<br>
|
||||||
* For left and right tab placement, the layed out component size will be
|
* For left and right tab placement, the laid out component size will be
|
||||||
* the tab area width and the preferred component height.
|
* the tab area width and the preferred component height.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
@@ -678,9 +879,9 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
* For top and bottom tab placement, the layed out component size will be
|
* For top and bottom tab placement, the laid out component size will be
|
||||||
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
||||||
* For left and right tab placement, the layed out component size will be
|
* For left and right tab placement, the laid out component size will be
|
||||||
* the tab area width and the available vertical space (minimum is preferred component height).
|
* the tab area width and the available vertical space (minimum is preferred component height).
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
@@ -745,10 +946,137 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TEXT_FIELD_PADDING = "JTextField.padding";
|
String TEXT_FIELD_PADDING = "JTextField.padding";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an icon that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.Icon}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_LEADING_ICON = "JTextField.leadingIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an icon that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.Icon}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #OUTLINE}).
|
||||||
|
* <p>
|
||||||
|
* The component is prepared in the following way:
|
||||||
|
* <ul>
|
||||||
|
* <li>Component client property {@link #STYLE_CLASS} is set to {@code inTextField}.
|
||||||
|
* <li>If component is a button or toggle button, client property {@link #BUTTON_TYPE}
|
||||||
|
* is set to {@link #BUTTON_TYPE_TOOLBAR_BUTTON}
|
||||||
|
* and button cursor is set to default cursor (if not set).
|
||||||
|
* <li>If component is a toolbar, client property {@link #STYLE_CLASS}
|
||||||
|
* is set to {@code inTextField} on all toolbar children
|
||||||
|
* and toolbar cursor is set to default cursor (if not set).
|
||||||
|
* </ul>
|
||||||
|
* Because text fields use the text cursor by default and the cursor is inherited by child components,
|
||||||
|
* it may be necessary to explicitly set component cursor if you e.g. need the default arrow cursor.
|
||||||
|
* E.g. {@code comp.setCursor( Cursor.getDefaultCursor() )}.
|
||||||
|
* <p>
|
||||||
|
* Styling is used to modify insets/margins and appearance of buttons and toolbars
|
||||||
|
* so that they fit nicely into the text field and do not increase text field height.
|
||||||
|
* See styles {@code [style]Button.inTextField} and {@code [style]ToolBar.inTextField}
|
||||||
|
* in {@code Flat[Light|Dark]Laf.properties}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* See {@link #TEXT_FIELD_LEADING_COMPONENT} for details.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||||
|
* if the text field is not empty, editable and enabled. Default is {@code false}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the callback that is invoked when a "clear" (or "cancel") button is clicked.
|
||||||
|
* If a callback is specified than it is responsible for clearing the text field.
|
||||||
|
* Without callback, the text field clears itself.
|
||||||
|
* <p>
|
||||||
|
* Either use a {@link java.lang.Runnable}:
|
||||||
|
* <pre>{@code
|
||||||
|
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||||
|
* (Runnable) () -> {
|
||||||
|
* // clear field here or cancel search
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* Or use a {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||||
|
* that receives the text field as parameter:
|
||||||
|
* <pre>{@code
|
||||||
|
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||||
|
* (Consumer<JTextComponent>) textField -> {
|
||||||
|
* // clear field here or cancel search
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Runnable}
|
||||||
|
* or {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||||
|
*
|
||||||
|
* @see #TEXT_FIELD_SHOW_CLEAR_BUTTON
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback";
|
||||||
|
|
||||||
//---- JToggleButton ------------------------------------------------------
|
//---- JToggleButton ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
* Placement of underline if toggle button type is {@link #BUTTON_TYPE_TAB}
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||||
|
* <strong>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>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||||
@@ -813,8 +1141,7 @@ public interface FlatClientProperties
|
|||||||
* If the client property is not set, or not a {@link Boolean}, defaultValue is returned.
|
* If the client property is not set, or not a {@link Boolean}, defaultValue is returned.
|
||||||
*/
|
*/
|
||||||
static Boolean clientPropertyBooleanStrict( JComponent c, String key, Boolean defaultValue ) {
|
static Boolean clientPropertyBooleanStrict( JComponent c, String key, Boolean defaultValue ) {
|
||||||
Object value = c.getClientProperty( key );
|
return clientProperty( c, key, defaultValue, Boolean.class );
|
||||||
return (value instanceof Boolean) ? (Boolean) value : defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -831,7 +1158,18 @@ public interface FlatClientProperties
|
|||||||
* If the client property is not set, or not a color, defaultValue is returned.
|
* If the client property is not set, or not a color, defaultValue is returned.
|
||||||
*/
|
*/
|
||||||
static Color clientPropertyColor( JComponent c, String key, Color defaultValue ) {
|
static Color clientPropertyColor( JComponent c, String key, Color defaultValue ) {
|
||||||
|
return clientProperty( c, key, defaultValue, Color.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the specified client property if it is an instance of
|
||||||
|
* the specified type. Otherwise, defaultValue is returned.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
static <T> T clientProperty( JComponent c, String key, T defaultValue, Class<T> type ) {
|
||||||
Object value = c.getClientProperty( key );
|
Object value = c.getClientProperty( key );
|
||||||
return (value instanceof Color) ? (Color) value : defaultValue;
|
return type.isInstance( value ) ? (T) value : defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class FlatDarculaLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatDarculaLaf() );
|
return setup( new FlatDarculaLaf() );
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public class FlatDarkLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatDarkLaf() );
|
return setup( new FlatDarkLaf() );
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import javax.swing.UIDefaults;
|
|||||||
* Allows loading of additional .properties files from addon JARs.
|
* Allows loading of additional .properties files from addon JARs.
|
||||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||||
* <p>
|
* <p>
|
||||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
* If you extend this class in an addon JAR, you also have to add a text file named
|
||||||
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
||||||
* to the addon JAR. The file must contain a single line with the class name.
|
* to the addon JAR. The file must contain a single line with the class name.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -61,7 +61,7 @@ public abstract class FlatDefaultsAddon
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the priority used to sort addon loading.
|
* Returns the priority used to sort addon loading.
|
||||||
* The order is only important if you want overwrite UI defaults of other addons.
|
* The order is only important if you want to overwrite UI defaults of other addons.
|
||||||
* Lower numbers mean higher priority.
|
* Lower numbers mean higher priority.
|
||||||
* Returns 10000 by default.
|
* Returns 10000 by default.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf;
|
|||||||
/**
|
/**
|
||||||
* Default color palette for action icons and object icons.
|
* Default color palette for action icons and object icons.
|
||||||
* <p>
|
* <p>
|
||||||
* The idea is to use only this well defined set of colors in SVG icons and
|
* The idea is to use only this well-defined set of colors in SVG icons, and
|
||||||
* then they are replaced at runtime to dark variants or to other theme colors.
|
* then they are replaced at runtime to dark variants or to other theme colors.
|
||||||
* Then a single SVG icon (light variant) can be used for dark themes too.
|
* Then a single SVG icon (light variant) can be used for dark themes too.
|
||||||
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
||||||
@@ -35,7 +35,7 @@ package com.formdev.flatlaf;
|
|||||||
* <p>
|
* <p>
|
||||||
* You may use these colors also in your application (outside of SVG icons), but do
|
* You may use these colors also in your application (outside of SVG icons), but do
|
||||||
* not use the RGB values defined in this enum.<br>
|
* not use the RGB values defined in this enum.<br>
|
||||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
* Instead, use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ class FlatInputMaps
|
|||||||
//---- class LazyInputMapEx -----------------------------------------------
|
//---- class LazyInputMapEx -----------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazily creates a input map.
|
* Lazily creates an input map.
|
||||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||||
*/
|
*/
|
||||||
private static class LazyInputMapEx
|
private static class LazyInputMapEx
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class FlatIntelliJLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatIntelliJLaf() );
|
return setup( new FlatIntelliJLaf() );
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,8 @@ public class FlatLightLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatLightLaf() );
|
return setup( new FlatLightLaf() );
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
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",
|
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
||||||
* which has the same syntax as this one.
|
* which has the same syntax as this one.
|
||||||
* <p>
|
* <p>
|
||||||
* Since FlatLaf 1.1.2: Scale factors less then 100% are allowed.
|
* Since FlatLaf 1.1.2: Scale factors less than 100% are allowed.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
||||||
*/
|
*/
|
||||||
@@ -81,7 +82,7 @@ public interface FlatSystemProperties
|
|||||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||||
* UI default {@code TitlePane.useWindowDecorations}.
|
* UI default {@code TitlePane.useWindowDecorations}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Window 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> none
|
* <strong>Default</strong> none
|
||||||
@@ -92,16 +93,16 @@ public interface FlatSystemProperties
|
|||||||
* Specifies whether JetBrains Runtime custom window decorations should be used
|
* Specifies whether JetBrains Runtime custom window decorations should be used
|
||||||
* when creating {@code JFrame} or {@code JDialog}.
|
* when creating {@code JFrame} or {@code JDialog}.
|
||||||
* Requires that the application runs in a
|
* Requires that the application runs in a
|
||||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
|
* <a href="https://github.com/JetBrains/JetBrainsRuntime/wiki">JetBrains Runtime</a>
|
||||||
* (based on OpenJDK).
|
* (based on OpenJDK).
|
||||||
* <p>
|
* <p>
|
||||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||||
* Then FlatLaf native window decorations are used.
|
* Then FlatLaf native window decorations are used.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Window 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> {@code true}
|
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
||||||
*/
|
*/
|
||||||
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ public interface FlatSystemProperties
|
|||||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Window 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> none
|
* <strong>Default</strong> none
|
||||||
@@ -139,6 +140,39 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether FlatLaf updates the UI when the system font changes.
|
||||||
|
* If {@code true}, {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)}
|
||||||
|
* gets invoked for all windows if the system font has changed.
|
||||||
|
* This is the similar to when switching to another look and feel (theme).
|
||||||
|
* Applications that do not work correctly when switching look and feel,
|
||||||
|
* should disable this option to avoid corrupted UI.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies 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 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
|
* Checks whether a system property is set and returns {@code true} if its value
|
||||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.formdev.flatlaf.json.ParseException;
|
|||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
||||||
@@ -72,6 +73,8 @@ public class IntelliJTheme
|
|||||||
*
|
*
|
||||||
* The input stream is automatically closed.
|
* The input stream is automatically closed.
|
||||||
* Using a buffered input stream is not necessary.
|
* Using a buffered input stream is not necessary.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup( InputStream in ) {
|
public static boolean setup( InputStream in ) {
|
||||||
try {
|
try {
|
||||||
@@ -162,8 +165,11 @@ public class IntelliJTheme
|
|||||||
applyCheckBoxColors( defaults );
|
applyCheckBoxColors( defaults );
|
||||||
|
|
||||||
// copy values
|
// copy values
|
||||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() )
|
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
||||||
defaults.put( e.getKey(), defaults.get( e.getValue() ) );
|
Object value = defaults.get( e.getValue() );
|
||||||
|
if( value != null )
|
||||||
|
defaults.put( e.getKey(), value );
|
||||||
|
}
|
||||||
|
|
||||||
// IDEA does not paint button background if disabled, but FlatLaf does
|
// IDEA does not paint button background if disabled, but FlatLaf does
|
||||||
Object panelBackground = defaults.get( "Panel.background" );
|
Object panelBackground = defaults.get( "Panel.background" );
|
||||||
@@ -175,7 +181,7 @@ public class IntelliJTheme
|
|||||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||||
defaults.put( "HelpButton.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 helpButtonBackground = defaults.get( "Button.startBackground" );
|
||||||
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
||||||
if( helpButtonBackground == null )
|
if( helpButtonBackground == null )
|
||||||
@@ -242,14 +248,26 @@ public class IntelliJTheme
|
|||||||
defaults.put( "Tree.rowHeight", 22 );
|
defaults.put( "Tree.rowHeight", 22 );
|
||||||
|
|
||||||
// apply theme specific UI defaults at the end to allow overwriting
|
// 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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||||
// search for theme specific UI defaults keys
|
// search for theme specific UI defaults keys
|
||||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||||
for( Object key : defaults.keySet() ) {
|
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 );
|
themeSpecificKeys.add( (String) key );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +302,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
ColorUIResource color = UIDefaultsLoader.parseColor( value );
|
ColorUIResource color = parseColor( value );
|
||||||
if( color != null ) {
|
if( color != null ) {
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
namedColors.put( key, color );
|
namedColors.put( key, color );
|
||||||
@@ -299,8 +317,19 @@ public class IntelliJTheme
|
|||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
||||||
if( value instanceof Map ) {
|
if( value instanceof Map ) {
|
||||||
for( Map.Entry<String, Object> e : ((Map<String, Object>)value).entrySet() )
|
Map<String, Object> map = (Map<String, Object>)value;
|
||||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
|
||||||
|
String osKey = SystemInfo.isWindows ? "os.windows"
|
||||||
|
: SystemInfo.isMacOS ? "os.mac"
|
||||||
|
: SystemInfo.isLinux ? "os.linux" : null;
|
||||||
|
if( osKey != null && map.containsKey( osKey ) )
|
||||||
|
apply( key, map.get( osKey ), 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 {
|
} else {
|
||||||
if( "".equals( value ) )
|
if( "".equals( value ) )
|
||||||
return; // ignore empty value
|
return; // ignore empty value
|
||||||
@@ -338,7 +367,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
try {
|
try {
|
||||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr );
|
uiValue = UIDefaultsLoader.parseValue( key, valueStr, null );
|
||||||
} catch( RuntimeException ex ) {
|
} catch( RuntimeException ex ) {
|
||||||
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
||||||
return; // ignore invalid value
|
return; // ignore invalid value
|
||||||
@@ -419,7 +448,15 @@ public class IntelliJTheme
|
|||||||
ColorUIResource color = namedColors.get( value );
|
ColorUIResource color = namedColors.get( value );
|
||||||
|
|
||||||
// parse color
|
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -504,18 +541,18 @@ public class IntelliJTheme
|
|||||||
// for filled checkbox/radiobutton used in light themes
|
// for filled checkbox/radiobutton used in light themes
|
||||||
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
||||||
defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
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 ) {
|
if( dark ) {
|
||||||
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
||||||
// radioFocused.svg and radioSelectedFocused.svg
|
// radioFocused.svg and radioSelectedFocused.svg
|
||||||
// use opacity=".65" for the border
|
// use opacity=".65" for the border
|
||||||
// --> add alpha to focused border colors
|
// --> add alpha to focused border colors
|
||||||
String[] focusedBorderColorKeys = new String[] {
|
String[] focusedBorderColorKeys = {
|
||||||
"CheckBox.icon.focusedBorderColor",
|
"CheckBox.icon.focusedBorderColor",
|
||||||
"CheckBox.icon.selectedFocusedBorderColor",
|
"CheckBox.icon.focusedSelectedBorderColor",
|
||||||
"CheckBox.icon[filled].focusedBorderColor",
|
"CheckBox.icon[filled].focusedBorderColor",
|
||||||
"CheckBox.icon[filled].selectedFocusedBorderColor",
|
"CheckBox.icon[filled].focusedSelectedBorderColor",
|
||||||
};
|
};
|
||||||
for( String key : focusedBorderColorKeys ) {
|
for( String key : focusedBorderColorKeys ) {
|
||||||
Color color = defaults.getColor( key );
|
Color color = defaults.getColor( key );
|
||||||
@@ -534,12 +571,12 @@ public class IntelliJTheme
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Rename UI default keys (key --> value). */
|
/** Rename UI default keys (key --> value). */
|
||||||
private static Map<String, String> uiKeyMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
||||||
/** Copy UI default keys (value --> key). */
|
/** Copy UI default keys (value --> key). */
|
||||||
private static Map<String, String> uiKeyCopying = new HashMap<>();
|
private static final Map<String, String> uiKeyCopying = new HashMap<>();
|
||||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// ComboBox
|
// ComboBox
|
||||||
@@ -549,6 +586,8 @@ public class IntelliJTheme
|
|||||||
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
||||||
|
uiKeyCopying.put( "ComboBox.buttonSeparatorColor", "Component.borderColor" );
|
||||||
|
uiKeyCopying.put( "ComboBox.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
||||||
|
|
||||||
// Component
|
// Component
|
||||||
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
|
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
|
||||||
@@ -594,6 +633,15 @@ public class IntelliJTheme
|
|||||||
uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" );
|
uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" );
|
||||||
uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" );
|
uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" );
|
||||||
|
|
||||||
|
// Spinner
|
||||||
|
uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" );
|
||||||
|
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
||||||
|
|
||||||
|
// TabbedPane
|
||||||
|
uiKeyCopying.put( "TabbedPane.selectedBackground", "DefaultTabs.underlinedTabBackground" );
|
||||||
|
uiKeyCopying.put( "TabbedPane.selectedForeground", "DefaultTabs.underlinedTabForeground" );
|
||||||
|
uiKeyCopying.put( "TabbedPane.inactiveUnderlineColor", "DefaultTabs.inactiveUnderlineColor" );
|
||||||
|
|
||||||
// TitlePane
|
// TitlePane
|
||||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
||||||
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
||||||
@@ -618,7 +666,7 @@ public class IntelliJTheme
|
|||||||
checkboxKeyMapping.put( "Checkbox.Background.Selected", "CheckBox.icon.selectedBackground" );
|
checkboxKeyMapping.put( "Checkbox.Background.Selected", "CheckBox.icon.selectedBackground" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Border.Selected", "CheckBox.icon.selectedBorderColor" );
|
checkboxKeyMapping.put( "Checkbox.Border.Selected", "CheckBox.icon.selectedBorderColor" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Foreground.Selected", "CheckBox.icon.checkmarkColor" );
|
checkboxKeyMapping.put( "Checkbox.Foreground.Selected", "CheckBox.icon.checkmarkColor" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.selectedFocusedBorderColor" );
|
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.focusedSelectedBorderColor" );
|
||||||
|
|
||||||
checkboxDuplicateColors.put( "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
checkboxDuplicateColors.put( "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
||||||
checkboxDuplicateColors.put( "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
checkboxDuplicateColors.put( "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
import java.awt.GraphicsConfiguration;
|
import java.awt.GraphicsConfiguration;
|
||||||
import java.awt.GraphicsEnvironment;
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
@@ -28,7 +29,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import javax.swing.text.StyleContext;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
@@ -121,14 +122,25 @@ class LinuxFontPolicy
|
|||||||
for(;;) {
|
for(;;) {
|
||||||
Font font = createFont( family, style, size, dsize );
|
Font font = createFont( family, style, size, dsize );
|
||||||
|
|
||||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
if( Font.DIALOG.equals( family ) )
|
||||||
if( !"Dialog".equals( font.getFamily() ) || "Dialog".equals( family ) )
|
|
||||||
return font;
|
return font;
|
||||||
|
|
||||||
|
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||||
|
if( !Font.DIALOG.equals( font.getFamily() ) ) {
|
||||||
|
// check for font problems
|
||||||
|
// - font height much larger than expected (e.g. font Inter; Oracle Java 8)
|
||||||
|
// - character width is zero (e.g. font Cantarell; Fedora; Oracle Java 8)
|
||||||
|
FontMetrics fm = StyleContext.getDefaultStyleContext().getFontMetrics( font );
|
||||||
|
if( fm.getHeight() > size * 2 || fm.stringWidth( "a" ) == 0 )
|
||||||
|
return createFont( Font.DIALOG, style, size, dsize );
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
// find last word in family
|
// find last word in family
|
||||||
int index = family.lastIndexOf( ' ' );
|
int index = family.lastIndexOf( ' ' );
|
||||||
if( index < 0 )
|
if( index < 0 )
|
||||||
return createFont( "Dialog", style, size, dsize );
|
return createFont( Font.DIALOG, style, size, dsize );
|
||||||
|
|
||||||
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
||||||
String lastWord = family.substring( index + 1 ).toLowerCase();
|
String lastWord = family.substring( index + 1 ).toLowerCase();
|
||||||
@@ -158,7 +170,7 @@ class LinuxFontPolicy
|
|||||||
|
|
||||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||||
if( value instanceof Integer ) {
|
if( value instanceof Integer ) {
|
||||||
int dpi = ((Integer)value).intValue() / 1024;
|
int dpi = (Integer) value / 1024;
|
||||||
if( dpi == -1 )
|
if( dpi == -1 )
|
||||||
dpi = 96;
|
dpi = 96;
|
||||||
if( dpi < 50 )
|
if( dpi < 50 )
|
||||||
@@ -185,7 +197,7 @@ class LinuxFontPolicy
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default font for KDE for KDE configuration files.
|
* Gets the default font for KDE from KDE configuration files.
|
||||||
*
|
*
|
||||||
* The Swing fonts are not updated when the user changes system font size
|
* The Swing fonts are not updated when the user changes system font size
|
||||||
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
||||||
@@ -266,7 +278,7 @@ class LinuxFontPolicy
|
|||||||
// read config file
|
// read config file
|
||||||
ArrayList<String> lines = new ArrayList<>( 200 );
|
ArrayList<String> lines = new ArrayList<>( 200 );
|
||||||
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
||||||
String line = null;
|
String line;
|
||||||
while( (line = reader.readLine()) != null )
|
while( (line = reader.readLine()) != null )
|
||||||
lines.add( line );
|
lines.add( line );
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
|
|||||||
@@ -0,0 +1,336 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
|
import java.awt.AWTEvent;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.MouseInfo;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.PointerInfo;
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLayeredPane;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.MenuElement;
|
||||||
|
import javax.swing.MenuSelectionManager;
|
||||||
|
import javax.swing.RootPaneContainer;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Improves usability of submenus by using a
|
||||||
|
* <a href="https://height.app/blog/guide-to-build-context-menus#safe-triangle">safe triangle</a>
|
||||||
|
* to avoid that the submenu closes while the user moves the mouse to it.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
class SubMenuUsabilityHelper
|
||||||
|
implements ChangeListener
|
||||||
|
{
|
||||||
|
private static final String KEY_USE_SAFE_TRIANGLE = "Menu.useSafeTriangle";
|
||||||
|
private static final String KEY_SHOW_SAFE_TRIANGLE = "FlatLaf.debug.menu.showSafeTriangle";
|
||||||
|
|
||||||
|
// Using a static field to ensure that there is only one instance in the system.
|
||||||
|
// Multiple instances would freeze the application.
|
||||||
|
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
|
||||||
|
private static SubMenuUsabilityHelper instance;
|
||||||
|
|
||||||
|
private SubMenuEventQueue subMenuEventQueue;
|
||||||
|
private SafeTrianglePainter safeTrianglePainter;
|
||||||
|
private boolean changePending;
|
||||||
|
|
||||||
|
// mouse location in screen coordinates
|
||||||
|
private int mouseX;
|
||||||
|
private int mouseY;
|
||||||
|
|
||||||
|
// target popup bounds in screen coordinates
|
||||||
|
private int targetX;
|
||||||
|
private int targetTopY;
|
||||||
|
private int targetBottomY;
|
||||||
|
|
||||||
|
private Rectangle invokerBounds;
|
||||||
|
|
||||||
|
static synchronized boolean install() {
|
||||||
|
if( instance != null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
instance = new SubMenuUsabilityHelper();
|
||||||
|
MenuSelectionManager.defaultManager().addChangeListener( instance );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized void uninstall() {
|
||||||
|
if( instance == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
MenuSelectionManager.defaultManager().removeChangeListener( instance );
|
||||||
|
instance.uninstallEventQueue();
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
if( !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// handle menu selection change later, but only once in case of temporary changes
|
||||||
|
// e.g. moving mouse from one menu item to another one, fires two events:
|
||||||
|
// 1. old menu item is removed from menu selection
|
||||||
|
// 2. new menu item is added to menu selection
|
||||||
|
synchronized( this ) {
|
||||||
|
if( changePending )
|
||||||
|
return;
|
||||||
|
changePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
synchronized( this ) {
|
||||||
|
changePending = false;
|
||||||
|
}
|
||||||
|
menuSelectionChanged();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void menuSelectionChanged() {
|
||||||
|
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||||
|
|
||||||
|
/*debug
|
||||||
|
System.out.println( "--- " + path.length );
|
||||||
|
for( int i = 0; i < path.length; i++ )
|
||||||
|
System.out.println( " " + i + ": " + path[i].getClass().getName() );
|
||||||
|
debug*/
|
||||||
|
|
||||||
|
// find submenu in menu selection
|
||||||
|
int subMenuIndex = findSubMenu( path );
|
||||||
|
|
||||||
|
// uninstall if there is no submenu in selection
|
||||||
|
if( subMenuIndex < 0 || subMenuIndex != path.length - 1 ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get current mouse location
|
||||||
|
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||||
|
Point mouseLocation = (pointerInfo != null) ? pointerInfo.getLocation() : new Point();
|
||||||
|
mouseX = mouseLocation.x;
|
||||||
|
mouseY = mouseLocation.y;
|
||||||
|
|
||||||
|
// check whether popup is showing, which is e.g. not the case if it is empty
|
||||||
|
JPopupMenu popup = (JPopupMenu) path[subMenuIndex];
|
||||||
|
if( !popup.isShowing() ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get invoker screen bounds
|
||||||
|
Component invoker = popup.getInvoker();
|
||||||
|
invokerBounds = (invoker != null)
|
||||||
|
? 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 supress 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 width;
|
||||||
protected final int height;
|
protected final int height;
|
||||||
protected final Color color;
|
protected Color color;
|
||||||
|
|
||||||
public FlatAbstractIcon( int width, int height, Color color ) {
|
public FlatAbstractIcon( int width, int height, Color color ) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ import java.awt.Graphics2D;
|
|||||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for animated icons that scales width and height, creates and initializes
|
* Base class for animated icons that scale width and height, creates and initializes
|
||||||
* a scaled graphics context for icon painting.
|
* a scaled graphics context for icon painting.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses do not need to scale icon painting.
|
* Subclasses do not need to scale icon painting.
|
||||||
* <p>
|
* <p>
|
||||||
* This class does not store any state information (needed for animation) in its instance.
|
* This class does not store any state information (needed for animation) in its instance.
|
||||||
* Instead a client property is set on the painted component.
|
* Instead, a client property is set on the painted component.
|
||||||
* This makes it possible to use a share icon instance for multiple components.
|
* This makes it possible to use a share icon instance for multiple components.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.TableHeaderUI;
|
||||||
|
import javax.swing.table.JTableHeader;
|
||||||
|
import com.formdev.flatlaf.ui.FlatTableHeaderUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,8 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatAscendingSortIcon
|
public class FlatAscendingSortIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
protected boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
||||||
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
protected Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
||||||
|
|
||||||
public FlatAscendingSortIcon() {
|
public FlatAscendingSortIcon() {
|
||||||
super( 10, 5, null );
|
super( 10, 5, null );
|
||||||
@@ -44,7 +48,28 @@ public class FlatAscendingSortIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
boolean chevron = this.chevron;
|
||||||
|
Color sortIconColor = this.sortIconColor;
|
||||||
|
|
||||||
|
// Because this icon is always shared for all table headers,
|
||||||
|
// get icon specific style from FlatTableHeaderUI.
|
||||||
|
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
|
||||||
|
if( tableHeader != null ) {
|
||||||
|
TableHeaderUI ui = tableHeader.getUI();
|
||||||
|
if( ui instanceof FlatTableHeaderUI ) {
|
||||||
|
FlatTableHeaderUI fui = (FlatTableHeaderUI) ui;
|
||||||
|
if( fui.arrowType != null )
|
||||||
|
chevron = FlatUIUtils.isChevron( fui.arrowType );
|
||||||
|
if( fui.sortIconColor != null )
|
||||||
|
sortIconColor = fui.sortIconColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g.setColor( sortIconColor );
|
g.setColor( sortIconColor );
|
||||||
|
paintArrow( c, g, chevron );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );
|
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );
|
||||||
|
|||||||
@@ -16,12 +16,17 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,26 +39,51 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatCapsLockIcon
|
public class FlatCapsLockIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatCapsLockIcon() {
|
public FlatCapsLockIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
Object oldValue;
|
||||||
|
switch( key ) {
|
||||||
|
case "capsLockIconColor": oldValue = color; color = (Color) value; return oldValue;
|
||||||
|
default: throw new UnknownStyleException( key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
switch( key ) {
|
||||||
|
case "capsLockIconColor": return color;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||||
<rect width="6" height="2" x="5" y="11.5" fill="#FFF"/>
|
<rect width="5" height="2" x="5.5" y="11.5" stroke="#FFF" stroke-linejoin="round"/>
|
||||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
<path stroke="#FFF" stroke-linejoin="round" d="M2.5,7.5 L8,2 L13.5,7.5 L10.5,7.5 L10.5,9.5 L5.5,9.5 L5.5,7.5 L2.5,7.5 Z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND );
|
||||||
path.append( new Rectangle2D.Float( 5, 11.5f, 6, 2 ), false );
|
|
||||||
path.append( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 11,8, 11,10, 5,10, 5,8 ), false );
|
if( path == null ) {
|
||||||
|
path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
||||||
|
path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false );
|
||||||
|
path.append( new Area( stroke.createStrokedShape( FlatUIUtils.createPath(
|
||||||
|
2.5,7.5, 8,2, 13.5,7.5, 10.5,7.5, 10.5,9.5, 5.5,9.5, 5.5,7.5, 2.5,7.5 ) ) ), false );
|
||||||
|
}
|
||||||
g.fill( path );
|
g.fill( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,83 +23,115 @@ import java.awt.Component;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon for {@link javax.swing.JCheckBox}.
|
* Icon for {@link javax.swing.JCheckBox}.
|
||||||
*
|
* <p>
|
||||||
* Note: If Component.focusWidth is greater than zero, then the outline focus border
|
* <strong>Note</strong>:
|
||||||
|
* If Component.focusWidth is greater than zero, then the outer focus border
|
||||||
* is painted outside of the icon bounds. Make sure that the checkbox
|
* is painted outside of the icon bounds. Make sure that the checkbox
|
||||||
* has margins, which are equal or greater than focusWidth.
|
* has margins, which are equal or greater than focusWidth.
|
||||||
*
|
*
|
||||||
* @uiDefault CheckBox.icon.style String optional; "outline"/null (default) or "filled"
|
* @uiDefault CheckBox.icon.style String optional; "outlined"/null (default) or "filled"
|
||||||
* @uiDefault Component.focusWidth int
|
* @uiDefault Component.focusWidth int
|
||||||
|
* @uiDefault Component.borderWidth int
|
||||||
* @uiDefault Component.focusColor Color
|
* @uiDefault Component.focusColor Color
|
||||||
* @uiDefault CheckBox.icon.focusWidth int optional; defaults to Component.focusWidth
|
* @uiDefault CheckBox.icon.focusWidth int or float optional; defaults to Component.focusWidth
|
||||||
|
* @uiDefault CheckBox.icon.borderWidth int or float optional; defaults to Component.borderWidth
|
||||||
|
* @uiDefault CheckBox.icon.selectedBorderWidth int or float optional; defaults to CheckBox.icon.borderWidth
|
||||||
|
* @uiDefault CheckBox.icon.disabledSelectedBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth
|
||||||
|
* @uiDefault CheckBox.arc int
|
||||||
|
*
|
||||||
* @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor
|
* @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor
|
||||||
* @uiDefault CheckBox.icon.borderColor Color
|
* @uiDefault CheckBox.icon.borderColor Color
|
||||||
* @uiDefault CheckBox.icon.background Color
|
* @uiDefault CheckBox.icon.background Color
|
||||||
* @uiDefault CheckBox.icon.selectedBorderColor Color
|
* @uiDefault CheckBox.icon.selectedBorderColor Color
|
||||||
* @uiDefault CheckBox.icon.selectedBackground Color
|
* @uiDefault CheckBox.icon.selectedBackground Color
|
||||||
* @uiDefault CheckBox.icon.checkmarkColor Color
|
* @uiDefault CheckBox.icon.checkmarkColor Color
|
||||||
|
*
|
||||||
* @uiDefault CheckBox.icon.disabledBorderColor Color
|
* @uiDefault CheckBox.icon.disabledBorderColor Color
|
||||||
* @uiDefault CheckBox.icon.disabledBackground 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.disabledCheckmarkColor Color
|
||||||
|
*
|
||||||
* @uiDefault CheckBox.icon.focusedBorderColor Color optional
|
* @uiDefault CheckBox.icon.focusedBorderColor Color optional
|
||||||
* @uiDefault CheckBox.icon.focusedBackground 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.focusedSelectedBorderColor 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.focusedSelectedBackground 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.focusedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified
|
||||||
|
*
|
||||||
* @uiDefault CheckBox.icon.hoverBorderColor Color optional
|
* @uiDefault CheckBox.icon.hoverBorderColor Color optional
|
||||||
* @uiDefault CheckBox.icon.hoverBackground 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.pressedBackground Color optional
|
||||||
* @uiDefault CheckBox.icon.selectedPressedBackground Color optional; CheckBox.icon.pressedBackground is used if not specified
|
* @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; CheckBox.icon.pressedBorderColor is used if not specified
|
||||||
* @uiDefault CheckBox.arc int
|
* @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
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatCheckBoxIcon
|
public class FlatCheckBoxIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final String style = UIManager.getString( "CheckBox.icon.style" );
|
protected final String style = UIManager.getString( getPropertyPrefix() + "icon.style" );
|
||||||
public final int focusWidth = getUIInt( "CheckBox.icon.focusWidth",
|
@Styleable protected float focusWidth = getUIFloat( "CheckBox.icon.focusWidth", UIManager.getInt( "Component.focusWidth" ), style );
|
||||||
UIManager.getInt( "Component.focusWidth" ), style );
|
@Styleable protected Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusColor", UIManager.getColor( "Component.focusColor" ) );
|
||||||
protected final Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusColor",
|
/** @since 2 */ @Styleable protected float borderWidth = getUIFloat( "CheckBox.icon.borderWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ), style );
|
||||||
UIManager.getColor( "Component.focusColor" ) );
|
/** @since 2 */ @Styleable protected float selectedBorderWidth = getUIFloat( "CheckBox.icon.selectedBorderWidth", Float.MIN_VALUE, style );
|
||||||
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
|
/** @since 2 */ @Styleable protected float disabledSelectedBorderWidth = getUIFloat( "CheckBox.icon.disabledSelectedBorderWidth", Float.MIN_VALUE, style );
|
||||||
|
@Styleable protected int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
|
||||||
|
|
||||||
// enabled
|
// enabled
|
||||||
protected final Color borderColor = getUIColor( "CheckBox.icon.borderColor", style );
|
@Styleable protected Color borderColor = getUIColor( "CheckBox.icon.borderColor", style );
|
||||||
protected final Color background = getUIColor( "CheckBox.icon.background", style );
|
@Styleable protected Color background = getUIColor( "CheckBox.icon.background", style );
|
||||||
protected final Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
|
@Styleable protected Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
|
||||||
protected final Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
|
@Styleable protected Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
|
||||||
protected final Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
|
@Styleable protected Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
|
||||||
|
|
||||||
// disabled
|
// disabled
|
||||||
protected final Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
|
@Styleable protected Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
|
||||||
protected final Color disabledBackground = getUIColor( "CheckBox.icon.disabledBackground", style );
|
@Styleable protected Color disabledBackground = getUIColor( "CheckBox.icon.disabledBackground", style );
|
||||||
protected final Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
|
/** @since 2 */ @Styleable protected Color disabledSelectedBorderColor = getUIColor( "CheckBox.icon.disabledSelectedBorderColor", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color disabledSelectedBackground = getUIColor( "CheckBox.icon.disabledSelectedBackground", style );
|
||||||
|
@Styleable protected Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
|
||||||
|
|
||||||
// focused
|
// focused
|
||||||
protected final Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
|
@Styleable protected Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
|
||||||
protected final Color focusedBackground = getUIColor( "CheckBox.icon.focusedBackground", style );
|
@Styleable protected Color focusedBackground = getUIColor( "CheckBox.icon.focusedBackground", style );
|
||||||
protected final Color selectedFocusedBorderColor = getUIColor( "CheckBox.icon.selectedFocusedBorderColor", style );
|
/** @since 2 */ @Styleable protected Color focusedSelectedBorderColor = getUIColor( "CheckBox.icon.focusedSelectedBorderColor", style );
|
||||||
protected final Color selectedFocusedBackground = getUIColor( "CheckBox.icon.selectedFocusedBackground", style );
|
/** @since 2 */ @Styleable protected Color focusedSelectedBackground = getUIColor( "CheckBox.icon.focusedSelectedBackground", style );
|
||||||
protected final Color selectedFocusedCheckmarkColor = getUIColor( "CheckBox.icon.selectedFocusedCheckmarkColor", style );
|
/** @since 2 */ @Styleable protected Color focusedCheckmarkColor = getUIColor( "CheckBox.icon.focusedCheckmarkColor", style );
|
||||||
|
|
||||||
// hover
|
// hover
|
||||||
protected final Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
|
@Styleable protected Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
|
||||||
protected final Color hoverBackground = getUIColor( "CheckBox.icon.hoverBackground", style );
|
@Styleable protected Color hoverBackground = getUIColor( "CheckBox.icon.hoverBackground", style );
|
||||||
protected final Color selectedHoverBackground = getUIColor( "CheckBox.icon.selectedHoverBackground", style );
|
/** @since 2 */ @Styleable protected Color hoverSelectedBorderColor = getUIColor( "CheckBox.icon.hoverSelectedBorderColor", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color hoverSelectedBackground = getUIColor( "CheckBox.icon.hoverSelectedBackground", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color hoverCheckmarkColor = getUIColor( "CheckBox.icon.hoverCheckmarkColor", style );
|
||||||
|
|
||||||
// pressed
|
// pressed
|
||||||
protected final Color pressedBackground = getUIColor( "CheckBox.icon.pressedBackground", style );
|
/** @since 2 */ @Styleable protected Color pressedBorderColor = getUIColor( "CheckBox.icon.pressedBorderColor", style );
|
||||||
protected final Color selectedPressedBackground = getUIColor( "CheckBox.icon.selectedPressedBackground", style );
|
@Styleable protected Color pressedBackground = getUIColor( "CheckBox.icon.pressedBackground", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color pressedSelectedBorderColor = getUIColor( "CheckBox.icon.pressedSelectedBorderColor", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color pressedSelectedBackground = getUIColor( "CheckBox.icon.pressedSelectedBackground", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color pressedCheckmarkColor = getUIColor( "CheckBox.icon.pressedCheckmarkColor", style );
|
||||||
|
|
||||||
|
protected String getPropertyPrefix() {
|
||||||
|
return "CheckBox.";
|
||||||
|
}
|
||||||
|
|
||||||
protected static Color getUIColor( String key, String style ) {
|
protected static Color getUIColor( String key, String style ) {
|
||||||
if( style != null ) {
|
if( style != null ) {
|
||||||
@@ -110,13 +142,14 @@ public class FlatCheckBoxIcon
|
|||||||
return UIManager.getColor( key );
|
return UIManager.getColor( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int getUIInt( String key, int defaultValue, String style ) {
|
/** @since 2 */
|
||||||
|
protected static float getUIFloat( String key, float defaultValue, String style ) {
|
||||||
if( style != null ) {
|
if( style != null ) {
|
||||||
Object value = UIManager.get( styleKey( key, style ) );
|
float value = FlatUIUtils.getUIFloat( styleKey( key, style ), Float.MIN_VALUE );
|
||||||
if( value instanceof Integer )
|
if( value != Float.MIN_VALUE )
|
||||||
return (Integer) value;
|
return value;
|
||||||
}
|
}
|
||||||
return FlatUIUtils.getUIInt( key, defaultValue );
|
return FlatUIUtils.getUIFloat( key, defaultValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String styleKey( String key, String style ) {
|
private static String styleKey( String key, String style ) {
|
||||||
@@ -129,11 +162,31 @@ public class FlatCheckBoxIcon
|
|||||||
super( ICON_SIZE, ICON_SIZE, null );
|
super( ICON_SIZE, ICON_SIZE, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
boolean indeterminate = isIndeterminate( c );
|
boolean indeterminate = isIndeterminate( c );
|
||||||
boolean selected = indeterminate || isSelected( c );
|
boolean selected = indeterminate || isSelected( c );
|
||||||
boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c );
|
boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||||
|
float bw = selected
|
||||||
|
? (disabledSelectedBorderWidth != Float.MIN_VALUE && !c.isEnabled()
|
||||||
|
? disabledSelectedBorderWidth
|
||||||
|
: (selectedBorderWidth != Float.MIN_VALUE ? selectedBorderWidth : borderWidth))
|
||||||
|
: borderWidth;
|
||||||
|
|
||||||
// paint focused border
|
// paint focused border
|
||||||
if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) {
|
if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) {
|
||||||
@@ -143,7 +196,7 @@ public class FlatCheckBoxIcon
|
|||||||
|
|
||||||
// paint border
|
// paint border
|
||||||
g.setColor( getBorderColor( c, selected ) );
|
g.setColor( getBorderColor( c, selected ) );
|
||||||
paintBorder( c, g );
|
paintBorder( c, g, bw );
|
||||||
|
|
||||||
// paint background
|
// paint background
|
||||||
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ),
|
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ),
|
||||||
@@ -151,14 +204,14 @@ public class FlatCheckBoxIcon
|
|||||||
if( bg.getAlpha() < 255 ) {
|
if( bg.getAlpha() < 255 ) {
|
||||||
// fill background with default color before filling with non-opaque background
|
// fill background with default color before filling with non-opaque background
|
||||||
g.setColor( selected ? selectedBackground : background );
|
g.setColor( selected ? selectedBackground : background );
|
||||||
paintBackground( c, g );
|
paintBackground( c, g, bw );
|
||||||
}
|
}
|
||||||
g.setColor( bg );
|
g.setColor( bg );
|
||||||
paintBackground( c, g );
|
paintBackground( c, g, bw );
|
||||||
|
|
||||||
// paint checkmark
|
// paint checkmark
|
||||||
if( selected || indeterminate ) {
|
if( selected ) {
|
||||||
g.setColor( getCheckmarkColor( c, selected, isFocused ) );
|
g.setColor( getCheckmarkColor( c ) );
|
||||||
if( indeterminate )
|
if( indeterminate )
|
||||||
paintIndeterminate( c, g );
|
paintIndeterminate( c, g );
|
||||||
else
|
else
|
||||||
@@ -167,24 +220,29 @@ public class FlatCheckBoxIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||||
// the outline focus border is painted outside of the icon
|
// the outer focus border is painted outside of the icon
|
||||||
int wh = ICON_SIZE - 1 + (focusWidth * 2);
|
float wh = ICON_SIZE - 1 + (focusWidth * 2);
|
||||||
int arcwh = arc + (focusWidth * 2);
|
float arcwh = arc + (focusWidth * 2);
|
||||||
g.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
|
g.fill( new RoundRectangle2D.Float( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintBorder( Component c, Graphics2D g ) {
|
protected void paintBorder( Component c, Graphics2D g, float borderWidth ) {
|
||||||
|
if( borderWidth == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
int arcwh = arc;
|
int arcwh = arc;
|
||||||
g.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
|
g.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
protected void paintBackground( Component c, Graphics2D g, float borderWidth ) {
|
||||||
int arcwh = arc - 1;
|
float xy = borderWidth;
|
||||||
g.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
|
float wh = 14 - (borderWidth * 2);
|
||||||
|
float arcwh = arc - borderWidth;
|
||||||
|
g.fill( new RoundRectangle2D.Float( 1 + xy, xy, wh, wh, arcwh, arcwh ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCheckmark( Component c, Graphics2D g ) {
|
protected void paintCheckmark( Component c, Graphics2D g ) {
|
||||||
Path2D.Float path = new Path2D.Float();
|
Path2D.Float path = new Path2D.Float( Path2D.WIND_NON_ZERO, 3 );
|
||||||
path.moveTo( 4.5f, 7.5f );
|
path.moveTo( 4.5f, 7.5f );
|
||||||
path.lineTo( 6.6f, 10f );
|
path.lineTo( 6.6f, 10f );
|
||||||
path.lineTo( 11.25f, 3.5f );
|
path.lineTo( 11.25f, 3.5f );
|
||||||
@@ -205,6 +263,11 @@ public class FlatCheckBoxIcon
|
|||||||
return c instanceof AbstractButton && ((AbstractButton)c).isSelected();
|
return c instanceof AbstractButton && ((AbstractButton)c).isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public float getFocusWidth() {
|
||||||
|
return focusWidth;
|
||||||
|
}
|
||||||
|
|
||||||
protected Color getFocusColor( Component c ) {
|
protected Color getFocusColor( Component c ) {
|
||||||
return focusColor;
|
return focusColor;
|
||||||
}
|
}
|
||||||
@@ -212,26 +275,27 @@ public class FlatCheckBoxIcon
|
|||||||
protected Color getBorderColor( Component c, boolean selected ) {
|
protected Color getBorderColor( Component c, boolean selected ) {
|
||||||
return FlatButtonUI.buttonStateColor( c,
|
return FlatButtonUI.buttonStateColor( c,
|
||||||
selected ? selectedBorderColor : borderColor,
|
selected ? selectedBorderColor : borderColor,
|
||||||
disabledBorderColor,
|
(selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor,
|
||||||
selected && selectedFocusedBorderColor != null ? selectedFocusedBorderColor : focusedBorderColor,
|
(selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor,
|
||||||
hoverBorderColor,
|
(selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor,
|
||||||
null );
|
(selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBackground( Component c, boolean selected ) {
|
protected Color getBackground( Component c, boolean selected ) {
|
||||||
return FlatButtonUI.buttonStateColor( c,
|
return FlatButtonUI.buttonStateColor( c,
|
||||||
selected ? selectedBackground : background,
|
selected ? selectedBackground : background,
|
||||||
disabledBackground,
|
(selected && disabledSelectedBackground != null) ? disabledSelectedBackground : disabledBackground,
|
||||||
(selected && selectedFocusedBackground != null) ? selectedFocusedBackground : focusedBackground,
|
(selected && focusedSelectedBackground != null) ? focusedSelectedBackground : focusedBackground,
|
||||||
(selected && selectedHoverBackground != null) ? selectedHoverBackground : hoverBackground,
|
(selected && hoverSelectedBackground != null) ? hoverSelectedBackground : hoverBackground,
|
||||||
(selected && selectedPressedBackground != null) ? selectedPressedBackground : pressedBackground );
|
(selected && pressedSelectedBackground != null) ? pressedSelectedBackground : pressedBackground );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getCheckmarkColor( Component c, boolean selected, boolean isFocused ) {
|
protected Color getCheckmarkColor( Component c ) {
|
||||||
return c.isEnabled()
|
return FlatButtonUI.buttonStateColor( c,
|
||||||
? ((selected && isFocused && selectedFocusedCheckmarkColor != null)
|
checkmarkColor,
|
||||||
? selectedFocusedCheckmarkColor
|
disabledCheckmarkColor,
|
||||||
: checkmarkColor)
|
focusedCheckmarkColor,
|
||||||
: disabledCheckmarkColor;
|
hoverCheckmarkColor,
|
||||||
|
pressedCheckmarkColor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,18 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon for {@link javax.swing.JCheckBoxMenuItem}.
|
* Icon for {@link javax.swing.JCheckBoxMenuItem}.
|
||||||
*
|
*
|
||||||
* @uiDefault MenuItemCheckBox.icon.checkmarkColor Color
|
* @uiDefault CheckBoxMenuItem.icon.checkmarkColor Color
|
||||||
* @uiDefault MenuItemCheckBox.icon.disabledCheckmarkColor Color
|
* @uiDefault CheckBoxMenuItem.icon.disabledCheckmarkColor Color
|
||||||
* @uiDefault MenuItem.selectionForeground Color
|
* @uiDefault MenuItem.selectionForeground Color
|
||||||
* @uiDefault MenuItem.selectionType String
|
* @uiDefault MenuItem.selectionType String
|
||||||
*
|
*
|
||||||
@@ -38,14 +41,29 @@ import javax.swing.UIManager;
|
|||||||
public class FlatCheckBoxMenuItemIcon
|
public class FlatCheckBoxMenuItemIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final Color checkmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.checkmarkColor" );
|
@Styleable protected Color checkmarkColor = UIManager.getColor( "CheckBoxMenuItem.icon.checkmarkColor" );
|
||||||
protected final Color disabledCheckmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.disabledCheckmarkColor" );
|
@Styleable protected Color disabledCheckmarkColor = UIManager.getColor( "CheckBoxMenuItem.icon.disabledCheckmarkColor" );
|
||||||
protected final Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
@Styleable protected Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
||||||
|
|
||||||
public FlatCheckBoxMenuItemIcon() {
|
public FlatCheckBoxMenuItemIcon() {
|
||||||
super( 15, 15, null );
|
super( 15, 15, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||||
boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected();
|
boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected();
|
||||||
@@ -58,7 +76,7 @@ public class FlatCheckBoxMenuItemIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCheckmark( Graphics2D g2 ) {
|
protected void paintCheckmark( Graphics2D g2 ) {
|
||||||
Path2D.Float path = new Path2D.Float();
|
Path2D.Float path = new Path2D.Float( Path2D.WIND_NON_ZERO, 3 );
|
||||||
path.moveTo( 4.5f, 7.5f );
|
path.moveTo( 4.5f, 7.5f );
|
||||||
path.lineTo( 6.6f, 10f );
|
path.lineTo( 6.6f, 10f );
|
||||||
path.lineTo( 11.25f, 3.5f );
|
path.lineTo( 11.25f, 3.5f );
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.ButtonModel;
|
import javax.swing.ButtonModel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,17 +42,40 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatClearIcon
|
public class FlatClearIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected Color clearIconColor = UIManager.getColor( "SearchField.clearIconColor" );
|
@Styleable protected Color clearIconColor = UIManager.getColor( "SearchField.clearIconColor" );
|
||||||
protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" );
|
@Styleable protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" );
|
||||||
protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" );
|
@Styleable protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" );
|
||||||
|
|
||||||
|
private final boolean ignoreButtonState;
|
||||||
|
|
||||||
public FlatClearIcon() {
|
public FlatClearIcon() {
|
||||||
|
this( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public FlatClearIcon( boolean ignoreButtonState ) {
|
||||||
super( 16, 16, null );
|
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
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
if( c instanceof AbstractButton ) {
|
if( !ignoreButtonState && c instanceof AbstractButton ) {
|
||||||
ButtonModel model = ((AbstractButton)c).getModel();
|
ButtonModel model = ((AbstractButton)c).getModel();
|
||||||
if( model.isPressed() || model.isRollover() ) {
|
if( model.isPressed() || model.isRollover() ) {
|
||||||
/*
|
/*
|
||||||
@@ -77,9 +102,11 @@ public class FlatClearIcon
|
|||||||
|
|
||||||
// paint cross
|
// paint cross
|
||||||
g.setColor( clearIconColor );
|
g.setColor( clearIconColor );
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( 5,5, 11,11 ), false );
|
path.moveTo( 5, 5 );
|
||||||
path.append( new Line2D.Float( 5,11, 11,5 ), false );
|
path.lineTo( 11, 11 );
|
||||||
|
path.moveTo( 5, 11 );
|
||||||
|
path.lineTo( 11, 5 );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,9 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,18 +31,14 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatDescendingSortIcon
|
public class FlatDescendingSortIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAscendingSortIcon
|
||||||
{
|
{
|
||||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
|
||||||
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
|
||||||
|
|
||||||
public FlatDescendingSortIcon() {
|
public FlatDescendingSortIcon() {
|
||||||
super( 10, 5, null );
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
|
||||||
g.setColor( sortIconColor );
|
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );
|
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );
|
||||||
|
|||||||
@@ -39,21 +39,25 @@ public class FlatFileChooserDetailsViewIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="2" height="2" x="2" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="7" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="11" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="7" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="11" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fillRect( 2, 3, 2, 2 );
|
g.fillRoundRect( 2, 3, 2, 1, 1, 1 );
|
||||||
g.fillRect( 2, 7, 2, 2 );
|
g.fillRoundRect( 2, 6, 2, 1, 1, 1 );
|
||||||
g.fillRect( 2, 11, 2, 2 );
|
g.fillRoundRect( 2, 9, 2, 1, 1, 1 );
|
||||||
g.fillRect( 6, 3, 8, 2 );
|
g.fillRoundRect( 2, 12, 2, 1, 1, 1 );
|
||||||
g.fillRect( 6, 7, 8, 2 );
|
g.fillRoundRect( 6, 3, 8, 1, 1, 1 );
|
||||||
g.fillRect( 6, 11, 8, 2 );
|
g.fillRoundRect( 6, 6, 8, 1, 1, 1 );
|
||||||
|
g.fillRoundRect( 6, 9, 8, 1, 1, 1 );
|
||||||
|
g.fillRoundRect( 6, 12, 8, 1, 1, 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -39,10 +41,22 @@ public class FlatFileChooserHomeFolderIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="2 8 8 2 14 8 12 8 12 13 9 13 9 10 7 10 7 13 4 13 4 8"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linejoin="round" points="6.5 13 6.5 9.5 9.5 9.5 9.5 13"/>
|
||||||
|
<path stroke="#6E6E6E" d="M3.5,6.5 L3.5,12.5 C3.5,13.0522847 3.94771525,13.5 4.5,13.5 L11.5,13.5 C12.0522847,13.5 12.5,13.0522847 12.5,12.5 L12.5,6.5 L12.5,6.5"/>
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linecap="round" stroke-linejoin="round" points="1.5 8.5 8 2 14.5 8.5"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 12,8, 12,13, 9,13, 9,10, 7,10, 7,13, 4,13, 4,8 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 6.5,13, 6.5,9.5, 9.5,9.5, 9.5,13 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 3.5,6.5,
|
||||||
|
3.5,12.5, FlatUIUtils.QUAD_TO, 3.5,13.5, 4.5,13.5,
|
||||||
|
11.5,13.5, FlatUIUtils.QUAD_TO, 12.5,13.5, 12.5,12.5,
|
||||||
|
12.5,6.5 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 1.5,8.5, 8,2, 14.5,8.5 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,17 +42,20 @@ public class FlatFileChooserListViewIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="4" height="4" x="3" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="3" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fillRect( 3, 3, 4, 4 );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fillRect( 3, 9, 4, 4 );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
g.fillRect( 9, 9, 4, 4 );
|
|
||||||
g.fillRect( 9, 3, 4, 4 );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 2.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 2.5f, 9.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 9.5f, 9.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 9.5f, 2.5f, 4, 4, 2, 2 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileChooserNewFolderIcon
|
public class FlatFileChooserNewFolderIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private final Color greenColor = UIManager.getColor( "Actions.Green" );
|
||||||
|
|
||||||
public FlatFileChooserNewFolderIcon() {
|
public FlatFileChooserNewFolderIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Actions.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Actions.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -40,13 +45,20 @@ public class FlatFileChooserNewFolderIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 14 5 14 8 11 8 11 10 9 10 9 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#59A869" d="M14,11 L16,11 L16,13 L14,13 L14,15 L12,15 L12,13 L10,13 L10,11 L12,11 L12,9 L14,9 L14,11 Z"/>
|
<line x1="5.5" x2="10.5" y1="9" y2="9" stroke="#59A869" stroke-linecap="round"/>
|
||||||
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#59A869" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,3, 5.5,3, 7,5, 14,5, 14,8, 11,8, 11,10, 9,10, 9,13, 2,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 14,11, 16,11, 16,13, 14,13, 14,15, 12,15, 12,13, 10,13, 10,11, 12,11, 12,9, 14,9, 14,11 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatFileViewDirectoryIcon.createFolderPath() );
|
||||||
|
|
||||||
|
g.setColor( greenColor );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 9, 10.5f, 9 ) );
|
||||||
|
g.draw( new Line2D.Float( 8, 6.5f, 8, 11.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -44,15 +47,20 @@ public class FlatFileChooserUpFolderIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 9 5 9 9 13 9 13 5 14 5 14 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#389FD6" d="M12,4 L12,8 L10,8 L10,4 L8,4 L11,1 L14,4 L12,4 Z"/>
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#389FD6" stroke-linecap="round"/>
|
||||||
|
<polyline stroke="#389FD6" stroke-linecap="round" stroke-linejoin="round" points="5.5 9 8 6.5 10.5 9"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,3, 5.5,3, 7,5, 9,5, 9,9, 13,9, 13,5, 14,5, 14,13, 2,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatFileViewDirectoryIcon.createFolderPath() );
|
||||||
|
|
||||||
g.setColor( blueColor );
|
g.setColor( blueColor );
|
||||||
g.fill( FlatUIUtils.createPath( 12,4, 12,8, 10,8, 10,4, 8,4, 11,1, 14,4, 12,4 ) );
|
g.draw( new Line2D.Float( 8, 6.5f, 8, 11.5f ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 5.5,9, 8,6.5, 10.5,9 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,17 +43,18 @@ public class FlatFileViewComputerIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<path fill="#6E6E6E" d="M2,3 L14,3 L14,11 L2,11 L2,3 Z M4,5 L4,9 L12,9 L12,5 L4,5 Z"/>
|
<rect width="11" height="7" x="2.5" y="3.5" stroke="#6E6E6E" rx="1"/>
|
||||||
<rect width="12" height="2" x="2" y="12" fill="#6E6E6E"/>
|
<line x1="8" x2="8" y1="11" y2="12" stroke="#6E6E6E"/>
|
||||||
|
<line x1="4.5" x2="11.5" y1="12.5" y2="12.5" stroke="#6E6E6E" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new Rectangle2D.Float( 2, 3, 12, 8 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( new Rectangle2D.Float( 4, 5, 8, 4 ), false );
|
|
||||||
g.fill( path );
|
|
||||||
|
|
||||||
g.fillRect( 2, 12, 12, 2 );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 3.5f, 11, 7, 2, 2 ) );
|
||||||
|
g.drawLine( 8, 11, 8, 12 );
|
||||||
|
g.draw( new Line2D.Float( 4.5f, 12.5f, 11.5f, 12.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileViewDirectoryIcon
|
public class FlatFileViewDirectoryIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatFileViewDirectoryIcon() {
|
public FlatFileViewDirectoryIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -39,10 +43,32 @@ public class FlatFileViewDirectoryIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 15,4, 15,13, 1,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
if( path == null )
|
||||||
|
path = createFolderPath();
|
||||||
|
g.draw( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Path2D createFolderPath() {
|
||||||
|
double arc = 1.5;
|
||||||
|
double arc2 = 0.5;
|
||||||
|
return FlatUIUtils.createPath(
|
||||||
|
// bottom-right
|
||||||
|
14.5,13.5-arc, FlatUIUtils.QUAD_TO, 14.5,13.5, 14.5-arc,13.5,
|
||||||
|
// bottom-left
|
||||||
|
1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc,
|
||||||
|
// top-left
|
||||||
|
1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5,
|
||||||
|
// top-mid-left
|
||||||
|
6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2,
|
||||||
|
// top-mid-right
|
||||||
|
8.5,4.5,
|
||||||
|
// top-right
|
||||||
|
14.5-arc,4.5, FlatUIUtils.QUAD_TO, 14.5,4.5, 14.5,4.5+arc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileViewFileIcon
|
public class FlatFileViewFileIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatFileViewFileIcon() {
|
public FlatFileViewFileIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -39,14 +44,33 @@ public class FlatFileViewFileIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<path stroke="#6E6E6E" d="M4,1.5 L8.8,1.5 L8.8,1.5 L13.5,6.2 L13.5,13 C13.5,13.8284271 12.8284271,14.5 12,14.5 L4,14.5 C3.17157288,14.5 2.5,13.8284271 2.5,13 L2.5,3 C2.5,2.17157288 3.17157288,1.5 4,1.5 Z"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<path stroke="#6E6E6E" d="M8.5,2 L8.5,5 C8.5,5.82842712 9.17157288,6.5 10,6.5 L13,6.5 L13,6.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
double arc = 1.5;
|
||||||
|
path = FlatUIUtils.createPath( false,
|
||||||
|
// top-left
|
||||||
|
2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5,
|
||||||
|
// top-right
|
||||||
|
8.8,1.5, 13.5,6.2,
|
||||||
|
// bottom-right
|
||||||
|
13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5,
|
||||||
|
// bottom-left
|
||||||
|
2.5+arc,14.5, FlatUIUtils.QUAD_TO, 2.5,14.5, 2.5,14.5-arc,
|
||||||
|
FlatUIUtils.CLOSE_PATH,
|
||||||
|
|
||||||
|
FlatUIUtils.MOVE_TO, 8.5,2,
|
||||||
|
8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5,
|
||||||
|
13,6.5 );
|
||||||
|
}
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -40,18 +41,22 @@ public class FlatFileViewFloppyDriveIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<path fill="#6E6E6E" d="M11,14 L11,11 L5,11 L5,14 L2,14 L2,2 L14,2 L14,14 L11,14 Z M4,4 L4,8 L12,8 L12,4 L4,4 Z"/>
|
<path stroke="#6E6E6E" d="M3.5,2.5 L11.5,2.5 L11.5,2.5 L13.5,4.5 L13.5,12.5 C13.5,13.0522847 13.0522847,13.5 12.5,13.5 L3.5,13.5 C2.94771525,13.5 2.5,13.0522847 2.5,12.5 L2.5,3.5 C2.5,2.94771525 2.94771525,2.5 3.5,2.5 Z"/>
|
||||||
<rect width="4" height="2" x="6" y="12" fill="#6E6E6E"/>
|
<polyline stroke="#6E6E6E" points="4.5 13 4.5 9.5 11.5 9.5 11.5 13"/>
|
||||||
|
<polyline stroke="#6E6E6E" points="5.5 3 5.5 5.5 10.5 5.5 10.5 3"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( FlatUIUtils.createPath( 11,14, 11,11, 5,11, 5,14, 2,14, 2,2, 14,2, 14,14, 11,14 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( FlatUIUtils.createPath( 4,4, 4,8, 12,8, 12,4, 4,4 ), false );
|
|
||||||
g.fill( path );
|
|
||||||
|
|
||||||
g.fillRect( 6, 12, 4, 2 );
|
g.draw( FlatUIUtils.createPath( 3.5,2.5, 11.5,2.5, 11.5,2.5, 13.5,4.5,
|
||||||
|
13.5,12.5, FlatUIUtils.QUAD_TO, 13.5,13.5, 12.5,13.5,
|
||||||
|
3.5,13.5, FlatUIUtils.QUAD_TO, 2.5,13.5, 2.5,12.5,
|
||||||
|
2.5,3.5, FlatUIUtils.QUAD_TO, 2.5,2.5, 3.5,2.5 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 4.5,13, 4.5,9.5, 11.5,9.5, 11.5,13 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 5.5,3, 5.5,5.5, 10.5,5.5, 10.5,3 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,14 +42,19 @@ public class FlatFileViewHardDriveIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<path fill="#6E6E6E" fill-rule="evenodd" d="M2,6 L14,6 L14,10 L2,10 L2,6 Z M12,8 L12,9 L13,9 L13,8 L12,8 Z M10,8 L10,9 L11,9 L11,8 L10,8 Z"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<rect width="11" height="5" x="2.5" y="5.5" stroke="#6E6E6E" rx="1"/>
|
||||||
|
<circle cx="11.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
<circle cx="9.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new Rectangle2D.Float( 2, 6, 12, 4 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( new Rectangle2D.Float( 12, 8, 1, 1 ), false );
|
|
||||||
path.append( new Rectangle2D.Float( 10, 8, 1, 1 ), false );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 5.5f, 11, 5, 2, 2 ) );
|
||||||
g.fill( path );
|
g.fill( new Ellipse2D.Float( 10.8f, 7.8f, 1.4f, 1.4f ) );
|
||||||
|
g.fill( new Ellipse2D.Float( 8.8f, 7.8f, 1.4f, 1.4f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,18 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.util.UIScale.*;
|
import static com.formdev.flatlaf.util.UIScale.*;
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,29 +55,42 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatHelpButtonIcon
|
public class FlatHelpButtonIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
@Styleable protected int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
@Styleable protected Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "HelpButton.innerFocusWidth", FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 ) );
|
@Styleable protected float innerFocusWidth = FlatUIUtils.getUIFloat( "HelpButton.innerFocusWidth", FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 ) );
|
||||||
protected final int borderWidth = FlatUIUtils.getUIInt( "HelpButton.borderWidth", 1 );
|
@Styleable protected int borderWidth = FlatUIUtils.getUIInt( "HelpButton.borderWidth", 1 );
|
||||||
|
|
||||||
protected final Color borderColor = UIManager.getColor( "HelpButton.borderColor" );
|
@Styleable protected Color borderColor = UIManager.getColor( "HelpButton.borderColor" );
|
||||||
protected final Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" );
|
@Styleable protected Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" );
|
||||||
protected final Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" );
|
@Styleable protected Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" );
|
||||||
protected final Color hoverBorderColor = UIManager.getColor( "HelpButton.hoverBorderColor" );
|
@Styleable protected Color hoverBorderColor = UIManager.getColor( "HelpButton.hoverBorderColor" );
|
||||||
protected final Color background = UIManager.getColor( "HelpButton.background" );
|
@Styleable protected Color background = UIManager.getColor( "HelpButton.background" );
|
||||||
protected final Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" );
|
@Styleable protected Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" );
|
||||||
protected final Color focusedBackground = UIManager.getColor( "HelpButton.focusedBackground" );
|
@Styleable protected Color focusedBackground = UIManager.getColor( "HelpButton.focusedBackground" );
|
||||||
protected final Color hoverBackground = UIManager.getColor( "HelpButton.hoverBackground" );
|
@Styleable protected Color hoverBackground = UIManager.getColor( "HelpButton.hoverBackground" );
|
||||||
protected final Color pressedBackground = UIManager.getColor( "HelpButton.pressedBackground" );
|
@Styleable protected Color pressedBackground = UIManager.getColor( "HelpButton.pressedBackground" );
|
||||||
protected final Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" );
|
@Styleable protected Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" );
|
||||||
protected final Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" );
|
@Styleable protected Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" );
|
||||||
|
|
||||||
protected final int iconSize = 22 + (focusWidth * 2);
|
|
||||||
|
|
||||||
public FlatHelpButtonIcon() {
|
public FlatHelpButtonIcon() {
|
||||||
super( 0, 0, null );
|
super( 0, 0, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||||
/*
|
/*
|
||||||
@@ -80,16 +98,17 @@ public class FlatHelpButtonIcon
|
|||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
||||||
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
||||||
<path fill="#6E6E6E" d="M10,17 L12,17 L12,15 L10,15 L10,17 Z M11,5 C8.8,5 7,6.8 7,9 L9,9 C9,7.9 9.9,7 11,7 C12.1,7 13,7.9 13,9 C13,11 10,10.75 10,14 L12,14 C12,11.75 15,11.5 15,9 C15,6.8 13.2,5 11,5 Z"/>
|
<path stroke="#6E6E6E" stroke-linecap="round" stroke-width="2" d="M8,8.5 C8.25,7 9.66585007,6 11,6 C12.5,6 14,7 14,8.5 C14,10.5 11,11 11,13"/>
|
||||||
|
<circle cx="11" cy="16" r="1.2" fill="#6E6E6E"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
boolean enabled = c.isEnabled();
|
boolean enabled = c == null || c.isEnabled();
|
||||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
|
||||||
|
|
||||||
float xy = 0.5f;
|
float xy = 0.5f;
|
||||||
float wh = iconSize - 1;
|
float wh = iconSize() - 1;
|
||||||
|
|
||||||
// paint outer focus border
|
// paint outer focus border
|
||||||
if( focused && FlatButtonUI.isFocusPainted( c ) ) {
|
if( focused && FlatButtonUI.isFocusPainted( c ) ) {
|
||||||
@@ -131,31 +150,32 @@ public class FlatHelpButtonIcon
|
|||||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||||
|
|
||||||
// paint question mark
|
// paint question mark
|
||||||
Path2D q = new Path2D.Float();
|
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||||
q.moveTo( 11, 5 );
|
q.moveTo( 8,8.5 );
|
||||||
q.curveTo( 8.8,5, 7,6.8, 7,9 );
|
q.curveTo( 8.25,7, 9.66585007,6, 11,6 );
|
||||||
q.lineTo( 9, 9 );
|
q.curveTo( 12.5,6, 14,7, 14,8.5 );
|
||||||
q.curveTo( 9,7.9, 9.9,7, 11,7 );
|
q.curveTo( 14,10.5, 11,11, 11,13 );
|
||||||
q.curveTo( 12.1,7, 13,7.9, 13,9 );
|
|
||||||
q.curveTo( 13,11, 10,10.75, 10,14 );
|
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
q.lineTo( 12, 14 );
|
g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
q.curveTo( 12,11.75, 15,11.5, 15,9 );
|
|
||||||
q.curveTo( 15,6.8, 13.2,5, 11,5 );
|
|
||||||
q.closePath();
|
|
||||||
|
|
||||||
g2.translate( focusWidth, focusWidth );
|
g2.translate( focusWidth, focusWidth );
|
||||||
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
||||||
g2.fill( q );
|
g2.draw( q );
|
||||||
g2.fillRect( 10, 15, 2, 2 );
|
g2.fill( new Ellipse2D.Float( 9.8f, 14.8f, 2.4f, 2.4f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIconWidth() {
|
public int getIconWidth() {
|
||||||
return scale( iconSize );
|
return scale( iconSize() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIconHeight() {
|
public int getIconHeight() {
|
||||||
return scale( iconSize );
|
return scale( iconSize() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int iconSize() {
|
||||||
|
return 22 + (focusWidth * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.awt.BasicStroke;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
@@ -58,9 +57,11 @@ public class FlatInternalFrameCloseIcon
|
|||||||
float my = height / 2;
|
float my = height / 2;
|
||||||
float r = 3.25f;
|
float r = 3.25f;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
path.moveTo( mx - r, my - r );
|
||||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
path.lineTo( mx + r, my + r );
|
||||||
|
path.moveTo( mx - r, my + r );
|
||||||
|
path.lineTo( mx + r, my - r );
|
||||||
g.setStroke( new BasicStroke( 1f ) );
|
g.setStroke( new BasicStroke( 1f ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "arrow" icon for {@link javax.swing.JMenu}.
|
* "arrow" icon for {@link javax.swing.JMenu}.
|
||||||
@@ -39,22 +42,37 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatMenuArrowIcon
|
public class FlatMenuArrowIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
@Styleable protected String arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
protected final Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" );
|
@Styleable protected Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" );
|
||||||
protected final Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" );
|
@Styleable protected Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" );
|
||||||
protected final Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
@Styleable protected Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
||||||
|
|
||||||
public FlatMenuArrowIcon() {
|
public FlatMenuArrowIcon() {
|
||||||
super( 6, 10, null );
|
super( 6, 10, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
if( !c.getComponentOrientation().isLeftToRight() )
|
if( c != null && !c.getComponentOrientation().isLeftToRight() )
|
||||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||||
|
|
||||||
g.setColor( getArrowColor( c ) );
|
g.setColor( getArrowColor( c ) );
|
||||||
if( chevron ) {
|
if( FlatUIUtils.isChevron( arrowType ) ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 1,9 );
|
Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 1,9 );
|
||||||
g.setStroke( new BasicStroke( 1f ) );
|
g.setStroke( new BasicStroke( 1f ) );
|
||||||
@@ -69,7 +87,7 @@ public class FlatMenuArrowIcon
|
|||||||
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
||||||
return selectionForeground;
|
return selectionForeground;
|
||||||
|
|
||||||
return c.isEnabled() ? arrowColor : disabledArrowColor;
|
return c == null || c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isUnderlineSelection() {
|
protected boolean isUnderlineSelection() {
|
||||||
|
|||||||
@@ -21,14 +21,16 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "arrow" icon for {@link javax.swing.JMenuItem}.
|
* "arrow" icon for {@link javax.swing.JMenuItem}, {@link javax.swing.JCheckBoxMenuItem}
|
||||||
|
* and {@link javax.swing.JRadioButtonMenuItem}.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatMenuItemArrowIcon
|
public class FlatMenuItemArrowIcon
|
||||||
extends FlatMenuArrowIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatMenuItemArrowIcon() {
|
public FlatMenuItemArrowIcon() {
|
||||||
|
super( 6, 10, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Error" icon for {@link javax.swing.JOptionPane}.
|
* "Error" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneErrorIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
||||||
<rect width="4" height="11" x="14" y="7" fill="#FFF"/>
|
<rect width="4" height="12" x="14" y="7" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneErrorIcon
|
|||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 11 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 7, 4, 12, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Information" icon for {@link javax.swing.JOptionPane}.
|
* "Information" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneInformationIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||||
<rect width="4" height="11" x="14" y="14" fill="#FFF"/>
|
<rect width="4" height="12" x="14" y="13" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="7" fill="#FFF"/>
|
<circle cx="16" cy="9" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneInformationIcon
|
|||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 14, 4, 11 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 13, 4, 12, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 7, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Question" icon for {@link javax.swing.JOptionPane}.
|
* "Question" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneQuestionIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||||
<rect width="4" height="4" x="14" y="22" fill="#FFF"/>
|
<circle cx="16" cy="24" r="1.7" fill="#FFF"/>
|
||||||
<path fill="#FFF" d="M14,20 C14,20 18,20 18,20 C18,16 23,16 23,12 C23,8 20,6 16,6 C12,6 9,8 9,12 C9,12 13,12 13,12 C13,10 14,9 16,9 C18,9 19,10 19,12 C19,15 14,15 14,20 Z"/>
|
<path stroke="#FFF" stroke-linecap="round" stroke-width="3" d="M11.5,11.75 C11.75,9.5 13.75,8 16,8 C18.25,8 20.5,9.5 20.5,11.75 C20.5,14.75 16,15.5 16,19"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -53,21 +53,17 @@ public class FlatOptionPaneQuestionIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D q = new Path2D.Float();
|
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||||
q.moveTo( 14, 20 );
|
q.moveTo( 11.5,11.75 );
|
||||||
q.lineTo( 18, 20 );
|
q.curveTo( 11.75,9.5, 13.75,8, 16,8 );
|
||||||
q.curveTo( 18, 16, 23, 16, 23, 12 );
|
q.curveTo( 18.25,8, 20.5,9.5, 20.5,11.75 );
|
||||||
q.curveTo( 23, 8, 20, 6, 16, 6 );
|
q.curveTo( 20.5,14.75, 16,15.5, 16,19 );
|
||||||
q.curveTo( 12, 6, 9, 8, 9, 12 );
|
|
||||||
q.curveTo( 9, 12, 13, 12, 13, 12 );
|
BasicStroke stroke = new BasicStroke( 3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER );
|
||||||
q.curveTo( 13, 10, 14, 9, 16, 9 );
|
|
||||||
q.curveTo( 18, 9, 19, 10, 19, 12 );
|
|
||||||
q.curveTo( 19, 15, 14, 15, 14, 20 );
|
|
||||||
q.closePath();
|
|
||||||
|
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 22, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14.3f, 22.3f, 3.4f, 3.4f ), false );
|
||||||
inside.append( q, false );
|
inside.append( stroke.createStrokedShape( q ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,23 +40,24 @@ public class FlatOptionPaneWarningIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#EDA200" points="16 2 31 28 1 28"/>
|
<path fill="#EDA200" d="M17.7364863,3.038851 L30.2901269,25.0077221 C30.8381469,25.966757 30.5049534,27.1884663 29.5459185,27.7364863 C29.2437231,27.9091694 28.9016945,28 28.5536406,28 L3.44635936,28 C2.34178986,28 1.44635936,27.1045695 1.44635936,26 C1.44635936,25.6519461 1.53718999,25.3099175 1.70987307,25.0077221 L14.2635137,3.038851 C14.8115337,2.0798161 16.033243,1.74662265 16.9922779,2.29464259 C17.3023404,2.47182119 17.5593077,2.72878844 17.7364863,3.038851 Z"/>
|
||||||
<rect width="4" height="8" x="14" y="10" fill="#FFF"/>
|
<rect width="4" height="11" x="14" y="8" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createOutside() {
|
protected Shape createOutside() {
|
||||||
return FlatUIUtils.createPath( 16,2, 31,28, 1,28 );
|
return FlatUIUtils.createRoundTrianglePath( 16,0, 32,28, 0,28, 4 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 10, 4, 8 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 8, 4, 11, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,38 +19,51 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon for {@link javax.swing.JRadioButton}.
|
* Icon for {@link javax.swing.JRadioButton}.
|
||||||
*
|
* <p>
|
||||||
* Note: If Component.focusWidth is greater than zero, then the outline focus border
|
* <strong>Note</strong>:
|
||||||
|
* If Component.focusWidth is greater than zero, then the outer focus border
|
||||||
* is painted outside of the icon bounds. Make sure that the radiobutton
|
* is painted outside of the icon bounds. Make sure that the radiobutton
|
||||||
* has margins, which are equal or greater than focusWidth.
|
* has margins, which are equal or greater than focusWidth.
|
||||||
*
|
*
|
||||||
* @uiDefault RadioButton.icon.centerDiameter int
|
* @uiDefault RadioButton.icon.style String optional; "outlined"/null (default) or "filled"
|
||||||
|
* @uiDefault RadioButton.icon.centerDiameter int or float
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatRadioButtonIcon
|
public class FlatRadioButtonIcon
|
||||||
extends FlatCheckBoxIcon
|
extends FlatCheckBoxIcon
|
||||||
{
|
{
|
||||||
protected final int centerDiameter = getUIInt( "RadioButton.icon.centerDiameter", 8, style );
|
@Styleable protected float centerDiameter = getUIFloat( "RadioButton.icon.centerDiameter", 8, style );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
protected String getPropertyPrefix() {
|
||||||
// the outline focus border is painted outside of the icon
|
return "RadioButton.";
|
||||||
int wh = ICON_SIZE + (focusWidth * 2);
|
|
||||||
g.fillOval( -focusWidth, -focusWidth, wh, wh );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBorder( Component c, Graphics2D g ) {
|
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||||
|
// the outer focus border is painted outside of the icon
|
||||||
|
float wh = ICON_SIZE + (focusWidth * 2);
|
||||||
|
g.fill( new Ellipse2D.Float( -focusWidth, -focusWidth, wh, wh ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintBorder( Component c, Graphics2D g, float borderWidth ) {
|
||||||
|
if( borderWidth == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
g.fillOval( 0, 0, 15, 15 );
|
g.fillOval( 0, 0, 15, 15 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
protected void paintBackground( Component c, Graphics2D g, float borderWidth ) {
|
||||||
g.fillOval( 1, 1, 13, 13 );
|
float xy = borderWidth;
|
||||||
|
float wh = 15 - (borderWidth * 2);
|
||||||
|
g.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Area;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "eye" icon for {@link javax.swing.JPasswordField}.
|
||||||
|
*
|
||||||
|
* @uiDefault PasswordField.revealIconColor Color
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public class FlatRevealIcon
|
||||||
|
extends FlatAbstractIcon
|
||||||
|
{
|
||||||
|
public FlatRevealIcon() {
|
||||||
|
super( 16, 16, UIManager.getColor( "PasswordField.revealIconColor" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( new Ellipse2D.Float( 5.15f, 6.15f, 5.7f, 5.7f ), false );
|
||||||
|
path.append( new Ellipse2D.Float( 6, 7, 4, 4 ), false );
|
||||||
|
g.fill( path );
|
||||||
|
|
||||||
|
Path2D path2 = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path2.append( new Ellipse2D.Float( 2.15f, 4.15f, 11.7f, 11.7f ), false );
|
||||||
|
path2.append( new Ellipse2D.Float( 3, 5, 10, 10 ), false );
|
||||||
|
Area area = new Area( path2 );
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( 0, 9.5f, 16, 16 ) ) );
|
||||||
|
g.fill( area );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,8 +21,11 @@ import java.awt.Component;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Area;
|
import java.awt.geom.Area;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,12 +41,36 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatSearchIcon
|
public class FlatSearchIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected Color searchIconColor = UIManager.getColor( "SearchField.searchIconColor" );
|
@Styleable protected Color searchIconColor = UIManager.getColor( "SearchField.searchIconColor" );
|
||||||
protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" );
|
@Styleable protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" );
|
||||||
protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
||||||
|
|
||||||
|
private final boolean ignoreButtonState;
|
||||||
|
private Area area;
|
||||||
|
|
||||||
public FlatSearchIcon() {
|
public FlatSearchIcon() {
|
||||||
|
this( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public FlatSearchIcon( boolean ignoreButtonState ) {
|
||||||
super( 16, 16, null );
|
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
|
@Override
|
||||||
@@ -57,13 +84,17 @@ public class FlatSearchIcon
|
|||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.setColor( FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
g.setColor( ignoreButtonState
|
||||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
? searchIconColor
|
||||||
|
: FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||||
|
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||||
|
|
||||||
// paint magnifier
|
// paint magnifier
|
||||||
Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
if( area == null ) {
|
||||||
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) );
|
area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
||||||
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) );
|
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 );
|
g.fill( area );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ public class FlatSearchWithHistoryIcon
|
|||||||
extends FlatSearchIcon
|
extends FlatSearchIcon
|
||||||
{
|
{
|
||||||
public FlatSearchWithHistoryIcon() {
|
public FlatSearchWithHistoryIcon() {
|
||||||
|
this( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public FlatSearchWithHistoryIcon( boolean ignoreButtonState ) {
|
||||||
|
super( ignoreButtonState );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,44 +49,61 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTabbedPaneCloseIcon
|
public class FlatTabbedPaneCloseIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final Dimension size = UIManager.getDimension( "TabbedPane.closeSize" );
|
@Styleable protected Dimension closeSize = UIManager.getDimension( "TabbedPane.closeSize" );
|
||||||
protected final int arc = UIManager.getInt( "TabbedPane.closeArc" );
|
@Styleable protected int closeArc = UIManager.getInt( "TabbedPane.closeArc" );
|
||||||
protected final float crossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
@Styleable protected float closeCrossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
||||||
protected final float crossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", crossPlainSize );
|
@Styleable protected float closeCrossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", closeCrossPlainSize );
|
||||||
protected final float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
@Styleable protected float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
||||||
protected final Color background = UIManager.getColor( "TabbedPane.closeBackground" );
|
@Styleable protected Color closeBackground = UIManager.getColor( "TabbedPane.closeBackground" );
|
||||||
protected final Color foreground = UIManager.getColor( "TabbedPane.closeForeground" );
|
@Styleable protected Color closeForeground = UIManager.getColor( "TabbedPane.closeForeground" );
|
||||||
protected final Color hoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
@Styleable protected Color closeHoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
||||||
protected final Color hoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
@Styleable protected Color closeHoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
||||||
protected final Color pressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
@Styleable protected Color closePressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
||||||
protected final Color pressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
@Styleable protected Color closePressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
||||||
|
|
||||||
public FlatTabbedPaneCloseIcon() {
|
public FlatTabbedPaneCloseIcon() {
|
||||||
super( 16, 16, null );
|
super( 16, 16, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
// paint background
|
// paint background
|
||||||
Color bg = FlatButtonUI.buttonStateColor( c, background, null, null, hoverBackground, pressedBackground );
|
Color bg = FlatButtonUI.buttonStateColor( c, closeBackground, null, null, closeHoverBackground, closePressedBackground );
|
||||||
if( bg != null ) {
|
if( bg != null ) {
|
||||||
g.setColor( FlatUIUtils.deriveColor( bg, c.getBackground() ) );
|
g.setColor( FlatUIUtils.deriveColor( bg, c.getBackground() ) );
|
||||||
g.fillRoundRect( (width - size.width) / 2, (height - size.height) / 2,
|
g.fillRoundRect( (width - closeSize.width) / 2, (height - closeSize.height) / 2,
|
||||||
size.width, size.height, arc, arc );
|
closeSize.width, closeSize.height, closeArc, closeArc );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set cross color
|
// set cross color
|
||||||
Color fg = FlatButtonUI.buttonStateColor( c, foreground, null, null, hoverForeground, pressedForeground );
|
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
||||||
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
||||||
|
|
||||||
float mx = width / 2;
|
float mx = width / 2;
|
||||||
float my = height / 2;
|
float my = height / 2;
|
||||||
float r = ((bg != null) ? crossFilledSize : crossPlainSize) / 2;
|
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
||||||
|
|
||||||
// paint cross
|
// paint cross
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
path.moveTo( mx - r, my - r );
|
||||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
path.lineTo( mx + r, my + r );
|
||||||
|
path.moveTo( mx - r, my + r );
|
||||||
|
path.lineTo( mx + r, my - r );
|
||||||
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||||
@@ -31,18 +32,26 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTreeClosedIcon
|
public class FlatTreeClosedIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeClosedIcon() {
|
public FlatTreeClosedIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconClosedColor );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 15,4, 15,13, 1,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
if( path == null )
|
||||||
|
path = FlatFileViewDirectoryIcon.createFolderPath();
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,17 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import javax.swing.JTree;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.TreeUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatTreeUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,6 +41,7 @@ public class FlatTreeCollapsedIcon
|
|||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
private final boolean chevron;
|
private final boolean chevron;
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeCollapsedIcon() {
|
public FlatTreeCollapsedIcon() {
|
||||||
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
||||||
@@ -46,19 +54,54 @@ public class FlatTreeCollapsedIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
setStyleColorFromTreeUI( c, g );
|
||||||
rotate( c, g );
|
rotate( c, g );
|
||||||
|
|
||||||
|
String arrowType = getStyleFromTreeUI( c, ui -> ui.iconArrowType );
|
||||||
|
boolean chevron = (arrowType != null) ? FlatUIUtils.isChevron( arrowType ) : this.chevron;
|
||||||
|
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
g.fill( FlatUIUtils.createPath( 3,1, 3,2.5, 6,5.5, 3,8.5, 3,10, 4.5,10, 9,5.5, 4.5,1 ) );
|
g.setStroke( new BasicStroke( 1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER ) );
|
||||||
|
if( path == null )
|
||||||
|
path = FlatUIUtils.createPath( false, 3.5,1.5, 7.5,5.5, 3.5,9.5 );
|
||||||
|
g.draw( path );
|
||||||
} else {
|
} else {
|
||||||
// triangle arrow
|
// triangle arrow
|
||||||
g.fill( FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ) );
|
if( path == null )
|
||||||
|
path = FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 );
|
||||||
|
g.fill( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStyleColorFromTreeUI( Component c, Graphics2D g ) {
|
||||||
|
setStyleColorFromTreeUI( c, g, ui -> ui.iconCollapsedColor );
|
||||||
|
}
|
||||||
|
|
||||||
void rotate( Component c, Graphics2D g ) {
|
void rotate( Component c, Graphics2D g ) {
|
||||||
if( !c.getComponentOrientation().isLeftToRight() )
|
if( !c.getComponentOrientation().isLeftToRight() )
|
||||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because this icon is always shared for all trees,
|
||||||
|
* get icon specific style from FlatTreeUI.
|
||||||
|
*/
|
||||||
|
static <T> T getStyleFromTreeUI( Component c, Function<FlatTreeUI, T> f ) {
|
||||||
|
JTree tree = (c instanceof JTree)
|
||||||
|
? (JTree) c
|
||||||
|
: (JTree) SwingUtilities.getAncestorOfClass( JTree.class, c );
|
||||||
|
if( tree != null ) {
|
||||||
|
TreeUI ui = tree.getUI();
|
||||||
|
if( ui instanceof FlatTreeUI )
|
||||||
|
return f.apply( (FlatTreeUI) ui );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setStyleColorFromTreeUI( Component c, Graphics2D g, Function<FlatTreeUI, Color> f ) {
|
||||||
|
Color color = getStyleFromTreeUI( c, f );
|
||||||
|
if( color != null )
|
||||||
|
g.setColor( color );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ public class FlatTreeExpandedIcon
|
|||||||
super( UIManager.getColor( "Tree.icon.expandedColor" ) );
|
super( UIManager.getColor( "Tree.icon.expandedColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void setStyleColorFromTreeUI( Component c, Graphics2D g ) {
|
||||||
|
setStyleColorFromTreeUI( c, g, ui -> ui.iconExpandedColor );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void rotate( Component c, Graphics2D g ) {
|
void rotate( Component c, Graphics2D g ) {
|
||||||
g.rotate( Math.toRadians( 90 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 90 ), width / 2., height / 2. );
|
||||||
|
|||||||
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "leaf" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
* "leaf" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||||
@@ -37,16 +41,27 @@ public class FlatTreeLeafIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconLeafColor );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<rect width="11" height="13" x="2.5" y="1.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<line x1="5.5" x2="10.5" y1="5.5" y2="5.5" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
|
<line x1="5.5" x2="10.5" y1="8" y2="8" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
|
<line x1="5.5" x2="10.5" y1="10.5" y2="10.5" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( new RoundRectangle2D.Float( 2.5f, 1.5f, 11, 13, 3, 3 ) );
|
||||||
|
|
||||||
|
g.setColor( ColorFunctions.fade( g.getColor(), 0.6f ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 5.5f, 10.5f, 5.5f ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 8, 10.5f, 8 ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 10.5f, 10.5f, 10.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,22 +34,50 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTreeOpenIcon
|
public class FlatTreeOpenIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeOpenIcon() {
|
public FlatTreeOpenIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconOpenColor );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<path fill="none" stroke="#6E6E6E" d="M2,13.5 L4.11538462,8.42307692 C4.34828895,7.86410651 4.89444872,7.5 5.5,7.5 L14.75,7.5 C15.0261424,7.5 15.25,7.72385763 15.25,8 C15.25,8.06601301 15.2369281,8.13137261 15.2115385,8.19230769 L13.3846154,12.5769231 C13.151711,13.1358935 12.6055513,13.5 12,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L12,4.5 C12.8284271,4.5 13.5,5.17157288 13.5,6 L13.5,6.5 L13.5,6.5"/>
|
||||||
<polygon fill="#6E6E6E" points="1 2 6 2 8 4 14 4 14 6 3.5 6 1 11"/>
|
|
||||||
<polygon fill="#6E6E6E" points="4 7 16 7 13 13 1 13"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 14,4, 14,6, 3.5,6, 1,11 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 4,7, 16,7, 13,13, 1,13 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
double arc = 1.5;
|
||||||
|
double arc2 = 0.5;
|
||||||
|
path = FlatUIUtils.createPath( false,
|
||||||
|
// bottom-left of opend part
|
||||||
|
2,13.5,
|
||||||
|
// top-left of opend part
|
||||||
|
FlatUIUtils.ROUNDED, 4.5,7.5, arc,
|
||||||
|
// top-right of opend 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,6 +20,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
@@ -65,8 +66,14 @@ public abstract class FlatWindowAbstractIcon
|
|||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
protected void paintBackground( Component c, Graphics2D g ) {
|
||||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||||
if( background != null ) {
|
if( background != null ) {
|
||||||
|
// disable antialiasing for background rectangle painting to avoid blury 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.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||||
g.fillRect( 0, 0, width, height );
|
g.fillRect( 0, 0, width, height );
|
||||||
|
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import java.awt.BasicStroke;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "close" icon for windows (frames and dialogs).
|
* "close" icon for windows (frames and dialogs).
|
||||||
@@ -54,11 +54,13 @@ public class FlatWindowCloseIcon
|
|||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int ix2 = ix + iwh - 1;
|
int ix2 = ix + iwh - 1;
|
||||||
int iy2 = iy + iwh - 1;
|
int iy2 = iy + iwh - 1;
|
||||||
int thickness = (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
path.moveTo( ix, iy );
|
||||||
path.append( new Line2D.Float( ix, iy2, ix2, iy ), false );
|
path.lineTo( ix2, iy2 );
|
||||||
|
path.moveTo( ix, iy2 );
|
||||||
|
path.lineTo( ix2, iy );
|
||||||
g.setStroke( new BasicStroke( thickness ) );
|
g.setStroke( new BasicStroke( thickness ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "maximize" icon for windows (frames and dialogs).
|
* "maximize" icon for windows (frames and dialogs).
|
||||||
@@ -35,8 +36,11 @@ public class FlatWindowMaximizeIcon
|
|||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (10 * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int thickness = (int) scaleFactor;
|
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.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "restore" icon for windows (frames and dialogs).
|
* "restore" icon for windows (frames and dialogs).
|
||||||
@@ -38,18 +39,33 @@ public class FlatWindowRestoreIcon
|
|||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (10 * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int thickness = (int) scaleFactor;
|
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) (8 * scaleFactor);
|
||||||
int ro2 = iwh - rwh;
|
int ro2 = iwh - rwh;
|
||||||
|
|
||||||
Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
// upper-right rectangle
|
||||||
Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
Path2D r1 = SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix + ro2, iy, rwh, rwh, thickness, arc, arcOuter, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||||
|
|
||||||
|
// lower-left rectangle
|
||||||
|
Path2D r2 = SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix, iy + ro2, rwh, rwh, thickness, arc, arc, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||||
|
|
||||||
|
// paint upper-right rectangle
|
||||||
Area area = new Area( r1 );
|
Area area = new Area( r1 );
|
||||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
if( SystemInfo.isWindows_11_orLater ) {
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( ix, (float) (iy + scaleFactor), rwh, rwh ) ) );
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( (float) (ix + scaleFactor), iy + ro2, rwh, rwh ) ) );
|
||||||
|
} else
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||||
g.fill( area );
|
g.fill( area );
|
||||||
|
|
||||||
|
// paint lower-left rectangle
|
||||||
g.fill( r2 );
|
g.fill( r2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.resources;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
||||||
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
|
* Otherwise, the compiler outputs a warning because this package is opened in module-info.java.
|
||||||
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
* Also, when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.themes;
|
||||||
|
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Flat LaF that imitates macOS dark look.
|
||||||
|
* <p>
|
||||||
|
* The UI defaults are loaded from {@code FlatMacDarkLaf.properties},
|
||||||
|
* {@code FlatDarkLaf.properties} and {@code FlatLaf.properties}.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FlatMacDarkLaf
|
||||||
|
extends FlatDarkLaf
|
||||||
|
{
|
||||||
|
public static final String NAME = "FlatLaf macOS Dark";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the application look and feel to this LaF
|
||||||
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*/
|
||||||
|
public static boolean setup() {
|
||||||
|
return setup( new FlatMacDarkLaf() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this look and feel to the set of available look and feels.
|
||||||
|
* <p>
|
||||||
|
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||||
|
* to query available LaFs and display them to the user in a combobox.
|
||||||
|
*/
|
||||||
|
public static void installLafInfo() {
|
||||||
|
installLafInfo( NAME, FlatMacDarkLaf.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "FlatLaf macOS Dark Look and Feel";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDark() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.themes;
|
||||||
|
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Flat LaF that imitates macOS light look.
|
||||||
|
* <p>
|
||||||
|
* The UI defaults are loaded from {@code FlatMacLightLaf.properties},
|
||||||
|
* {@code FlatLightLaf.properties} and {@code FlatLaf.properties}.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FlatMacLightLaf
|
||||||
|
extends FlatLightLaf
|
||||||
|
{
|
||||||
|
public static final String NAME = "FlatLaf macOS Light";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the application look and feel to this LaF
|
||||||
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*/
|
||||||
|
public static boolean setup() {
|
||||||
|
return setup( new FlatMacLightLaf() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this look and feel to the set of available look and feels.
|
||||||
|
* <p>
|
||||||
|
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||||
|
* to query available LaFs and display them to the user in a combobox.
|
||||||
|
*/
|
||||||
|
public static void installLafInfo() {
|
||||||
|
installLafInfo( NAME, FlatMacLightLaf.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "FlatLaf macOS Light Look and Feel";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDark() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicArrowButton;
|
import javax.swing.plaf.basic.BasicArrowButton;
|
||||||
|
|
||||||
@@ -37,19 +38,21 @@ public class FlatArrowButton
|
|||||||
extends BasicArrowButton
|
extends BasicArrowButton
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
public static final int DEFAULT_ARROW_WIDTH = 8;
|
public static final int DEFAULT_ARROW_WIDTH = 9;
|
||||||
|
|
||||||
protected final boolean chevron;
|
protected boolean chevron;
|
||||||
protected final Color foreground;
|
protected Color foreground;
|
||||||
protected final Color disabledForeground;
|
protected Color disabledForeground;
|
||||||
protected final Color hoverForeground;
|
protected Color hoverForeground;
|
||||||
protected final Color hoverBackground;
|
protected Color hoverBackground;
|
||||||
protected final Color pressedForeground;
|
protected Color pressedForeground;
|
||||||
protected final Color pressedBackground;
|
protected Color pressedBackground;
|
||||||
|
|
||||||
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
||||||
|
private float arrowThickness = 1;
|
||||||
private float xOffset = 0;
|
private float xOffset = 0;
|
||||||
private float yOffset = 0;
|
private float yOffset = 0;
|
||||||
|
private boolean roundBorderAutoXOffset = true;
|
||||||
|
|
||||||
private boolean hover;
|
private boolean hover;
|
||||||
private boolean pressed;
|
private boolean pressed;
|
||||||
@@ -58,14 +61,8 @@ public class FlatArrowButton
|
|||||||
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
||||||
{
|
{
|
||||||
super( direction, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE );
|
super( direction, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE );
|
||||||
|
updateStyle( type, foreground, disabledForeground, hoverForeground, hoverBackground,
|
||||||
this.chevron = FlatUIUtils.isChevron( type );
|
pressedForeground, pressedBackground );
|
||||||
this.foreground = foreground;
|
|
||||||
this.disabledForeground = disabledForeground;
|
|
||||||
this.hoverForeground = hoverForeground;
|
|
||||||
this.hoverBackground = hoverBackground;
|
|
||||||
this.pressedForeground = pressedForeground;
|
|
||||||
this.pressedBackground = pressedBackground;
|
|
||||||
|
|
||||||
setOpaque( false );
|
setOpaque( false );
|
||||||
setBorder( null );
|
setBorder( null );
|
||||||
@@ -88,19 +85,36 @@ public class FlatArrowButton
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed( MouseEvent e ) {
|
public void mousePressed( MouseEvent e ) {
|
||||||
pressed = true;
|
if( SwingUtilities.isLeftMouseButton( e ) ) {
|
||||||
repaint();
|
pressed = true;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased( MouseEvent e ) {
|
public void mouseReleased( MouseEvent e ) {
|
||||||
pressed = false;
|
if( SwingUtilities.isLeftMouseButton( e ) ) {
|
||||||
repaint();
|
pressed = false;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public void updateStyle( String type, Color foreground, Color disabledForeground,
|
||||||
|
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
||||||
|
{
|
||||||
|
this.chevron = FlatUIUtils.isChevron( type );
|
||||||
|
this.foreground = foreground;
|
||||||
|
this.disabledForeground = disabledForeground;
|
||||||
|
this.hoverForeground = hoverForeground;
|
||||||
|
this.hoverBackground = hoverBackground;
|
||||||
|
this.pressedForeground = pressedForeground;
|
||||||
|
this.pressedBackground = pressedBackground;
|
||||||
|
}
|
||||||
|
|
||||||
public int getArrowWidth() {
|
public int getArrowWidth() {
|
||||||
return arrowWidth;
|
return arrowWidth;
|
||||||
}
|
}
|
||||||
@@ -109,6 +123,16 @@ public class FlatArrowButton
|
|||||||
this.arrowWidth = arrowWidth;
|
this.arrowWidth = arrowWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public float getArrowThickness() {
|
||||||
|
return arrowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public void setArrowThickness( float arrowThickness ) {
|
||||||
|
this.arrowThickness = arrowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isHover() {
|
protected boolean isHover() {
|
||||||
return hover;
|
return hover;
|
||||||
}
|
}
|
||||||
@@ -133,6 +157,16 @@ public class FlatArrowButton
|
|||||||
this.yOffset = yOffset;
|
this.yOffset = yOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public boolean isRoundBorderAutoXOffset() {
|
||||||
|
return roundBorderAutoXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public void setRoundBorderAutoXOffset( boolean roundBorderAutoXOffset ) {
|
||||||
|
this.roundBorderAutoXOffset = roundBorderAutoXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
protected Color deriveBackground( Color background ) {
|
protected Color deriveBackground( Color background ) {
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
@@ -196,14 +230,17 @@ public class FlatArrowButton
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintArrow( Graphics2D g ) {
|
protected void paintArrow( Graphics2D g ) {
|
||||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
// move arrow for round borders
|
// move arrow for round borders
|
||||||
Container parent = getParent();
|
if( isRoundBorderAutoXOffset() ) {
|
||||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
Container parent = getParent();
|
||||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||||
|
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||||
|
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||||
|
}
|
||||||
|
|
||||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, arrowWidth, xOffset, yOffset );
|
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
@@ -31,20 +32,25 @@ import javax.swing.JViewport;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.basic.BasicBorders;
|
import javax.swing.plaf.basic.BasicBorders;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
import com.formdev.flatlaf.util.DerivedColor;
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for various components (e.g. {@link javax.swing.JTextField}).
|
* Border for various components (e.g. {@link javax.swing.JTextField}).
|
||||||
*
|
* <p>
|
||||||
* There is empty space around the component border, if Component.focusWidth is greater than zero,
|
* There is empty space around the component border, if Component.focusWidth is greater than zero,
|
||||||
* which is used to paint outer focus border.
|
* which is used to paint outer focus border.
|
||||||
*
|
* <p>
|
||||||
* Because there is empty space (if outer focus border is not painted),
|
* Because there is empty space (if outer focus border is not painted),
|
||||||
* UI delegates that use this border (or subclasses) must invoke
|
* UI delegates that use this border (or subclasses) must invoke
|
||||||
* {@link FlatUIUtils#paintParentBackground} to paint the empty space correctly.
|
* {@link FlatUIUtils#paintParentBackground} to fill the empty space correctly.
|
||||||
*
|
*
|
||||||
* @uiDefault Component.focusWidth int
|
* @uiDefault Component.focusWidth int
|
||||||
* @uiDefault Component.innerFocusWidth int or float
|
* @uiDefault Component.innerFocusWidth int or float
|
||||||
|
* @uiDefault Component.innerOutlineWidth int or float
|
||||||
|
* @uiDefault Component.borderWidth int or float
|
||||||
|
*
|
||||||
* @uiDefault Component.focusColor Color
|
* @uiDefault Component.focusColor Color
|
||||||
* @uiDefault Component.borderColor Color
|
* @uiDefault Component.borderColor Color
|
||||||
* @uiDefault Component.disabledBorderColor Color
|
* @uiDefault Component.disabledBorderColor Color
|
||||||
@@ -60,20 +66,46 @@ import com.formdev.flatlaf.util.DerivedColor;
|
|||||||
*/
|
*/
|
||||||
public class FlatBorder
|
public class FlatBorder
|
||||||
extends BasicBorders.MarginBorder
|
extends BasicBorders.MarginBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
@Styleable protected int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
@Styleable protected float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
||||||
protected final float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
@Styleable protected float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
||||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
/** @since 2 */ @Styleable protected float borderWidth = FlatUIUtils.getUIFloat( "Component.borderWidth", 1 );
|
||||||
protected final Color borderColor = UIManager.getColor( "Component.borderColor" );
|
|
||||||
protected final Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
|
||||||
protected final Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
|
||||||
|
|
||||||
protected final Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
@Styleable protected Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||||
protected final Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
@Styleable protected Color borderColor = UIManager.getColor( "Component.borderColor" );
|
||||||
protected final Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
@Styleable protected Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
||||||
protected final Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
@Styleable protected Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
||||||
protected final Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
|
||||||
|
@Styleable(dot=true) protected Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
||||||
|
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||||
|
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||||
|
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||||
|
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||||
|
|
||||||
|
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||||
|
/** @since 2 */ @Styleable protected String outline;
|
||||||
|
/** @since 2 */ @Styleable protected Color outlineColor;
|
||||||
|
/** @since 2 */ @Styleable protected Color outlineFocusedColor;
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
@@ -82,9 +114,11 @@ public class FlatBorder
|
|||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
float focusWidth = scale( (float) getFocusWidth( c ) );
|
float focusWidth = scale( (float) getFocusWidth( c ) );
|
||||||
float borderWidth = scale( (float) getBorderWidth( c ) );
|
float focusInnerWidth = 0;
|
||||||
|
float borderWidth = scale( getBorderWidth( c ) );
|
||||||
float arc = scale( (float) getArc( c ) );
|
float arc = scale( (float) getArc( c ) );
|
||||||
Color outlineColor = getOutlineColor( c );
|
Color outlineColor = getOutlineColor( c );
|
||||||
|
Color focusColor = null;
|
||||||
|
|
||||||
// paint outer border
|
// paint outer border
|
||||||
if( outlineColor != null || isFocused( c ) ) {
|
if( outlineColor != null || isFocused( c ) ) {
|
||||||
@@ -93,15 +127,16 @@ public class FlatBorder
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
if( focusWidth > 0 || innerWidth > 0 ) {
|
if( focusWidth > 0 || innerWidth > 0 ) {
|
||||||
g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) );
|
focusColor = (outlineColor != null) ? outlineColor : getFocusColor( c );
|
||||||
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height,
|
focusInnerWidth = borderWidth + scale( innerWidth );
|
||||||
focusWidth, borderWidth + scale( innerWidth ), arc );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint border
|
// paint border
|
||||||
g2.setPaint( (outlineColor != null) ? outlineColor : getBorderColor( c ) );
|
Paint borderColor = (outlineColor != null) ? outlineColor : getBorderColor( c );
|
||||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, focusWidth, borderWidth, arc );
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||||
|
focusWidth, 1, focusInnerWidth, borderWidth, arc,
|
||||||
|
focusColor, borderColor, null );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
@@ -116,6 +151,17 @@ public class FlatBorder
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
Object outline = ((JComponent)c).getClientProperty( FlatClientProperties.OUTLINE );
|
Object outline = ((JComponent)c).getClientProperty( FlatClientProperties.OUTLINE );
|
||||||
|
if( outline == null )
|
||||||
|
outline = this.outline;
|
||||||
|
if( outline == null ) {
|
||||||
|
if( outlineColor != null && outlineFocusedColor != null )
|
||||||
|
outline = new Color[] { outlineFocusedColor, outlineColor };
|
||||||
|
else if( outlineColor != null )
|
||||||
|
outline = outlineColor;
|
||||||
|
else if( outlineFocusedColor != null )
|
||||||
|
outline = outlineFocusedColor;
|
||||||
|
}
|
||||||
|
|
||||||
if( outline instanceof String ) {
|
if( outline instanceof String ) {
|
||||||
switch( (String) outline ) {
|
switch( (String) outline ) {
|
||||||
case FlatClientProperties.OUTLINE_ERROR:
|
case FlatClientProperties.OUTLINE_ERROR:
|
||||||
@@ -228,8 +274,8 @@ public class FlatBorder
|
|||||||
* Returns the (unscaled) line thickness used to paint the border.
|
* Returns the (unscaled) line thickness used to paint the border.
|
||||||
* This may be different to {@link #getLineWidth}.
|
* This may be different to {@link #getLineWidth}.
|
||||||
*/
|
*/
|
||||||
protected int getBorderWidth( Component c ) {
|
protected float getBorderWidth( Component c ) {
|
||||||
return getLineWidth( c );
|
return borderWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,57 +26,66 @@ import java.awt.Paint;
|
|||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for {@link javax.swing.JButton}.
|
* Border for {@link javax.swing.JButton}.
|
||||||
*
|
*
|
||||||
|
* @uiDefault Button.arc int
|
||||||
|
* @uiDefault Button.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
||||||
|
* @uiDefault Button.borderWidth int or float optional; defaults to Component.borderWidth
|
||||||
|
*
|
||||||
* @uiDefault Button.borderColor Color
|
* @uiDefault Button.borderColor Color
|
||||||
* @uiDefault Button.startBorderColor Color optional; if set, a gradient paint is used and Button.borderColor is ignored
|
* @uiDefault Button.startBorderColor Color optional; if set, a gradient paint is used and Button.borderColor is ignored
|
||||||
* @uiDefault Button.endBorderColor Color optional; if set, a gradient paint is used
|
* @uiDefault Button.endBorderColor Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.disabledBorderColor Color
|
* @uiDefault Button.disabledBorderColor Color
|
||||||
* @uiDefault Button.focusedBorderColor Color
|
* @uiDefault Button.focusedBorderColor Color
|
||||||
* @uiDefault Button.hoverBorderColor Color optional
|
* @uiDefault Button.hoverBorderColor Color optional
|
||||||
|
*
|
||||||
|
* @uiDefault Button.default.borderWidth int or float
|
||||||
* @uiDefault Button.default.borderColor Color
|
* @uiDefault Button.default.borderColor Color
|
||||||
* @uiDefault Button.default.startBorderColor Color optional; if set, a gradient paint is used and Button.default.borderColor is ignored
|
* @uiDefault Button.default.startBorderColor Color optional; if set, a gradient paint is used and Button.default.borderColor is ignored
|
||||||
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.default.hoverBorderColor Color optional
|
|
||||||
* @uiDefault Button.default.focusedBorderColor Color
|
* @uiDefault Button.default.focusedBorderColor Color
|
||||||
* @uiDefault Button.default.focusColor Color
|
* @uiDefault Button.default.focusColor Color
|
||||||
|
* @uiDefault Button.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.focusColor Color optional; defaults to Component.focusColor
|
||||||
* @uiDefault Button.borderWidth int
|
|
||||||
* @uiDefault Button.default.borderWidth int
|
|
||||||
* @uiDefault Button.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
|
||||||
* @uiDefault Button.toolbar.margin Insets
|
* @uiDefault Button.toolbar.margin Insets
|
||||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||||
* @uiDefault Button.toolbar.focusWidth int or float optional; default is 1
|
|
||||||
* @uiDefault Button.arc int
|
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatButtonBorder
|
public class FlatButtonBorder
|
||||||
extends FlatBorder
|
extends FlatBorder
|
||||||
{
|
{
|
||||||
protected final Color borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
|
@Styleable protected int arc = UIManager.getInt( "Button.arc" );
|
||||||
protected final Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
|
||||||
protected final Color disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
|
protected Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
||||||
protected final Color focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
|
@Styleable protected Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
||||||
protected final Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
|
||||||
protected final Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
@Styleable(dot=true) protected float defaultBorderWidth = FlatUIUtils.getUIFloat( "Button.default.borderWidth", 1 );
|
||||||
protected final Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
|
@Styleable(dot=true) protected Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
||||||
protected final Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
protected Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
|
||||||
protected final Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
@Styleable(dot=true) protected Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
||||||
protected final Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
@Styleable(dot=true) protected Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
||||||
/** @since 1.4 */
|
@Styleable(dot=true) protected Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
||||||
protected final Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" );
|
|
||||||
protected final int borderWidth = UIManager.getInt( "Button.borderWidth" );
|
/** @since 1.4 */ @Styleable(dot=true) protected float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f );
|
||||||
protected final int defaultBorderWidth = UIManager.getInt( "Button.default.borderWidth" );
|
/** @since 1.4 */ @Styleable(dot=true) protected Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" );
|
||||||
protected final float buttonInnerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth );
|
@Styleable(dot=true) protected Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
||||||
protected final Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
@Styleable(dot=true) protected Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||||
protected final Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
|
||||||
/** @since 1.4 */
|
public FlatButtonBorder() {
|
||||||
protected final float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f );
|
innerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth );
|
||||||
protected final int arc = UIManager.getInt( "Button.arc" );
|
borderWidth = FlatUIUtils.getUIFloat( "Button.borderWidth", borderWidth );
|
||||||
|
|
||||||
|
borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
|
||||||
|
disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
|
||||||
|
focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
@@ -90,9 +99,7 @@ public class FlatButtonBorder
|
|||||||
paintToolBarFocus( c, g, x, y, width, height );
|
paintToolBarFocus( c, g, x, y, width, height );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @since 1.4 */
|
||||||
* @since 1.4
|
|
||||||
*/
|
|
||||||
protected void paintToolBarFocus( Component c, Graphics g, int x, int y, int width, int height ) {
|
protected void paintToolBarFocus( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
Graphics2D g2 = (Graphics2D) g.create();
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
try {
|
try {
|
||||||
@@ -108,9 +115,10 @@ public class FlatButtonBorder
|
|||||||
width -= spacing.left + spacing.right;
|
width -= spacing.left + spacing.right;
|
||||||
height -= spacing.top + spacing.bottom;
|
height -= spacing.top + spacing.bottom;
|
||||||
|
|
||||||
g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) );
|
Color color = (outlineColor != null) ? outlineColor : getFocusColor( c );
|
||||||
// not using paintComponentOuterBorder() here because its round edges look too "thick"
|
// not using focus border painting of paintOutlinedComponent() here
|
||||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0, focusWidth, arc );
|
// because its round edges look too "thick"
|
||||||
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height, 0, 0, 0, focusWidth, arc, null, color, null );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
@@ -151,7 +159,7 @@ public class FlatButtonBorder
|
|||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
if( FlatButtonUI.isToolBarButton( c ) ) {
|
if( FlatButtonUI.isToolBarButton( c ) ) {
|
||||||
// In toolbars, use button margin only if explicitly set.
|
// In toolbars, use button margin only if explicitly set.
|
||||||
// Otherwise use toolbar margin specified in UI defaults.
|
// Otherwise, use toolbar margin specified in UI defaults.
|
||||||
Insets margin = (c instanceof AbstractButton)
|
Insets margin = (c instanceof AbstractButton)
|
||||||
? ((AbstractButton)c).getMargin()
|
? ((AbstractButton)c).getMargin()
|
||||||
: null;
|
: null;
|
||||||
@@ -175,12 +183,7 @@ public class FlatButtonBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getInnerFocusWidth( Component c ) {
|
protected float getBorderWidth( Component c ) {
|
||||||
return buttonInnerFocusWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getBorderWidth( Component c ) {
|
|
||||||
return FlatButtonUI.isDefaultButton( c ) ? defaultBorderWidth : borderWidth;
|
return FlatButtonUI.isDefaultButton( c ) ? defaultBorderWidth : borderWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
|||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
@@ -30,21 +31,35 @@ import java.awt.Insets;
|
|||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.ButtonModel;
|
import javax.swing.ButtonModel;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JTextField;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.plaf.ButtonUI;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.ToolBarUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicButtonListener;
|
import javax.swing.plaf.basic.BasicButtonListener;
|
||||||
import javax.swing.plaf.basic.BasicButtonUI;
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,20 +81,27 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
||||||
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.focusedBackground Color optional
|
* @uiDefault Button.focusedBackground Color optional
|
||||||
|
* @uiDefault Button.focusedForeground Color optional
|
||||||
* @uiDefault Button.hoverBackground Color optional
|
* @uiDefault Button.hoverBackground Color optional
|
||||||
|
* @uiDefault Button.hoverForeground Color optional
|
||||||
* @uiDefault Button.pressedBackground Color optional
|
* @uiDefault Button.pressedBackground Color optional
|
||||||
|
* @uiDefault Button.pressedForeground Color optional
|
||||||
* @uiDefault Button.selectedBackground Color
|
* @uiDefault Button.selectedBackground Color
|
||||||
* @uiDefault Button.selectedForeground Color
|
* @uiDefault Button.selectedForeground Color
|
||||||
* @uiDefault Button.disabledBackground Color optional
|
* @uiDefault Button.disabledBackground Color optional
|
||||||
* @uiDefault Button.disabledText Color
|
* @uiDefault Button.disabledText Color
|
||||||
* @uiDefault Button.disabledSelectedBackground Color
|
* @uiDefault Button.disabledSelectedBackground Color
|
||||||
|
* @uiDefault Button.disabledSelectedForeground Color optional
|
||||||
* @uiDefault Button.default.background Color
|
* @uiDefault Button.default.background Color
|
||||||
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
|
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
|
||||||
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.default.foreground Color
|
* @uiDefault Button.default.foreground Color
|
||||||
* @uiDefault Button.default.focusedBackground Color optional
|
* @uiDefault Button.default.focusedBackground Color optional
|
||||||
|
* @uiDefault Button.default.focusedForeground Color optional
|
||||||
* @uiDefault Button.default.hoverBackground Color optional
|
* @uiDefault Button.default.hoverBackground Color optional
|
||||||
|
* @uiDefault Button.default.hoverForeground Color optional
|
||||||
* @uiDefault Button.default.pressedBackground Color optional
|
* @uiDefault Button.default.pressedBackground Color optional
|
||||||
|
* @uiDefault Button.default.pressedForeground Color optional
|
||||||
* @uiDefault Button.default.boldText boolean
|
* @uiDefault Button.default.boldText boolean
|
||||||
* @uiDefault Button.paintShadow boolean default is false
|
* @uiDefault Button.paintShadow boolean default is false
|
||||||
* @uiDefault Button.shadowWidth int default is 2
|
* @uiDefault Button.shadowWidth int default is 2
|
||||||
@@ -87,15 +109,21 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.default.shadowColor Color optional
|
* @uiDefault Button.default.shadowColor Color optional
|
||||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||||
* @uiDefault Button.toolbar.hoverBackground Color
|
* @uiDefault Button.toolbar.hoverBackground Color
|
||||||
|
* @uiDefault Button.toolbar.hoverForeground Color optional
|
||||||
* @uiDefault Button.toolbar.pressedBackground Color
|
* @uiDefault Button.toolbar.pressedBackground Color
|
||||||
|
* @uiDefault Button.toolbar.pressedForeground Color optional
|
||||||
* @uiDefault Button.toolbar.selectedBackground Color
|
* @uiDefault Button.toolbar.selectedBackground Color
|
||||||
|
* @uiDefault Button.toolbar.selectedForeground Color optional
|
||||||
|
* @uiDefault Button.toolbar.disabledSelectedBackground Color optional
|
||||||
|
* @uiDefault Button.toolbar.disabledSelectedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatButtonUI
|
public class FlatButtonUI
|
||||||
extends BasicButtonUI
|
extends BasicButtonUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected int iconTextGap;
|
protected int iconTextGap;
|
||||||
|
|
||||||
protected Color background;
|
protected Color background;
|
||||||
@@ -103,39 +131,81 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
protected Color startBackground;
|
protected Color startBackground;
|
||||||
protected Color endBackground;
|
protected Color endBackground;
|
||||||
protected Color focusedBackground;
|
@Styleable protected Color focusedBackground;
|
||||||
protected Color hoverBackground;
|
/** @since 2.3 */ @Styleable protected Color focusedForeground;
|
||||||
protected Color pressedBackground;
|
@Styleable protected Color hoverBackground;
|
||||||
protected Color selectedBackground;
|
/** @since 2.3 */ @Styleable protected Color hoverForeground;
|
||||||
protected Color selectedForeground;
|
@Styleable protected Color pressedBackground;
|
||||||
protected Color disabledBackground;
|
/** @since 2.3 */ @Styleable protected Color pressedForeground;
|
||||||
protected Color disabledText;
|
@Styleable protected Color selectedBackground;
|
||||||
protected Color disabledSelectedBackground;
|
@Styleable protected Color selectedForeground;
|
||||||
|
@Styleable protected Color disabledBackground;
|
||||||
|
@Styleable protected Color disabledText;
|
||||||
|
@Styleable protected Color disabledSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable protected Color disabledSelectedForeground;
|
||||||
|
|
||||||
protected Color defaultBackground;
|
@Styleable(dot=true) protected Color defaultBackground;
|
||||||
protected Color defaultEndBackground;
|
protected Color defaultEndBackground;
|
||||||
protected Color defaultForeground;
|
@Styleable(dot=true) protected Color defaultForeground;
|
||||||
protected Color defaultFocusedBackground;
|
@Styleable(dot=true) protected Color defaultFocusedBackground;
|
||||||
protected Color defaultHoverBackground;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultFocusedForeground;
|
||||||
protected Color defaultPressedBackground;
|
@Styleable(dot=true) protected Color defaultHoverBackground;
|
||||||
protected boolean defaultBoldText;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultHoverForeground;
|
||||||
|
@Styleable(dot=true) protected Color defaultPressedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultPressedForeground;
|
||||||
|
@Styleable(dot=true) protected boolean defaultBoldText;
|
||||||
|
|
||||||
protected int shadowWidth;
|
@Styleable protected boolean paintShadow;
|
||||||
protected Color shadowColor;
|
@Styleable protected int shadowWidth;
|
||||||
protected Color defaultShadowColor;
|
@Styleable protected Color shadowColor;
|
||||||
|
@Styleable(dot=true) protected Color defaultShadowColor;
|
||||||
|
|
||||||
protected Insets toolbarSpacingInsets;
|
@Styleable(dot=true) protected Color toolbarHoverBackground;
|
||||||
protected Color toolbarHoverBackground;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarHoverForeground;
|
||||||
protected Color toolbarPressedBackground;
|
@Styleable(dot=true) protected Color toolbarPressedBackground;
|
||||||
protected Color toolbarSelectedBackground;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarPressedForeground;
|
||||||
|
@Styleable(dot=true) protected Color toolbarSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarSelectedForeground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedForeground;
|
||||||
|
|
||||||
|
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||||
|
/** @since 2 */ @Styleable protected String buttonType;
|
||||||
|
/** @since 2 */ @Styleable protected boolean squareSize;
|
||||||
|
/** @since 2 */ @Styleable protected int minimumHeight;
|
||||||
|
|
||||||
private Icon helpButtonIcon;
|
private Icon helpButtonIcon;
|
||||||
private Insets defaultMargin;
|
private Insets defaultMargin;
|
||||||
|
|
||||||
|
private final boolean shared;
|
||||||
|
private boolean helpButtonIconShared = true;
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
private AtomicBoolean borderShared;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return FlatUIUtils.createSharedUI( FlatButtonUI.class, FlatButtonUI::new );
|
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||||
|
? FlatUIUtils.createSharedUI( FlatButtonUI.class, () -> new FlatButtonUI( true ) )
|
||||||
|
: new FlatButtonUI( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected FlatButtonUI( boolean shared ) {
|
||||||
|
this.shared = shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
if( FlatUIUtils.needsLightAWTPeer( c ) )
|
||||||
|
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
|
||||||
|
else
|
||||||
|
installUIImpl( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installUIImpl( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle( (AbstractButton) c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -154,40 +224,47 @@ public class FlatButtonUI
|
|||||||
startBackground = UIManager.getColor( prefix + "startBackground" );
|
startBackground = UIManager.getColor( prefix + "startBackground" );
|
||||||
endBackground = UIManager.getColor( prefix + "endBackground" );
|
endBackground = UIManager.getColor( prefix + "endBackground" );
|
||||||
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
||||||
|
focusedForeground = UIManager.getColor( prefix + "focusedForeground" );
|
||||||
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
||||||
|
hoverForeground = UIManager.getColor( prefix + "hoverForeground" );
|
||||||
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
||||||
|
pressedForeground = UIManager.getColor( prefix + "pressedForeground" );
|
||||||
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
||||||
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
||||||
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
||||||
disabledText = UIManager.getColor( prefix + "disabledText" );
|
disabledText = UIManager.getColor( prefix + "disabledText" );
|
||||||
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
||||||
|
disabledSelectedForeground = UIManager.getColor( prefix + "disabledSelectedForeground" );
|
||||||
if( UIManager.getBoolean( "Button.paintShadow" ) ) {
|
|
||||||
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
|
|
||||||
shadowColor = UIManager.getColor( "Button.shadowColor" );
|
|
||||||
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
|
||||||
} else {
|
|
||||||
shadowWidth = 0;
|
|
||||||
shadowColor = null;
|
|
||||||
defaultShadowColor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
||||||
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
||||||
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
||||||
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
||||||
|
defaultFocusedForeground = UIManager.getColor( "Button.default.focusedForeground" );
|
||||||
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
||||||
|
defaultHoverForeground = UIManager.getColor( "Button.default.hoverForeground" );
|
||||||
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
||||||
|
defaultPressedForeground = UIManager.getColor( "Button.default.pressedForeground" );
|
||||||
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
||||||
|
|
||||||
toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
|
||||||
|
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
|
||||||
|
shadowColor = UIManager.getColor( "Button.shadowColor" );
|
||||||
|
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||||
|
|
||||||
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
||||||
|
toolbarHoverForeground = UIManager.getColor( prefix + "toolbar.hoverForeground" );
|
||||||
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
||||||
|
toolbarPressedForeground = UIManager.getColor( prefix + "toolbar.pressedForeground" );
|
||||||
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
|
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
|
||||||
|
toolbarSelectedForeground = UIManager.getColor( prefix + "toolbar.selectedForeground" );
|
||||||
|
toolbarDisabledSelectedBackground = UIManager.getColor( prefix + "toolbar.disabledSelectedBackground" );
|
||||||
|
toolbarDisabledSelectedForeground = UIManager.getColor( prefix + "toolbar.disabledSelectedForeground" );
|
||||||
|
|
||||||
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
|
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
|
||||||
defaultMargin = UIManager.getInsets( prefix + "margin" );
|
defaultMargin = UIManager.getInsets( prefix + "margin" );
|
||||||
|
|
||||||
|
helpButtonIconShared = true;
|
||||||
defaults_initialized = true;
|
defaults_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,6 +284,9 @@ public class FlatButtonUI
|
|||||||
protected void uninstallDefaults( AbstractButton b ) {
|
protected void uninstallDefaults( AbstractButton b ) {
|
||||||
super.uninstallDefaults( b );
|
super.uninstallDefaults( b );
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
borderShared = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( b );
|
MigLayoutVisualPadding.uninstall( b );
|
||||||
defaults_initialized = false;
|
defaults_initialized = false;
|
||||||
}
|
}
|
||||||
@@ -228,9 +308,86 @@ public class FlatButtonUI
|
|||||||
b.revalidate();
|
b.revalidate();
|
||||||
b.repaint();
|
b.repaint();
|
||||||
break;
|
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( borderShared == null )
|
||||||
|
borderShared = new AtomicBoolean( true );
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, b, borderShared );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
Map<String, Class<?>> infos = FlatStylingSupport.getAnnotatedStyleableInfos( this, c.getBorder() );
|
||||||
|
if( helpButtonIcon instanceof FlatHelpButtonIcon )
|
||||||
|
FlatStylingSupport.putAllPrefixKey( infos, "help.", ((FlatHelpButtonIcon)helpButtonIcon).getStyleableInfos() );
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
if( key.startsWith( "help." ) ) {
|
||||||
|
return (helpButtonIcon instanceof FlatHelpButtonIcon)
|
||||||
|
? ((FlatHelpButtonIcon)helpButtonIcon).getStyleableValue( key.substring( "help.".length() ) )
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, c.getBorder(), key );
|
||||||
|
}
|
||||||
|
|
||||||
static boolean isContentAreaFilled( Component c ) {
|
static boolean isContentAreaFilled( Component c ) {
|
||||||
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
||||||
}
|
}
|
||||||
@@ -245,7 +402,7 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the button has an icon but no text,
|
* Returns true if the button has an icon but no text,
|
||||||
* or it it does not have an icon and the text is either "..." or one character.
|
* or it does not have an icon and the text is either "..." or one character.
|
||||||
*/
|
*/
|
||||||
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
||||||
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
||||||
@@ -268,11 +425,11 @@ public class FlatButtonUI
|
|||||||
if( !(c instanceof AbstractButton) )
|
if( !(c instanceof AbstractButton) )
|
||||||
return TYPE_OTHER;
|
return TYPE_OTHER;
|
||||||
|
|
||||||
Object value = ((AbstractButton)c).getClientProperty( BUTTON_TYPE );
|
String value = getButtonTypeStr( (AbstractButton) c );
|
||||||
if( !(value instanceof String) )
|
if( value == null )
|
||||||
return TYPE_OTHER;
|
return TYPE_OTHER;
|
||||||
|
|
||||||
switch( (String) value ) {
|
switch( value ) {
|
||||||
case BUTTON_TYPE_SQUARE: return TYPE_SQUARE;
|
case BUTTON_TYPE_SQUARE: return TYPE_SQUARE;
|
||||||
case BUTTON_TYPE_ROUND_RECT: return TYPE_ROUND_RECT;
|
case BUTTON_TYPE_ROUND_RECT: return TYPE_ROUND_RECT;
|
||||||
default: return TYPE_OTHER;
|
default: return TYPE_OTHER;
|
||||||
@@ -280,16 +437,27 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
static boolean isHelpButton( Component c ) {
|
static boolean isHelpButton( Component c ) {
|
||||||
return c instanceof JButton && clientPropertyEquals( (JButton) c, BUTTON_TYPE, BUTTON_TYPE_HELP );
|
return c instanceof JButton && BUTTON_TYPE_HELP.equals( getButtonTypeStr( (JButton) c ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isToolBarButton( Component c ) {
|
static boolean isToolBarButton( Component c ) {
|
||||||
return c.getParent() instanceof JToolBar ||
|
return c.getParent() instanceof JToolBar ||
|
||||||
(c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON ));
|
(c instanceof AbstractButton && BUTTON_TYPE_TOOLBAR_BUTTON.equals( getButtonTypeStr( (AbstractButton) c ) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isBorderlessButton( Component c ) {
|
static boolean isBorderlessButton( Component c ) {
|
||||||
return c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_BORDERLESS );
|
return c instanceof AbstractButton && BUTTON_TYPE_BORDERLESS.equals( getButtonTypeStr( (AbstractButton) c ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getButtonTypeStr( AbstractButton c ) {
|
||||||
|
// get from client property
|
||||||
|
Object value = c.getClientProperty( BUTTON_TYPE );
|
||||||
|
if( value instanceof String )
|
||||||
|
return (String) value;
|
||||||
|
|
||||||
|
// get from styling property
|
||||||
|
ButtonUI ui = c.getUI();
|
||||||
|
return (ui instanceof FlatButtonUI) ? ((FlatButtonUI)ui).buttonType : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -318,28 +486,46 @@ public class FlatButtonUI
|
|||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
|
boolean def = isDefaultButton( c );
|
||||||
boolean isToolBarButton = isToolBarButton( c );
|
boolean isToolBarButton = isToolBarButton( c );
|
||||||
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
||||||
float arc = FlatUIUtils.getBorderArc( c );
|
float arc = FlatUIUtils.getBorderArc( c );
|
||||||
|
float textFieldArc = 0;
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
// if toolbar button is in leading/trailing component of a text field,
|
||||||
|
// increase toolbar button arc to match text field arc (if necessary)
|
||||||
|
if( isToolBarButton &&
|
||||||
|
FlatClientProperties.clientProperty( c, STYLE_CLASS, "", String.class ).contains( "inTextField" ) )
|
||||||
|
{
|
||||||
|
JTextField textField = (JTextField) SwingUtilities.getAncestorOfClass( JTextField.class, c );
|
||||||
|
if( textField != null )
|
||||||
|
textFieldArc = FlatUIUtils.getBorderArc( textField );
|
||||||
|
}
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
int width = c.getWidth();
|
int width = c.getWidth();
|
||||||
int height = c.getHeight();
|
int height = c.getHeight();
|
||||||
|
|
||||||
if( isToolBarButton ) {
|
if( isToolBarButton && c.getBorder() instanceof FlatButtonBorder ) {
|
||||||
Insets spacing = UIScale.scale( toolbarSpacingInsets );
|
Insets spacing = UIScale.scale( ((FlatButtonBorder)c.getBorder()).toolbarSpacingInsets );
|
||||||
x += spacing.left;
|
x += spacing.left;
|
||||||
y += spacing.top;
|
y += spacing.top;
|
||||||
width -= spacing.left + spacing.right;
|
width -= spacing.left + spacing.right;
|
||||||
height -= spacing.top + spacing.bottom;
|
height -= spacing.top + spacing.bottom;
|
||||||
|
|
||||||
|
// reduce text field arc
|
||||||
|
textFieldArc -= spacing.top + spacing.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increase toolbar button arc to match text field arc (if necessary)
|
||||||
|
if( arc < textFieldArc )
|
||||||
|
arc = textFieldArc;
|
||||||
|
|
||||||
// paint shadow
|
// paint shadow
|
||||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||||
if( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
if( paintShadow &&
|
||||||
|
shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
||||||
!isToolBarButton && !isBorderlessButton( c ) &&
|
!isToolBarButton && !isBorderlessButton( c ) &&
|
||||||
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) )
|
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) )
|
||||||
{
|
{
|
||||||
@@ -367,6 +553,23 @@ public class FlatButtonUI
|
|||||||
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Graphics g, JComponent c, Rectangle iconRect ) {
|
||||||
|
// correct icon location when using bold font for default button
|
||||||
|
int xOffset = defaultBoldPlainWidthDiff( c ) / 2;
|
||||||
|
if( xOffset > 0 ) {
|
||||||
|
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
||||||
|
switch( ((AbstractButton)c).getHorizontalTextPosition() ) {
|
||||||
|
case SwingConstants.RIGHT: iconRect.x -= xOffset; break;
|
||||||
|
case SwingConstants.LEFT: iconRect.x += xOffset; break;
|
||||||
|
case SwingConstants.TRAILING: iconRect.x -= ltr ? xOffset : -xOffset; break;
|
||||||
|
case SwingConstants.LEADING: iconRect.x += ltr ? xOffset : -xOffset; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintIcon( g, c, iconRect );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
|
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
|
||||||
if( isHelpButton( b ) )
|
if( isHelpButton( b ) )
|
||||||
@@ -387,6 +590,8 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
|
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() );
|
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
||||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
||||||
|
|
||||||
@@ -400,11 +605,14 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
// selected state
|
// selected state
|
||||||
if( ((AbstractButton)c).isSelected() ) {
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
// in toolbar use same background colors for disabled and enabled because
|
// in toolbar, if toolbarDisabledSelectedBackground is null,
|
||||||
|
// use same background colors for disabled and enabled because
|
||||||
// we assume that toolbar icon is shown disabled
|
// we assume that toolbar icon is shown disabled
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
||||||
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
|
toolBarButton
|
||||||
|
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
|
||||||
|
: disabledSelectedBackground,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
||||||
@@ -431,6 +639,9 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBackgroundBase( JComponent c, boolean def ) {
|
protected Color getBackgroundBase( JComponent c, boolean def ) {
|
||||||
|
if( FlatUIUtils.isAWTPeer( c ) )
|
||||||
|
return background;
|
||||||
|
|
||||||
// use component background if explicitly set
|
// use component background if explicitly set
|
||||||
Color bg = c.getBackground();
|
Color bg = c.getBackground();
|
||||||
if( isCustomBackground( bg ) )
|
if( isCustomBackground( bg ) )
|
||||||
@@ -446,6 +657,9 @@ public class FlatButtonUI
|
|||||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||||
{
|
{
|
||||||
|
if( c == null )
|
||||||
|
return enabledColor;
|
||||||
|
|
||||||
if( !c.isEnabled() )
|
if( !c.isEnabled() )
|
||||||
return disabledColor;
|
return disabledColor;
|
||||||
|
|
||||||
@@ -466,18 +680,48 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( JComponent c ) {
|
protected Color getForeground( JComponent c ) {
|
||||||
if( !c.isEnabled() )
|
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
||||||
return disabledText;
|
|
||||||
|
|
||||||
if( ((AbstractButton)c).isSelected() && !(isToolBarButton( c ) || isBorderlessButton( c )) )
|
// selected state
|
||||||
return selectedForeground;
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
|
return buttonStateColor( c,
|
||||||
|
toolBarButton
|
||||||
|
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : c.getForeground())
|
||||||
|
: selectedForeground,
|
||||||
|
toolBarButton
|
||||||
|
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
|
||||||
|
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
toolBarButton ? toolbarPressedForeground : pressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
// toolbar button
|
||||||
|
if( toolBarButton ) {
|
||||||
|
return buttonStateColor( c,
|
||||||
|
c.getForeground(),
|
||||||
|
disabledText,
|
||||||
|
null,
|
||||||
|
toolbarHoverForeground,
|
||||||
|
toolbarPressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean def = isDefaultButton( c );
|
||||||
|
return buttonStateColor( c,
|
||||||
|
getForegroundBase( c, def ),
|
||||||
|
disabledText,
|
||||||
|
isCustomForeground( c.getForeground() ) ? null : (def ? defaultFocusedForeground : focusedForeground),
|
||||||
|
def ? defaultHoverForeground : hoverForeground,
|
||||||
|
def ? defaultPressedForeground : pressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
protected Color getForegroundBase( JComponent c, boolean def ) {
|
||||||
// use component foreground if explicitly set
|
// use component foreground if explicitly set
|
||||||
Color fg = c.getForeground();
|
Color fg = c.getForeground();
|
||||||
if( isCustomForeground( fg ) )
|
if( isCustomForeground( fg ) )
|
||||||
return fg;
|
return fg;
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
|
||||||
return def ? defaultForeground : fg;
|
return def ? defaultForeground : fg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,9 +738,12 @@ public class FlatButtonUI
|
|||||||
if( prefSize == null )
|
if( prefSize == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// increase width when using bold font for default button
|
||||||
|
prefSize.width += defaultBoldPlainWidthDiff( c );
|
||||||
|
|
||||||
// make square or apply minimum width/height
|
// make square or apply minimum width/height
|
||||||
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
||||||
if( clientPropertyBoolean( c, SQUARE_SIZE, false ) ) {
|
if( clientPropertyBoolean( c, SQUARE_SIZE, squareSize ) ) {
|
||||||
// make button square (increase width or height so that they are equal)
|
// make button square (increase width or height so that they are equal)
|
||||||
prefSize.width = prefSize.height = Math.max( prefSize.width, prefSize.height );
|
prefSize.width = prefSize.height = Math.max( prefSize.width, prefSize.height );
|
||||||
} else if( isIconOnlyOrSingleCharacter && ((AbstractButton)c).getIcon() == null ) {
|
} else if( isIconOnlyOrSingleCharacter && ((AbstractButton)c).getIcon() == null ) {
|
||||||
@@ -508,12 +755,29 @@ public class FlatButtonUI
|
|||||||
// apply minimum width/height
|
// apply minimum width/height
|
||||||
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
||||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
||||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + fw );
|
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, minimumHeight ) ) + fw );
|
||||||
}
|
}
|
||||||
|
|
||||||
return prefSize;
|
return prefSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int defaultBoldPlainWidthDiff( JComponent c ) {
|
||||||
|
if( defaultBoldText && isDefaultButton( c ) && c.getFont() instanceof UIResource ) {
|
||||||
|
String text = ((AbstractButton)c).getText();
|
||||||
|
if( text == null || text.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Font font = c.getFont();
|
||||||
|
Font boldFont = font.deriveFont( Font.BOLD );
|
||||||
|
int boldWidth = c.getFontMetrics( boldFont ).stringWidth( text );
|
||||||
|
int plainWidth = c.getFontMetrics( font ).stringWidth( text );
|
||||||
|
if( boldWidth > plainWidth )
|
||||||
|
return boldWidth - plainWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasDefaultMargins( JComponent c ) {
|
private boolean hasDefaultMargins( JComponent c ) {
|
||||||
Insets margin = ((AbstractButton)c).getMargin();
|
Insets margin = ((AbstractButton)c).getMargin();
|
||||||
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
||||||
@@ -536,5 +800,20 @@ public class FlatButtonUI
|
|||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
FlatButtonUI.this.propertyChange( b, e );
|
FlatButtonUI.this.propertyChange( b, e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
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,19 +18,27 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
import java.awt.Insets;
|
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.ActionMap;
|
||||||
import javax.swing.JFormattedTextField;
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.DefaultCaret;
|
import javax.swing.text.DefaultCaret;
|
||||||
|
import javax.swing.text.DefaultEditorKit;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import javax.swing.text.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caret that can select all text on focus gained.
|
* Caret that can select all text on focus gained.
|
||||||
|
* Also fixes Swing's double-click-and-drag behavior so that dragging after
|
||||||
|
* a double-click extends selection by whole words.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
@@ -38,12 +46,19 @@ public class FlatCaret
|
|||||||
extends DefaultCaret
|
extends DefaultCaret
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
|
private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo";
|
||||||
|
|
||||||
private final String selectAllOnFocusPolicy;
|
private final String selectAllOnFocusPolicy;
|
||||||
private final boolean selectAllOnMouseClick;
|
private final boolean selectAllOnMouseClick;
|
||||||
|
|
||||||
|
private boolean inInstall;
|
||||||
private boolean wasFocused;
|
private boolean wasFocused;
|
||||||
private boolean wasTemporaryLost;
|
private boolean wasTemporaryLost;
|
||||||
private boolean isMousePressed;
|
private boolean isMousePressed;
|
||||||
|
private boolean isWordSelection;
|
||||||
|
private boolean isLineSelection;
|
||||||
|
private int dragSelectionStart;
|
||||||
|
private int dragSelectionEnd;
|
||||||
|
|
||||||
public FlatCaret( String selectAllOnFocusPolicy, boolean selectAllOnMouseClick ) {
|
public FlatCaret( String selectAllOnFocusPolicy, boolean selectAllOnMouseClick ) {
|
||||||
this.selectAllOnFocusPolicy = selectAllOnFocusPolicy;
|
this.selectAllOnFocusPolicy = selectAllOnFocusPolicy;
|
||||||
@@ -52,34 +67,82 @@ public class FlatCaret
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void install( JTextComponent c ) {
|
public void install( JTextComponent c ) {
|
||||||
super.install( c );
|
// get caret info if switched theme
|
||||||
|
long[] ci = (long[]) c.getClientProperty( KEY_CARET_INFO );
|
||||||
|
if( ci != null ) {
|
||||||
|
c.putClientProperty( KEY_CARET_INFO, null );
|
||||||
|
|
||||||
// the dot and mark are lost when switching LaF
|
// if caret info is too old assume that switched from FlatLaf
|
||||||
// --> move dot to end of text so that all text may be selected when it gains focus
|
// to another Laf and back to FlatLaf
|
||||||
Document doc = c.getDocument();
|
if( System.currentTimeMillis() - 500 > ci[3] )
|
||||||
if( doc != null && getDot() == 0 && getMark() == 0 ) {
|
ci = null;
|
||||||
int length = doc.getLength();
|
|
||||||
if( length > 0 )
|
|
||||||
setDot( length );
|
|
||||||
}
|
}
|
||||||
|
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
|
@Override
|
||||||
protected void adjustVisibility( Rectangle nloc ) {
|
protected void adjustVisibility( Rectangle nloc ) {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
if( c != null && c.getUI() instanceof FlatTextFieldUI ) {
|
if( c != null && c.getUI() instanceof FlatTextFieldUI ) {
|
||||||
Insets padding = ((FlatTextFieldUI)c.getUI()).getPadding();
|
// need to fix x location because JTextField.scrollRectToVisible() uses insets.left
|
||||||
if( padding != null ) {
|
// (as BasicTextUI.getVisibleEditorRect() does),
|
||||||
nloc.x -= padding.left;
|
// but FlatTextFieldUI.getVisibleEditorRect() may add some padding
|
||||||
nloc.y -= padding.top;
|
Rectangle r = ((FlatTextFieldUI)c.getUI()).getVisibleEditorRect();
|
||||||
}
|
if( r != null )
|
||||||
|
nloc.x -= r.x - c.getInsets().left;
|
||||||
}
|
}
|
||||||
super.adjustVisibility( nloc );
|
super.adjustVisibility( nloc );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
if( !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
|
if( !inInstall && !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
|
||||||
selectAllOnFocusGained();
|
selectAllOnFocusGained();
|
||||||
wasTemporaryLost = false;
|
wasTemporaryLost = false;
|
||||||
wasFocused = true;
|
wasFocused = true;
|
||||||
@@ -97,25 +160,83 @@ public class FlatCaret
|
|||||||
public void mousePressed( MouseEvent e ) {
|
public void mousePressed( MouseEvent e ) {
|
||||||
isMousePressed = true;
|
isMousePressed = true;
|
||||||
super.mousePressed( e );
|
super.mousePressed( e );
|
||||||
|
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
|
||||||
|
// left double-click starts word selection
|
||||||
|
isWordSelection = e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) && !e.isConsumed();
|
||||||
|
|
||||||
|
// left triple-click starts line selection
|
||||||
|
isLineSelection = e.getClickCount() == 3 && SwingUtilities.isLeftMouseButton( e ) && (!e.isConsumed() || c.getDragEnabled());
|
||||||
|
|
||||||
|
// select line
|
||||||
|
// (this is also done in DefaultCaret.mouseClicked(), but this event is
|
||||||
|
// sent when the mouse is released, which is too late for triple-click-and-drag)
|
||||||
|
if( isLineSelection ) {
|
||||||
|
ActionMap actionMap = c.getActionMap();
|
||||||
|
Action selectLineAction = (actionMap != null)
|
||||||
|
? actionMap.get( DefaultEditorKit.selectLineAction )
|
||||||
|
: null;
|
||||||
|
if( selectLineAction != null ) {
|
||||||
|
selectLineAction.actionPerformed( new ActionEvent( c,
|
||||||
|
ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember selection where word/line selection starts to keep it always selected while dragging
|
||||||
|
if( isWordSelection || isLineSelection ) {
|
||||||
|
int mark = getMark();
|
||||||
|
int dot = getDot();
|
||||||
|
dragSelectionStart = Math.min( dot, mark );
|
||||||
|
dragSelectionEnd = Math.max( dot, mark );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased( MouseEvent e ) {
|
public void mouseReleased( MouseEvent e ) {
|
||||||
isMousePressed = false;
|
isMousePressed = false;
|
||||||
|
isWordSelection = false;
|
||||||
|
isLineSelection = false;
|
||||||
super.mouseReleased( e );
|
super.mouseReleased( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged( MouseEvent e ) {
|
||||||
|
if( (isWordSelection || isLineSelection) &&
|
||||||
|
!e.isConsumed() && SwingUtilities.isLeftMouseButton( e ) )
|
||||||
|
{
|
||||||
|
// fix Swing's double/triple-click-and-drag behavior so that dragging after
|
||||||
|
// a double/triple-click extends selection by whole words/lines
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
int pos = c.viewToModel( e.getPoint() );
|
||||||
|
if( pos < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( pos > dragSelectionEnd )
|
||||||
|
select( dragSelectionStart, isWordSelection ? Utilities.getWordEnd( c, pos ) : Utilities.getRowEnd( c, pos ) );
|
||||||
|
else if( pos < dragSelectionStart )
|
||||||
|
select( dragSelectionEnd, isWordSelection ? Utilities.getWordStart( c, pos ) : Utilities.getRowStart( c, pos ) );
|
||||||
|
else
|
||||||
|
select( dragSelectionStart, dragSelectionEnd );
|
||||||
|
} catch( BadLocationException ex ) {
|
||||||
|
UIManager.getLookAndFeel().provideErrorFeedback( c );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
super.mouseDragged( e );
|
||||||
|
}
|
||||||
|
|
||||||
protected void selectAllOnFocusGained() {
|
protected void selectAllOnFocusGained() {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
Document doc = c.getDocument();
|
Document doc = c.getDocument();
|
||||||
if( doc == null || !c.isEnabled() || !c.isEditable() )
|
if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
||||||
if( selectAllOnFocusPolicy == null )
|
if( selectAllOnFocusPolicy == null )
|
||||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
||||||
|
|
||||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
||||||
@@ -135,18 +256,24 @@ public class FlatCaret
|
|||||||
// select all
|
// select all
|
||||||
if( c instanceof JFormattedTextField ) {
|
if( c instanceof JFormattedTextField ) {
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
setDot( 0 );
|
if( getComponent() == null )
|
||||||
moveDot( doc.getLength() );
|
return; // was deinstalled
|
||||||
|
|
||||||
|
select( 0, doc.getLength() );
|
||||||
} );
|
} );
|
||||||
} else {
|
} else {
|
||||||
setDot( 0 );
|
select( 0, doc.getLength() );
|
||||||
moveDot( doc.getLength() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void select( int mark, int dot ) {
|
||||||
* @since 1.4
|
if( mark != getMark() )
|
||||||
*/
|
setDot( mark );
|
||||||
|
if( dot != getDot() )
|
||||||
|
moveDot( dot );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 1.4 */
|
||||||
public void scrollCaretToVisible() {
|
public void scrollCaretToVisible() {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
if( c == null || c.getUI() == null )
|
if( c == null || c.getUI() == null )
|
||||||
|
|||||||
@@ -18,11 +18,19 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||||
|
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JCheckBoxMenuItem}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JCheckBoxMenuItem}.
|
||||||
@@ -52,15 +60,30 @@ import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
|||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionBackground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="disabledForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorSelectionForeground" )
|
||||||
|
|
||||||
public class FlatCheckBoxMenuItemUI
|
public class FlatCheckBoxMenuItemUI
|
||||||
extends BasicCheckBoxMenuItemUI
|
extends BasicCheckBoxMenuItemUI
|
||||||
|
implements StyleableUI, StyleableLookupProvider
|
||||||
{
|
{
|
||||||
private FlatMenuItemRenderer renderer;
|
private FlatMenuItemRenderer renderer;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatCheckBoxMenuItemUI();
|
return new FlatCheckBoxMenuItemUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -74,13 +97,59 @@ public class FlatCheckBoxMenuItemUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||||
renderer = null;
|
renderer = null;
|
||||||
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
|
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "CheckBoxMenuItem" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatMenuItemUI.getStyleableInfos( this, renderer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatMenuItemUI.getStyleableValue( this, renderer, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public MethodHandles.Lookup getLookupForStyling() {
|
||||||
|
// MethodHandles.lookup() is caller sensitive and must be invoked in this class,
|
||||||
|
// otherwise it is not possible to access protected fields in JRE superclass
|
||||||
|
return MethodHandles.lookup();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||||
return renderer.getPreferredMenuItemSize();
|
return renderer.getPreferredMenuItemSize();
|
||||||
|
|||||||
@@ -43,11 +43,24 @@ public class FlatCheckBoxUI
|
|||||||
extends FlatRadioButtonUI
|
extends FlatRadioButtonUI
|
||||||
{
|
{
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, FlatCheckBoxUI::new );
|
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||||
|
? FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, () -> new FlatCheckBoxUI( true ) )
|
||||||
|
: new FlatCheckBoxUI( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected FlatCheckBoxUI( boolean shared ) {
|
||||||
|
super( shared );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPropertyPrefix() {
|
public String getPropertyPrefix() {
|
||||||
return "CheckBox.";
|
return "CheckBox.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
String getStyleType() {
|
||||||
|
return "CheckBox";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import static com.formdev.flatlaf.util.UIScale.unscale;
|
import static com.formdev.flatlaf.util.UIScale.unscale;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
@@ -41,10 +42,12 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.CellRendererPane;
|
import javax.swing.CellRendererPane;
|
||||||
import javax.swing.ComboBoxEditor;
|
|
||||||
import javax.swing.DefaultListCellRenderer;
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.InputMap;
|
import javax.swing.InputMap;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
@@ -67,7 +70,12 @@ import javax.swing.plaf.basic.BasicComboBoxUI;
|
|||||||
import javax.swing.plaf.basic.BasicComboPopup;
|
import javax.swing.plaf.basic.BasicComboPopup;
|
||||||
import javax.swing.plaf.basic.ComboPopup;
|
import javax.swing.plaf.basic.ComboPopup;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,56 +90,73 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault ComboBox.padding Insets
|
* @uiDefault ComboBox.padding Insets
|
||||||
* @uiDefault ComboBox.squareButton boolean default is true
|
* @uiDefault ComboBox.squareButton boolean default is true
|
||||||
*
|
*
|
||||||
|
* <!-- BasicComboPopup -->
|
||||||
|
*
|
||||||
|
* @uiDefault ComboBox.selectionBackground Color
|
||||||
|
* @uiDefault ComboBox.selectionForeground Color
|
||||||
|
*
|
||||||
* <!-- FlatComboBoxUI -->
|
* <!-- FlatComboBoxUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault ComboBox.minimumWidth int
|
* @uiDefault ComboBox.minimumWidth int
|
||||||
* @uiDefault ComboBox.editorColumns int
|
* @uiDefault ComboBox.editorColumns int
|
||||||
* @uiDefault ComboBox.maximumRowCount int
|
* @uiDefault ComboBox.maximumRowCount int
|
||||||
* @uiDefault ComboBox.buttonStyle String auto (default), button or none
|
* @uiDefault ComboBox.buttonStyle String auto (default), button, mac or none
|
||||||
* @uiDefault Component.arrowType String chevron (default) or triangle
|
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
* @uiDefault Component.isIntelliJTheme boolean
|
||||||
* @uiDefault Component.borderColor Color
|
|
||||||
* @uiDefault Component.disabledBorderColor Color
|
|
||||||
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
||||||
* @uiDefault ComboBox.focusedBackground Color optional
|
* @uiDefault ComboBox.focusedBackground Color optional
|
||||||
* @uiDefault ComboBox.disabledBackground Color
|
* @uiDefault ComboBox.disabledBackground Color
|
||||||
* @uiDefault ComboBox.disabledForeground Color
|
* @uiDefault ComboBox.disabledForeground Color
|
||||||
* @uiDefault ComboBox.buttonBackground Color
|
* @uiDefault ComboBox.buttonBackground Color optional
|
||||||
* @uiDefault ComboBox.buttonEditableBackground Color
|
* @uiDefault ComboBox.buttonEditableBackground Color optional
|
||||||
* @uiDefault ComboBox.buttonFocusedBackground Color optional; defaults to ComboBox.focusedBackground
|
* @uiDefault ComboBox.buttonFocusedBackground Color optional; defaults to ComboBox.focusedBackground
|
||||||
|
* @uiDefault ComboBox.buttonSeparatorWidth int or float optional; defaults to Component.borderWidth
|
||||||
|
* @uiDefault ComboBox.buttonSeparatorColor Color optional
|
||||||
|
* @uiDefault ComboBox.buttonDisabledSeparatorColor Color optional
|
||||||
* @uiDefault ComboBox.buttonArrowColor Color
|
* @uiDefault ComboBox.buttonArrowColor Color
|
||||||
* @uiDefault ComboBox.buttonDisabledArrowColor Color
|
* @uiDefault ComboBox.buttonDisabledArrowColor Color
|
||||||
* @uiDefault ComboBox.buttonHoverArrowColor Color
|
* @uiDefault ComboBox.buttonHoverArrowColor Color
|
||||||
* @uiDefault ComboBox.buttonPressedArrowColor Color
|
* @uiDefault ComboBox.buttonPressedArrowColor Color
|
||||||
* @uiDefault ComboBox.popupBackground Color optional
|
* @uiDefault ComboBox.popupBackground Color optional
|
||||||
|
* @uiDefault ComboBox.popupInsets Insets
|
||||||
|
* @uiDefault ComboBox.selectionInsets Insets
|
||||||
|
* @uiDefault ComboBox.selectionArc int
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
@StyleableField( cls=BasicComboBoxUI.class, key="padding" )
|
||||||
|
|
||||||
public class FlatComboBoxUI
|
public class FlatComboBoxUI
|
||||||
extends BasicComboBoxUI
|
extends BasicComboBoxUI
|
||||||
|
implements StyleableUI, StyleableLookupProvider
|
||||||
{
|
{
|
||||||
protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected int editorColumns;
|
@Styleable protected int editorColumns;
|
||||||
protected String buttonStyle;
|
@Styleable protected String buttonStyle;
|
||||||
protected String arrowType;
|
@Styleable protected String arrowType;
|
||||||
protected boolean isIntelliJTheme;
|
protected boolean isIntelliJTheme;
|
||||||
protected Color borderColor;
|
|
||||||
protected Color disabledBorderColor;
|
|
||||||
|
|
||||||
protected Color editableBackground;
|
private Color background;
|
||||||
protected Color focusedBackground;
|
@Styleable protected Color editableBackground;
|
||||||
protected Color disabledBackground;
|
@Styleable protected Color focusedBackground;
|
||||||
protected Color disabledForeground;
|
@Styleable protected Color disabledBackground;
|
||||||
|
@Styleable protected Color disabledForeground;
|
||||||
|
|
||||||
protected Color buttonBackground;
|
@Styleable protected Color buttonBackground;
|
||||||
protected Color buttonEditableBackground;
|
@Styleable protected Color buttonEditableBackground;
|
||||||
protected Color buttonFocusedBackground;
|
@Styleable protected Color buttonFocusedBackground;
|
||||||
protected Color buttonArrowColor;
|
/** @since 2 */ @Styleable protected float buttonSeparatorWidth;
|
||||||
protected Color buttonDisabledArrowColor;
|
/** @since 2 */ @Styleable protected Color buttonSeparatorColor;
|
||||||
protected Color buttonHoverArrowColor;
|
/** @since 2 */ @Styleable protected Color buttonDisabledSeparatorColor;
|
||||||
protected Color buttonPressedArrowColor;
|
@Styleable protected Color buttonArrowColor;
|
||||||
|
@Styleable protected Color buttonDisabledArrowColor;
|
||||||
|
@Styleable protected Color buttonHoverArrowColor;
|
||||||
|
@Styleable protected Color buttonPressedArrowColor;
|
||||||
|
|
||||||
protected Color popupBackground;
|
@Styleable protected Color popupBackground;
|
||||||
|
/** @since 3 */ @Styleable protected Insets popupInsets;
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc;
|
||||||
|
|
||||||
private MouseListener hoverListener;
|
private MouseListener hoverListener;
|
||||||
protected boolean hover;
|
protected boolean hover;
|
||||||
@@ -139,10 +164,27 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
private CellPaddingBorder paddingBorder;
|
private CellPaddingBorder paddingBorder;
|
||||||
|
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
private AtomicBoolean borderShared;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatComboBoxUI();
|
return new FlatComboBoxUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
if( FlatUIUtils.needsLightAWTPeer( c ) )
|
||||||
|
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
|
||||||
|
else
|
||||||
|
installUIImpl( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installUIImpl( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installListeners() {
|
protected void installListeners() {
|
||||||
super.installListeners();
|
super.installListeners();
|
||||||
@@ -199,9 +241,8 @@ public class FlatComboBoxUI
|
|||||||
buttonStyle = UIManager.getString( "ComboBox.buttonStyle" );
|
buttonStyle = UIManager.getString( "ComboBox.buttonStyle" );
|
||||||
arrowType = UIManager.getString( "Component.arrowType" );
|
arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||||
borderColor = UIManager.getColor( "Component.borderColor" );
|
|
||||||
disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
|
||||||
|
|
||||||
|
background = UIManager.getColor( "ComboBox.background" );
|
||||||
editableBackground = UIManager.getColor( "ComboBox.editableBackground" );
|
editableBackground = UIManager.getColor( "ComboBox.editableBackground" );
|
||||||
focusedBackground = UIManager.getColor( "ComboBox.focusedBackground" );
|
focusedBackground = UIManager.getColor( "ComboBox.focusedBackground" );
|
||||||
disabledBackground = UIManager.getColor( "ComboBox.disabledBackground" );
|
disabledBackground = UIManager.getColor( "ComboBox.disabledBackground" );
|
||||||
@@ -210,12 +251,18 @@ public class FlatComboBoxUI
|
|||||||
buttonBackground = UIManager.getColor( "ComboBox.buttonBackground" );
|
buttonBackground = UIManager.getColor( "ComboBox.buttonBackground" );
|
||||||
buttonFocusedBackground = UIManager.getColor( "ComboBox.buttonFocusedBackground" );
|
buttonFocusedBackground = UIManager.getColor( "ComboBox.buttonFocusedBackground" );
|
||||||
buttonEditableBackground = UIManager.getColor( "ComboBox.buttonEditableBackground" );
|
buttonEditableBackground = UIManager.getColor( "ComboBox.buttonEditableBackground" );
|
||||||
|
buttonSeparatorWidth = FlatUIUtils.getUIFloat( "ComboBox.buttonSeparatorWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ) );
|
||||||
|
buttonSeparatorColor = UIManager.getColor( "ComboBox.buttonSeparatorColor" );
|
||||||
|
buttonDisabledSeparatorColor = UIManager.getColor( "ComboBox.buttonDisabledSeparatorColor" );
|
||||||
buttonArrowColor = UIManager.getColor( "ComboBox.buttonArrowColor" );
|
buttonArrowColor = UIManager.getColor( "ComboBox.buttonArrowColor" );
|
||||||
buttonDisabledArrowColor = UIManager.getColor( "ComboBox.buttonDisabledArrowColor" );
|
buttonDisabledArrowColor = UIManager.getColor( "ComboBox.buttonDisabledArrowColor" );
|
||||||
buttonHoverArrowColor = UIManager.getColor( "ComboBox.buttonHoverArrowColor" );
|
buttonHoverArrowColor = UIManager.getColor( "ComboBox.buttonHoverArrowColor" );
|
||||||
buttonPressedArrowColor = UIManager.getColor( "ComboBox.buttonPressedArrowColor" );
|
buttonPressedArrowColor = UIManager.getColor( "ComboBox.buttonPressedArrowColor" );
|
||||||
|
|
||||||
popupBackground = UIManager.getColor( "ComboBox.popupBackground" );
|
popupBackground = UIManager.getColor( "ComboBox.popupBackground" );
|
||||||
|
popupInsets = UIManager.getInsets( "ComboBox.popupInsets" );
|
||||||
|
selectionInsets = UIManager.getInsets( "ComboBox.selectionInsets" );
|
||||||
|
selectionArc = UIManager.getInt( "ComboBox.selectionArc" );
|
||||||
|
|
||||||
// set maximumRowCount
|
// set maximumRowCount
|
||||||
int maximumRowCount = UIManager.getInt( "ComboBox.maximumRowCount" );
|
int maximumRowCount = UIManager.getInt( "ComboBox.maximumRowCount" );
|
||||||
@@ -231,9 +278,7 @@ public class FlatComboBoxUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
borderColor = null;
|
background = null;
|
||||||
disabledBorderColor = null;
|
|
||||||
|
|
||||||
editableBackground = null;
|
editableBackground = null;
|
||||||
focusedBackground = null;
|
focusedBackground = null;
|
||||||
disabledBackground = null;
|
disabledBackground = null;
|
||||||
@@ -242,6 +287,8 @@ public class FlatComboBoxUI
|
|||||||
buttonBackground = null;
|
buttonBackground = null;
|
||||||
buttonEditableBackground = null;
|
buttonEditableBackground = null;
|
||||||
buttonFocusedBackground = null;
|
buttonFocusedBackground = null;
|
||||||
|
buttonSeparatorColor = null;
|
||||||
|
buttonDisabledSeparatorColor = null;
|
||||||
buttonArrowColor = null;
|
buttonArrowColor = null;
|
||||||
buttonDisabledArrowColor = null;
|
buttonDisabledArrowColor = null;
|
||||||
buttonHoverArrowColor = null;
|
buttonHoverArrowColor = null;
|
||||||
@@ -251,6 +298,9 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
paddingBorder.uninstall();
|
paddingBorder.uninstall();
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
borderShared = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( comboBox );
|
MigLayoutVisualPadding.uninstall( comboBox );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,15 +311,21 @@ public class FlatComboBoxUI
|
|||||||
public void layoutContainer( Container parent ) {
|
public void layoutContainer( Container parent ) {
|
||||||
super.layoutContainer( parent );
|
super.layoutContainer( parent );
|
||||||
|
|
||||||
if( arrowButton != null ) {
|
// on macOS, a Swing combo box is used for AWT component java.awt.Choice
|
||||||
|
// and the font may be (temporary) null
|
||||||
|
|
||||||
|
if( arrowButton != null && comboBox.getFont() != null ) {
|
||||||
// limit button width to height of a raw combobox (without insets)
|
// limit button width to height of a raw combobox (without insets)
|
||||||
FontMetrics fm = comboBox.getFontMetrics( comboBox.getFont() );
|
FontMetrics fm = comboBox.getFontMetrics( comboBox.getFont() );
|
||||||
int maxButtonWidth = fm.getHeight() + scale( padding.top ) + scale( padding.bottom );
|
int maxButtonWidth = fm.getHeight() + scale( padding.top ) + scale( padding.bottom );
|
||||||
|
int minButtonWidth = (maxButtonWidth * 3) / 4;
|
||||||
|
|
||||||
|
// make button square (except if width is limited)
|
||||||
Insets insets = getInsets();
|
Insets insets = getInsets();
|
||||||
int buttonWidth = Math.min( parent.getPreferredSize().height - insets.top - insets.bottom, maxButtonWidth );
|
int buttonWidth = Math.min( Math.max( parent.getHeight() - insets.top - insets.bottom, minButtonWidth ), maxButtonWidth );
|
||||||
|
|
||||||
if( buttonWidth != arrowButton.getWidth() ) {
|
if( buttonWidth != arrowButton.getWidth() ) {
|
||||||
// set width of arrow button to preferred height of combobox
|
// set width of arrow button
|
||||||
int xOffset = comboBox.getComponentOrientation().isLeftToRight()
|
int xOffset = comboBox.getComponentOrientation().isLeftToRight()
|
||||||
? arrowButton.getWidth() - buttonWidth
|
? arrowButton.getWidth() - buttonWidth
|
||||||
: 0;
|
: 0;
|
||||||
@@ -323,12 +379,30 @@ public class FlatComboBoxUI
|
|||||||
} else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) {
|
} else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) {
|
||||||
ComponentOrientation o = (ComponentOrientation) e.getNewValue();
|
ComponentOrientation o = (ComponentOrientation) e.getNewValue();
|
||||||
editor.applyComponentOrientation( o );
|
editor.applyComponentOrientation( o );
|
||||||
} else if( editor != null && FlatClientProperties.PLACEHOLDER_TEXT.equals( propertyName ) )
|
} else {
|
||||||
editor.repaint();
|
switch( propertyName ) {
|
||||||
else if( FlatClientProperties.COMPONENT_ROUND_RECT.equals( propertyName ) )
|
case PLACEHOLDER_TEXT:
|
||||||
comboBox.repaint();
|
if( editor != null )
|
||||||
else if( FlatClientProperties.MINIMUM_WIDTH.equals( propertyName ) )
|
editor.repaint();
|
||||||
comboBox.revalidate();
|
break;
|
||||||
|
|
||||||
|
case COMPONENT_ROUND_RECT:
|
||||||
|
case OUTLINE:
|
||||||
|
comboBox.repaint();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MINIMUM_WIDTH:
|
||||||
|
comboBox.revalidate();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STYLE:
|
||||||
|
case STYLE_CLASS:
|
||||||
|
installStyle();
|
||||||
|
comboBox.revalidate();
|
||||||
|
comboBox.repaint();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,33 +412,25 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ComboBoxEditor createEditor() {
|
protected void configureEditor() {
|
||||||
ComboBoxEditor comboBoxEditor = super.createEditor();
|
super.configureEditor();
|
||||||
|
|
||||||
Component editor = comboBoxEditor.getEditorComponent();
|
|
||||||
if( editor instanceof JTextField ) {
|
if( editor instanceof JTextField ) {
|
||||||
JTextField textField = (JTextField) editor;
|
JTextField textField = (JTextField) editor;
|
||||||
textField.setColumns( editorColumns );
|
textField.setColumns( editorColumns );
|
||||||
|
|
||||||
// assign a non-null and non-javax.swing.plaf.UIResource border to the text field,
|
// remove default text field border from editor
|
||||||
// otherwise it is replaced with default text field border when switching LaF
|
Border border = textField.getBorder();
|
||||||
// because javax.swing.plaf.basic.BasicComboBoxEditor.BorderlessTextField.setBorder()
|
if( border == null || border instanceof UIResource ) {
|
||||||
// uses "border instanceof javax.swing.plaf.basic.BasicComboBoxEditor.UIResource"
|
// assign a non-null and non-javax.swing.plaf.UIResource border to the text field,
|
||||||
// instead of "border instanceof javax.swing.plaf.UIResource"
|
// otherwise it is replaced with default text field border when switching LaF
|
||||||
textField.setBorder( BorderFactory.createEmptyBorder() );
|
// because javax.swing.plaf.basic.BasicComboBoxEditor.BorderlessTextField.setBorder()
|
||||||
|
// uses "border instanceof javax.swing.plaf.basic.BasicComboBoxEditor.UIResource"
|
||||||
|
// instead of "border instanceof javax.swing.plaf.UIResource"
|
||||||
|
textField.setBorder( BorderFactory.createEmptyBorder() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return comboBoxEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureEditor() {
|
|
||||||
super.configureEditor();
|
|
||||||
|
|
||||||
// remove default text field border from editor
|
|
||||||
if( editor instanceof JTextField && ((JTextField)editor).getBorder() instanceof FlatTextBorder )
|
|
||||||
((JTextField)editor).setBorder( BorderFactory.createEmptyBorder() );
|
|
||||||
|
|
||||||
// explicitly make non-opaque
|
// explicitly make non-opaque
|
||||||
if( editor instanceof JComponent )
|
if( editor instanceof JComponent )
|
||||||
((JComponent)editor).setOpaque( false );
|
((JComponent)editor).setOpaque( false );
|
||||||
@@ -404,7 +470,7 @@ public class FlatComboBoxUI
|
|||||||
unscale( Math.max( scale( padding.right ) - insets.right, 0 ) )
|
unscale( Math.max( scale( padding.right ) - insets.right, 0 ) )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, pad );
|
textField.putClientProperty( TEXT_FIELD_PADDING, pad );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateEditorColors() {
|
private void updateEditorColors() {
|
||||||
@@ -423,6 +489,61 @@ public class FlatComboBoxUI
|
|||||||
return new FlatComboBoxButton();
|
return new FlatComboBoxButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( comboBox, "ComboBox" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
Insets oldPadding = padding;
|
||||||
|
int oldEditorColumns = editorColumns;
|
||||||
|
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
|
||||||
|
if( !padding.equals( oldPadding ) ) {
|
||||||
|
paddingBorder.padding = padding;
|
||||||
|
updateEditorPadding();
|
||||||
|
}
|
||||||
|
if( arrowButton instanceof FlatComboBoxButton )
|
||||||
|
((FlatComboBoxButton)arrowButton).updateStyle();
|
||||||
|
if( popup instanceof FlatComboPopup )
|
||||||
|
((FlatComboPopup)popup).updateStyle();
|
||||||
|
if( editorColumns != oldEditorColumns && editor instanceof JTextField )
|
||||||
|
((JTextField)editor).setColumns( editorColumns );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
if( borderShared == null )
|
||||||
|
borderShared = new AtomicBoolean( true );
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, comboBox, borderShared );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this, comboBox.getBorder() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, comboBox.getBorder(), key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public MethodHandles.Lookup getLookupForStyling() {
|
||||||
|
// MethodHandles.lookup() is caller sensitive and must be invoked in this class,
|
||||||
|
// otherwise it is not possible to access protected fields in JRE superclass
|
||||||
|
return MethodHandles.lookup();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( Graphics g, JComponent c ) {
|
public void update( Graphics g, JComponent c ) {
|
||||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||||
@@ -448,7 +569,9 @@ public class FlatComboBoxUI
|
|||||||
int height = c.getHeight();
|
int height = c.getHeight();
|
||||||
int arrowX = arrowButton.getX();
|
int arrowX = arrowButton.getX();
|
||||||
int arrowWidth = arrowButton.getWidth();
|
int arrowWidth = arrowButton.getWidth();
|
||||||
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) && !"none".equals( buttonStyle );
|
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) &&
|
||||||
|
!"none".equals( buttonStyle ) &&
|
||||||
|
!isMacStyle();
|
||||||
boolean enabled = comboBox.isEnabled();
|
boolean enabled = comboBox.isEnabled();
|
||||||
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
|
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
|
||||||
|
|
||||||
@@ -459,26 +582,40 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
// paint arrow button background
|
// paint arrow button background
|
||||||
if( enabled && !isCellRenderer ) {
|
if( enabled && !isCellRenderer ) {
|
||||||
g2.setColor( paintButton
|
Color buttonColor = paintButton
|
||||||
? buttonEditableBackground
|
? buttonEditableBackground
|
||||||
: (buttonFocusedBackground != null || focusedBackground != null) && isPermanentFocusOwner( comboBox )
|
: (buttonFocusedBackground != null || focusedBackground != null) && isPermanentFocusOwner( comboBox )
|
||||||
? (buttonFocusedBackground != null ? buttonFocusedBackground : focusedBackground)
|
? (buttonFocusedBackground != null ? buttonFocusedBackground : focusedBackground)
|
||||||
: buttonBackground );
|
: buttonBackground;
|
||||||
Shape oldClip = g2.getClip();
|
if( buttonColor != null ) {
|
||||||
if( isLeftToRight )
|
g2.setColor( buttonColor );
|
||||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
if( isMacStyle() ) {
|
||||||
else
|
Insets insets = comboBox.getInsets();
|
||||||
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
int gap = scale( 2 );
|
||||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
FlatUIUtils.paintComponentBackground( g2, arrowX + gap, insets.top + gap,
|
||||||
g2.setClip( oldClip );
|
arrowWidth - (gap * 2), height - insets.top - insets.bottom - (gap * 2),
|
||||||
|
0, arc - focusWidth );
|
||||||
|
} else {
|
||||||
|
Shape oldClip = g2.getClip();
|
||||||
|
if( isLeftToRight )
|
||||||
|
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||||
|
else
|
||||||
|
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
||||||
|
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
||||||
|
g2.setClip( oldClip );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint vertical line between value and arrow button
|
// paint vertical line between value and arrow button
|
||||||
if( paintButton ) {
|
if( paintButton ) {
|
||||||
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
|
||||||
float lw = scale( 1f );
|
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
|
||||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
g2.setColor( separatorColor );
|
||||||
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2)) );
|
float lw = scale( buttonSeparatorWidth );
|
||||||
|
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||||
|
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2)) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,11 +641,20 @@ public class FlatComboBoxUI
|
|||||||
c.setBackground( getBackground( enabled ) );
|
c.setBackground( getBackground( enabled ) );
|
||||||
c.setForeground( getForeground( enabled ) );
|
c.setForeground( getForeground( enabled ) );
|
||||||
|
|
||||||
|
// make renderer component temporary non-opaque to avoid that renderer paints
|
||||||
|
// background outside of border if combobox uses larger arc for edges
|
||||||
|
// (e.g. FlatClientProperties.COMPONENT_ROUND_RECT is true)
|
||||||
|
if( c instanceof JComponent )
|
||||||
|
((JComponent)c).setOpaque( false );
|
||||||
|
|
||||||
boolean shouldValidate = (c instanceof JPanel);
|
boolean shouldValidate = (c instanceof JPanel);
|
||||||
|
|
||||||
paddingBorder.install( c );
|
paddingBorder.install( c, 0 );
|
||||||
currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate );
|
currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate );
|
||||||
paddingBorder.uninstall();
|
paddingBorder.uninstall();
|
||||||
|
|
||||||
|
if( c instanceof JComponent )
|
||||||
|
((JComponent)c).setOpaque( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -518,6 +664,9 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
protected Color getBackground( boolean enabled ) {
|
protected Color getBackground( boolean enabled ) {
|
||||||
if( enabled ) {
|
if( enabled ) {
|
||||||
|
if( FlatUIUtils.isAWTPeer( comboBox ) )
|
||||||
|
return background;
|
||||||
|
|
||||||
Color background = comboBox.getBackground();
|
Color background = comboBox.getBackground();
|
||||||
|
|
||||||
// always use explicitly set color
|
// always use explicitly set color
|
||||||
@@ -577,7 +726,7 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dimension getSizeForComponent( Component comp ) {
|
protected Dimension getSizeForComponent( Component comp ) {
|
||||||
paddingBorder.install( comp );
|
paddingBorder.install( comp, 0 );
|
||||||
Dimension size = super.getSizeForComponent( comp );
|
Dimension size = super.getSizeForComponent( comp );
|
||||||
paddingBorder.uninstall();
|
paddingBorder.uninstall();
|
||||||
return size;
|
return size;
|
||||||
@@ -593,13 +742,18 @@ public class FlatComboBoxUI
|
|||||||
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
|
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean isMacStyle() {
|
||||||
* @since 1.3
|
return "mac".equals( buttonStyle );
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
/** @since 1.3 */
|
||||||
public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) {
|
public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) {
|
||||||
if( comboBox.isEditable() ) {
|
if( comboBox.isEditable() ) {
|
||||||
|
if( FlatUIUtils.isPermanentFocusOwner( comboBox ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
||||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
return editorComponent != null && FlatUIUtils.isPermanentFocusOwner( editorComponent );
|
||||||
} else
|
} else
|
||||||
return FlatUIUtils.isPermanentFocusOwner( comboBox );
|
return FlatUIUtils.isPermanentFocusOwner( comboBox );
|
||||||
}
|
}
|
||||||
@@ -621,6 +775,26 @@ public class FlatComboBoxUI
|
|||||||
hoverForeground, hoverBackground, pressedForeground, pressedBackground );
|
hoverForeground, hoverBackground, pressedForeground, pressedBackground );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updateStyle() {
|
||||||
|
updateStyle( arrowType, buttonArrowColor, buttonDisabledArrowColor,
|
||||||
|
buttonHoverArrowColor, null, buttonPressedArrowColor, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getArrowWidth() {
|
||||||
|
return isMacStyle() ? (getWidth() % 2 == 0 ? 6 : 7) : super.getArrowWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getArrowThickness() {
|
||||||
|
return isMacStyle() ? 1.5f : super.getArrowThickness();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRoundBorderAutoXOffset() {
|
||||||
|
return isMacStyle() ? false : super.isRoundBorderAutoXOffset();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isHover() {
|
protected boolean isHover() {
|
||||||
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
||||||
@@ -638,6 +812,20 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
return super.getArrowColor();
|
return super.getArrowColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintArrow( Graphics2D g ) {
|
||||||
|
if( isMacStyle() && !comboBox.isEditable() ) {
|
||||||
|
// for style "mac", paint up and down arrows if combobox is not editable
|
||||||
|
int height = getHeight();
|
||||||
|
int h = Math.round( height / 2f );
|
||||||
|
FlatUIUtils.paintArrow( g, 0, 0, getWidth(), h, SwingConstants.NORTH, chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() + 1.25f );
|
||||||
|
FlatUIUtils.paintArrow( g, 0, height - h, getWidth(), h, SwingConstants.SOUTH, chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() - 1.25f );
|
||||||
|
} else
|
||||||
|
super.paintArrow( g );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatComboPopup -----------------------------------------------
|
//---- class FlatComboPopup -----------------------------------------------
|
||||||
@@ -672,12 +860,19 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for style "mac", add width of "checked item" icon
|
||||||
|
boolean isPopupOverComboBox = isPopupOverComboBox();
|
||||||
|
int selectedIndex = -1;
|
||||||
|
if( isPopupOverComboBox && (selectedIndex = comboBox.getSelectedIndex()) >= 0 )
|
||||||
|
displayWidth += MacCheckedItemIcon.INSTANCE.getIconWidth() + scale( CellPaddingBorder.MAC_STYLE_GAP );
|
||||||
|
|
||||||
// add width of vertical scroll bar
|
// add width of vertical scroll bar
|
||||||
JScrollBar verticalScrollBar = scroller.getVerticalScrollBar();
|
JScrollBar verticalScrollBar = scroller.getVerticalScrollBar();
|
||||||
if( verticalScrollBar != null )
|
if( verticalScrollBar != null )
|
||||||
displayWidth += verticalScrollBar.getPreferredSize().width;
|
displayWidth += verticalScrollBar.getPreferredSize().width;
|
||||||
|
|
||||||
// make popup wider if necessary
|
// make popup wider if necessary
|
||||||
|
int pw0 = pw;
|
||||||
if( displayWidth > pw ) {
|
if( displayWidth > pw ) {
|
||||||
// limit popup width to screen width
|
// limit popup width to screen width
|
||||||
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
||||||
@@ -697,6 +892,30 @@ public class FlatComboBoxUI
|
|||||||
px -= diff;
|
px -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for style "mac", place popup over combobox
|
||||||
|
Rectangle cellBounds;
|
||||||
|
if( isPopupOverComboBox && selectedIndex >= 0 &&
|
||||||
|
(cellBounds = list.getCellBounds( 0, 0 )) != null )
|
||||||
|
{
|
||||||
|
Insets comboBoxInsets = comboBox.getInsets();
|
||||||
|
Insets listInsets = list.getInsets();
|
||||||
|
Insets popupInsets = getInsets();
|
||||||
|
|
||||||
|
// position popup so that selected item is at same Y position as combobox
|
||||||
|
py -= (cellBounds.height * (selectedIndex + 1)) + comboBoxInsets.top + listInsets.top + popupInsets.top;
|
||||||
|
|
||||||
|
// position popup slightly to the left so that a small part of the right side of the combobox stays visible
|
||||||
|
int offset = Math.min( pw - pw0, MacCheckedItemIcon.INSTANCE.getIconWidth() ) + scale( 4 );
|
||||||
|
if( comboBox.getComponentOrientation().isLeftToRight() )
|
||||||
|
px -= offset + comboBoxInsets.right + listInsets.right;
|
||||||
|
else
|
||||||
|
px += offset + comboBoxInsets.left + listInsets.left;
|
||||||
|
|
||||||
|
// not invoking super.computePopupBounds() here to let
|
||||||
|
// JPopupMenu.adjustPopupLocationToFitScreen() fix the location if necessary
|
||||||
|
return new Rectangle( px, py, pw, ph );
|
||||||
|
}
|
||||||
|
|
||||||
return super.computePopupBounds( px, py, pw, ph );
|
return super.computePopupBounds( px, py, pw, ph );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,18 +923,37 @@ public class FlatComboBoxUI
|
|||||||
protected void configurePopup() {
|
protected void configurePopup() {
|
||||||
super.configurePopup();
|
super.configurePopup();
|
||||||
|
|
||||||
|
// make opaque to avoid that background shines thru border (e.g. at 150% scaling)
|
||||||
|
setOpaque( true );
|
||||||
|
|
||||||
|
// set popup border
|
||||||
|
// use non-UIResource to avoid that it is overwritten when making
|
||||||
|
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||||
Border border = UIManager.getBorder( "PopupMenu.border" );
|
Border border = UIManager.getBorder( "PopupMenu.border" );
|
||||||
if( border != null )
|
if( border != null )
|
||||||
setBorder( border );
|
setBorder( FlatUIUtils.nonUIResource( border ) );
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureList() {
|
|
||||||
super.configureList();
|
|
||||||
|
|
||||||
list.setCellRenderer( new PopupListCellRenderer() );
|
list.setCellRenderer( new PopupListCellRenderer() );
|
||||||
|
updateStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateStyle() {
|
||||||
if( popupBackground != null )
|
if( popupBackground != null )
|
||||||
list.setBackground( popupBackground );
|
list.setBackground( popupBackground );
|
||||||
|
|
||||||
|
// set popup background because it may shine thru when scaled (e.g. at 150%)
|
||||||
|
// use non-UIResource to avoid that it is overwritten when making
|
||||||
|
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||||
|
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
||||||
|
|
||||||
|
scroller.setViewportBorder( (popupInsets != null) ? new FlatEmptyBorder( popupInsets ) : null );
|
||||||
|
scroller.setOpaque( false );
|
||||||
|
|
||||||
|
if( list.getUI() instanceof FlatListUI ) {
|
||||||
|
FlatListUI ui = (FlatListUI) list.getUI();
|
||||||
|
ui.selectionInsets = selectionInsets;
|
||||||
|
ui.selectionArc = selectionArc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -736,12 +974,36 @@ public class FlatComboBoxUI
|
|||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show( Component invoker, int x, int y ) {
|
||||||
|
// Java 8: fix y coordinate if popup is shown above the combobox
|
||||||
|
// (already fixed in Java 9+ https://bugs.openjdk.java.net/browse/JDK-7072653)
|
||||||
|
if( y < 0 && !SystemInfo.isJava_9_orLater ) {
|
||||||
|
Border popupBorder = getBorder();
|
||||||
|
if( popupBorder != null ) {
|
||||||
|
Insets insets = popupBorder.getBorderInsets( this );
|
||||||
|
y -= insets.top + insets.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.show( invoker, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintChildren( Graphics g ) {
|
protected void paintChildren( Graphics g ) {
|
||||||
super.paintChildren( g );
|
super.paintChildren( g );
|
||||||
paddingBorder.uninstall();
|
paddingBorder.uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPopupOverComboBox() {
|
||||||
|
return isMacStyle() &&
|
||||||
|
!comboBox.isEditable() &&
|
||||||
|
comboBox.getItemCount() > 0 &&
|
||||||
|
comboBox.getItemCount() <= comboBox.getMaximumRowCount() &&
|
||||||
|
// for compatibility with Aqua Laf
|
||||||
|
!clientPropertyBoolean( comboBox, "JComboBox.isPopDown", false );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class PopupListCellRenderer -----
|
//---- class PopupListCellRenderer -----
|
||||||
|
|
||||||
private class PopupListCellRenderer
|
private class PopupListCellRenderer
|
||||||
@@ -759,7 +1021,14 @@ public class FlatComboBoxUI
|
|||||||
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
|
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
|
||||||
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
||||||
|
|
||||||
paddingBorder.install( c );
|
// style "mac"
|
||||||
|
if( isPopupOverComboBox() && c instanceof JComponent ) {
|
||||||
|
int selectedIndex = comboBox.getSelectedIndex();
|
||||||
|
((JComponent)c).putClientProperty( CellPaddingBorder.KEY_MAC_STYLE_HINT,
|
||||||
|
(selectedIndex >= 0) ? (index == selectedIndex) : null );
|
||||||
|
}
|
||||||
|
|
||||||
|
paddingBorder.install( c, Math.round( FlatUIUtils.getBorderFocusWidth( comboBox ) ) );
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -775,22 +1044,33 @@ public class FlatComboBoxUI
|
|||||||
* which vertically aligns text in popup list with text in combobox.
|
* which vertically aligns text in popup list with text in combobox.
|
||||||
* <p>
|
* <p>
|
||||||
* The renderer border is painted on the outer side of this border.
|
* The renderer border is painted on the outer side of this border.
|
||||||
|
* <p>
|
||||||
|
* For button style "mac", also used to increase insets on left side for
|
||||||
|
* "checked item" icon and to paint "checked item" icon for selected combobox item.
|
||||||
*/
|
*/
|
||||||
private static class CellPaddingBorder
|
private static class CellPaddingBorder
|
||||||
extends AbstractBorder
|
extends AbstractBorder
|
||||||
{
|
{
|
||||||
private final Insets padding;
|
static final String KEY_MAC_STYLE_HINT = "FlatLaf.internal.FlatComboBoxUI.macStyleHint";
|
||||||
|
static final int MAC_STYLE_GAP = 4;
|
||||||
|
|
||||||
|
private Insets padding;
|
||||||
private JComponent rendererComponent;
|
private JComponent rendererComponent;
|
||||||
private Border rendererBorder;
|
private Border rendererBorder;
|
||||||
|
private int focusWidth;
|
||||||
|
|
||||||
CellPaddingBorder( Insets padding ) {
|
CellPaddingBorder( Insets padding ) {
|
||||||
this.padding = padding;
|
this.padding = padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void install( Component c ) {
|
// using synchronized to avoid problems with code that modifies combo box
|
||||||
|
// (model, selection, etc) not on AWT thread (which should be not done)
|
||||||
|
synchronized void install( Component c, int focusWidth ) {
|
||||||
if( !(c instanceof JComponent) )
|
if( !(c instanceof JComponent) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
this.focusWidth = focusWidth;
|
||||||
|
|
||||||
JComponent jc = (JComponent) c;
|
JComponent jc = (JComponent) c;
|
||||||
Border oldBorder = jc.getBorder();
|
Border oldBorder = jc.getBorder();
|
||||||
if( oldBorder == this )
|
if( oldBorder == this )
|
||||||
@@ -810,7 +1090,7 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
// remember old border and replace it
|
// remember old border and replace it
|
||||||
rendererBorder = jc.getBorder();
|
rendererBorder = jc.getBorder();
|
||||||
rendererComponent.setBorder( this );
|
jc.setBorder( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -819,10 +1099,12 @@ public class FlatComboBoxUI
|
|||||||
* there is no single place to uninstall it.
|
* there is no single place to uninstall it.
|
||||||
* This is the reason why this method is called from various places.
|
* This is the reason why this method is called from various places.
|
||||||
*/
|
*/
|
||||||
void uninstall() {
|
synchronized void uninstall() {
|
||||||
if( rendererComponent == null )
|
if( rendererComponent == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
rendererComponent.putClientProperty( KEY_MAC_STYLE_HINT, null );
|
||||||
|
|
||||||
if( rendererComponent.getBorder() == this )
|
if( rendererComponent.getBorder() == this )
|
||||||
rendererComponent.setBorder( rendererBorder );
|
rendererComponent.setBorder( rendererBorder );
|
||||||
rendererComponent = null;
|
rendererComponent = null;
|
||||||
@@ -830,9 +1112,9 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
synchronized public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
Insets padding = scale( this.padding );
|
Insets padding = scale( this.padding );
|
||||||
if( rendererBorder != null ) {
|
if( rendererBorder != null && !(rendererBorder instanceof CellPaddingBorder) ) {
|
||||||
Insets insideInsets = rendererBorder.getBorderInsets( c );
|
Insets insideInsets = rendererBorder.getBorderInsets( c );
|
||||||
insets.top = Math.max( padding.top, insideInsets.top );
|
insets.top = Math.max( padding.top, insideInsets.top );
|
||||||
insets.left = Math.max( padding.left, insideInsets.left );
|
insets.left = Math.max( padding.left, insideInsets.left );
|
||||||
@@ -844,6 +1126,24 @@ public class FlatComboBoxUI
|
|||||||
insets.bottom = padding.bottom;
|
insets.bottom = padding.bottom;
|
||||||
insets.right = padding.right;
|
insets.right = padding.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if used in popup list, add focus width for exact vertical alignment
|
||||||
|
// of text in popup list with text in combobox
|
||||||
|
insets.left += focusWidth;
|
||||||
|
insets.right += focusWidth;
|
||||||
|
|
||||||
|
// style "mac"
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Boolean macStyleHint = clientPropertyBooleanStrict( (JComponent) c, KEY_MAC_STYLE_HINT, null );
|
||||||
|
if( macStyleHint != null ) {
|
||||||
|
int indent = MacCheckedItemIcon.INSTANCE.getIconWidth() + scale( MAC_STYLE_GAP );
|
||||||
|
if( c.getComponentOrientation().isLeftToRight() )
|
||||||
|
insets.left += indent;
|
||||||
|
else
|
||||||
|
insets.right += indent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return insets;
|
return insets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,6 +1151,35 @@ public class FlatComboBoxUI
|
|||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
if( rendererBorder != null )
|
if( rendererBorder != null )
|
||||||
rendererBorder.paintBorder( c, g, x, y, width, height );
|
rendererBorder.paintBorder( c, g, x, y, width, height );
|
||||||
|
|
||||||
|
// style "mac"
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Boolean macStyleHint = clientPropertyBooleanStrict( (JComponent) c, KEY_MAC_STYLE_HINT, null );
|
||||||
|
if( macStyleHint == Boolean.TRUE ) {
|
||||||
|
// paint "checked item" icon
|
||||||
|
int ix = c.getComponentOrientation().isLeftToRight()
|
||||||
|
? x + scale( padding.left )
|
||||||
|
: x + width - scale( padding.right ) - MacCheckedItemIcon.INSTANCE.getIconWidth();
|
||||||
|
MacCheckedItemIcon.INSTANCE.paintIcon( c, g, ix, y + ((height - MacCheckedItemIcon.INSTANCE.getIconHeight()) / 2) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class MacCheckedItemIcon -------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use for style "mac" to mark checked item.
|
||||||
|
*/
|
||||||
|
private static class MacCheckedItemIcon
|
||||||
|
extends FlatCheckBoxMenuItemIcon
|
||||||
|
{
|
||||||
|
static MacCheckedItemIcon INSTANCE = new MacCheckedItemIcon();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||||
|
g2.setColor( c.getForeground() );
|
||||||
|
paintCheckmark( g2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ import java.awt.Image;
|
|||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.RadialGradientPaint;
|
import java.awt.RadialGradientPaint;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -40,14 +43,17 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatDropShadowBorder
|
public class FlatDropShadowBorder
|
||||||
extends FlatEmptyBorder
|
extends FlatEmptyBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
private final Color shadowColor;
|
@Styleable protected Color shadowColor;
|
||||||
private final Insets shadowInsets;
|
@Styleable protected Insets shadowInsets;
|
||||||
private final float shadowOpacity;
|
@Styleable protected float shadowOpacity;
|
||||||
|
|
||||||
private final int shadowSize;
|
private int shadowSize;
|
||||||
private Image shadowImage;
|
private Image shadowImage;
|
||||||
private Color lastShadowColor;
|
private Color lastShadowColor;
|
||||||
|
private float lastShadowOpacity;
|
||||||
|
private int lastShadowSize;
|
||||||
private double lastSystemScaleFactor;
|
private double lastSystemScaleFactor;
|
||||||
private float lastUserScaleFactor;
|
private float lastUserScaleFactor;
|
||||||
|
|
||||||
@@ -64,17 +70,49 @@ public class FlatDropShadowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) {
|
public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) {
|
||||||
super( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ),
|
super( nonNegativeInsets( shadowInsets ) );
|
||||||
Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) );
|
|
||||||
this.shadowColor = shadowColor;
|
this.shadowColor = shadowColor;
|
||||||
this.shadowInsets = shadowInsets;
|
this.shadowInsets = shadowInsets;
|
||||||
this.shadowOpacity = shadowOpacity;
|
this.shadowOpacity = 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.left, shadowInsets.right ),
|
||||||
Math.max( shadowInsets.top, shadowInsets.bottom ) );
|
Math.max( shadowInsets.top, shadowInsets.bottom ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
Object oldValue = FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
if( key.equals( "shadowInsets" ) ) {
|
||||||
|
applyStyleProperty( nonNegativeInsets( shadowInsets ) );
|
||||||
|
shadowSize = maxInset( shadowInsets );
|
||||||
|
}
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
if( shadowSize <= 0 )
|
if( shadowSize <= 0 )
|
||||||
@@ -91,12 +129,16 @@ public class FlatDropShadowBorder
|
|||||||
float userScaleFactor = UIScale.getUserScaleFactor();
|
float userScaleFactor = UIScale.getUserScaleFactor();
|
||||||
if( shadowImage == null ||
|
if( shadowImage == null ||
|
||||||
!shadowColor.equals( lastShadowColor ) ||
|
!shadowColor.equals( lastShadowColor ) ||
|
||||||
|
lastShadowOpacity != shadowOpacity ||
|
||||||
|
lastShadowSize != shadowSize ||
|
||||||
lastSystemScaleFactor != scaleFactor ||
|
lastSystemScaleFactor != scaleFactor ||
|
||||||
lastUserScaleFactor != userScaleFactor )
|
lastUserScaleFactor != userScaleFactor )
|
||||||
{
|
{
|
||||||
shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity,
|
shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity,
|
||||||
(float) (scaleFactor * userScaleFactor) );
|
(float) (scaleFactor * userScaleFactor) );
|
||||||
lastShadowColor = shadowColor;
|
lastShadowColor = shadowColor;
|
||||||
|
lastShadowOpacity = shadowOpacity;
|
||||||
|
lastShadowSize = shadowSize;
|
||||||
lastSystemScaleFactor = scaleFactor;
|
lastSystemScaleFactor = scaleFactor;
|
||||||
lastUserScaleFactor = userScaleFactor;
|
lastUserScaleFactor = userScaleFactor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,14 +24,19 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
||||||
|
import javax.swing.text.Caret;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
||||||
@@ -39,8 +44,8 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
|||||||
* <!-- BasicEditorPaneUI -->
|
* <!-- BasicEditorPaneUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault EditorPane.font Font
|
* @uiDefault EditorPane.font Font
|
||||||
* @uiDefault EditorPane.background Color also used if not editable
|
* @uiDefault EditorPane.background Color
|
||||||
* @uiDefault EditorPane.foreground Color
|
* @uiDefault EditorPane.foreground Color also used if not editable
|
||||||
* @uiDefault EditorPane.caretForeground Color
|
* @uiDefault EditorPane.caretForeground Color
|
||||||
* @uiDefault EditorPane.selectionBackground Color
|
* @uiDefault EditorPane.selectionBackground Color
|
||||||
* @uiDefault EditorPane.selectionForeground Color
|
* @uiDefault EditorPane.selectionForeground Color
|
||||||
@@ -61,20 +66,35 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
|||||||
*/
|
*/
|
||||||
public class FlatEditorPaneUI
|
public class FlatEditorPaneUI
|
||||||
extends BasicEditorPaneUI
|
extends BasicEditorPaneUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected boolean isIntelliJTheme;
|
protected boolean isIntelliJTheme;
|
||||||
protected Color focusedBackground;
|
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 Insets defaultMargin;
|
||||||
|
|
||||||
private Object oldHonorDisplayProperties;
|
private Object oldHonorDisplayProperties;
|
||||||
private FocusListener focusListener;
|
private FocusListener focusListener;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatEditorPaneUI();
|
return new FlatEditorPaneUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -82,6 +102,9 @@ public class FlatEditorPaneUI
|
|||||||
String prefix = getPropertyPrefix();
|
String prefix = getPropertyPrefix();
|
||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
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" );
|
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
|
||||||
|
|
||||||
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
||||||
@@ -95,8 +118,16 @@ public class FlatEditorPaneUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
background = null;
|
||||||
|
disabledBackground = null;
|
||||||
|
inactiveBackground = null;
|
||||||
focusedBackground = null;
|
focusedBackground = null;
|
||||||
|
|
||||||
|
oldDisabledBackground = null;
|
||||||
|
oldInactiveBackground = null;
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
|
||||||
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
|
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,19 +149,78 @@ public class FlatEditorPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void propertyChange( PropertyChangeEvent e ) {
|
protected Caret createCaret() {
|
||||||
super.propertyChange( e );
|
return new FlatCaret( null, false );
|
||||||
propertyChange( getComponent(), e );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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() ) {
|
switch( e.getPropertyName() ) {
|
||||||
case FlatClientProperties.MINIMUM_WIDTH:
|
case FlatClientProperties.MINIMUM_WIDTH:
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FlatClientProperties.STYLE:
|
||||||
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
|
installStyle.run();
|
||||||
|
c.revalidate();
|
||||||
|
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
|
@Override
|
||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth, defaultMargin );
|
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth, defaultMargin );
|
||||||
|
|||||||
@@ -50,7 +50,13 @@ public class FlatEmptyBorder
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
boolean leftToRight = left == right || c.getComponentOrientation().isLeftToRight();
|
return scaleInsets( c, insets, top, left, bottom, right );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Insets scaleInsets( Component c, Insets insets,
|
||||||
|
int top, int left, int bottom, int right )
|
||||||
|
{
|
||||||
|
boolean leftToRight = left == right || c == null || c.getComponentOrientation().isLeftToRight();
|
||||||
insets.left = scale( leftToRight ? left : right );
|
insets.left = scale( leftToRight ? left : right );
|
||||||
insets.top = scale( top );
|
insets.top = scale( top );
|
||||||
insets.right = scale( leftToRight ? right : left );
|
insets.right = scale( leftToRight ? right : left );
|
||||||
@@ -61,4 +67,18 @@ public class FlatEmptyBorder
|
|||||||
public Insets getUnscaledBorderInsets() {
|
public Insets getUnscaledBorderInsets() {
|
||||||
return super.getBorderInsets();
|
return super.getBorderInsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object applyStyleProperty( Insets insets ) {
|
||||||
|
Insets oldInsets = getUnscaledBorderInsets();
|
||||||
|
top = insets.top;
|
||||||
|
left = insets.left;
|
||||||
|
bottom = insets.bottom;
|
||||||
|
right = insets.right;
|
||||||
|
return oldInsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Insets getStyleableValue() {
|
||||||
|
return new Insets( top, left, bottom, right );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,21 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
@@ -34,12 +44,16 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.JToolBar;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.filechooser.FileSystemView;
|
||||||
import javax.swing.filechooser.FileView;
|
import javax.swing.filechooser.FileView;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.metal.MetalFileChooserUI;
|
import javax.swing.plaf.metal.MetalFileChooserUI;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -133,12 +147,21 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault FileChooser.listViewActionLabelText String
|
* @uiDefault FileChooser.listViewActionLabelText String
|
||||||
* @uiDefault FileChooser.detailsViewActionLabelText String
|
* @uiDefault FileChooser.detailsViewActionLabelText String
|
||||||
*
|
*
|
||||||
|
* <!-- FlatFileChooserUI -->
|
||||||
|
*
|
||||||
|
* @uiDefault FileChooser.shortcuts.buttonSize Dimension optional; default is 84,64
|
||||||
|
* @uiDefault FileChooser.shortcuts.iconSize Dimension optional; default is 32,32
|
||||||
|
* @uiDefault FileChooser.shortcuts.filesFunction Function<File[], File[]>
|
||||||
|
* @uiDefault FileChooser.shortcuts.displayNameFunction Function<File, String>
|
||||||
|
* @uiDefault FileChooser.shortcuts.iconFunction Function<File, Icon>
|
||||||
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatFileChooserUI
|
public class FlatFileChooserUI
|
||||||
extends MetalFileChooserUI
|
extends MetalFileChooserUI
|
||||||
{
|
{
|
||||||
private final FlatFileView fileView = new FlatFileView();
|
private final FlatFileView fileView = new FlatFileView();
|
||||||
|
private FlatShortcutsPanel shortcutsPanel;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatFileChooserUI( (JFileChooser) c );
|
return new FlatFileChooserUI( (JFileChooser) c );
|
||||||
@@ -153,6 +176,25 @@ public class FlatFileChooserUI
|
|||||||
super.installComponents( fc );
|
super.installComponents( fc );
|
||||||
|
|
||||||
patchUI( fc );
|
patchUI( fc );
|
||||||
|
|
||||||
|
if( !UIManager.getBoolean( "FileChooser.noPlacesBar" ) ) { // same as in Windows L&F
|
||||||
|
FlatShortcutsPanel panel = createShortcutsPanel( fc );
|
||||||
|
if( panel.getComponentCount() > 0 ) {
|
||||||
|
shortcutsPanel = panel;
|
||||||
|
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 ) {
|
private void patchUI( JFileChooser fc ) {
|
||||||
@@ -192,6 +234,27 @@ public class FlatFileChooserUI
|
|||||||
} catch( ArrayIndexOutOfBoundsException ex ) {
|
} catch( ArrayIndexOutOfBoundsException ex ) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put north, center and south components into a new panel so that
|
||||||
|
// the shortcuts panel (at west) gets full height
|
||||||
|
LayoutManager layout = fc.getLayout();
|
||||||
|
if( layout instanceof BorderLayout ) {
|
||||||
|
BorderLayout borderLayout = (BorderLayout) layout;
|
||||||
|
borderLayout.setHgap( 8 );
|
||||||
|
|
||||||
|
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
|
||||||
|
Component lineEnd = borderLayout.getLayoutComponent( BorderLayout.LINE_END );
|
||||||
|
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
|
||||||
|
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
|
||||||
|
if( north != null && lineEnd != null && center != null && south != null ) {
|
||||||
|
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
|
||||||
|
p.add( north, BorderLayout.NORTH );
|
||||||
|
p.add( lineEnd, BorderLayout.LINE_END );
|
||||||
|
p.add( center, BorderLayout.CENTER );
|
||||||
|
p.add( south, BorderLayout.SOUTH );
|
||||||
|
fc.add( p, BorderLayout.CENTER );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -250,9 +313,19 @@ public class FlatFileChooserUI
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
protected FlatShortcutsPanel createShortcutsPanel( JFileChooser fc ) {
|
||||||
|
return new FlatShortcutsPanel( fc );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
return UIScale.scale( super.getPreferredSize( c ) );
|
Dimension prefSize = super.getPreferredSize( c );
|
||||||
|
Dimension minSize = getMinimumSize( c );
|
||||||
|
int shortcutsPanelWidth = (shortcutsPanel != null) ? shortcutsPanel.getPreferredSize().width : 0;
|
||||||
|
return new Dimension(
|
||||||
|
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
|
||||||
|
Math.max( prefSize.height, minSize.height ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -262,12 +335,23 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileView getFileView( JFileChooser fc ) {
|
public FileView getFileView( JFileChooser fc ) {
|
||||||
return fileView;
|
return doNotUseSystemIcons() ? super.getFileView( fc ) : fileView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearIconCache() {
|
public void clearIconCache() {
|
||||||
fileView.clearIconCache();
|
if( doNotUseSystemIcons() )
|
||||||
|
super.clearIconCache();
|
||||||
|
else
|
||||||
|
fileView.clearIconCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doNotUseSystemIcons() {
|
||||||
|
// Java 17 32bit craches on Windows when using system icons
|
||||||
|
// fixed in Java 18+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
||||||
|
return SystemInfo.isWindows &&
|
||||||
|
SystemInfo.isX86 &&
|
||||||
|
(SystemInfo.isJava_17_orLater && !SystemInfo.isJava_18_orLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatFileView -------------------------------------------------
|
//---- class FlatFileView -------------------------------------------------
|
||||||
@@ -305,4 +389,234 @@ public class FlatFileChooserUI
|
|||||||
return icon;
|
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;
|
||||||
|
|
||||||
|
@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 );
|
||||||
|
this.files = files;
|
||||||
|
|
||||||
|
// create toolbar buttons
|
||||||
|
buttons = new JToggleButton[files.length];
|
||||||
|
buttonGroup = new ButtonGroup();
|
||||||
|
for( int i = 0; i < files.length; i++ ) {
|
||||||
|
// wrap drive path
|
||||||
|
if( fsv.isFileSystemRoot( files[i] ) )
|
||||||
|
files[i] = fsv.createFileObject( files[i].getAbsolutePath() );
|
||||||
|
|
||||||
|
File file = files[i];
|
||||||
|
String name = getDisplayName( fsv, file );
|
||||||
|
Icon icon = getIcon( fsv, file );
|
||||||
|
|
||||||
|
// 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 );
|
||||||
|
button.addActionListener( e -> {
|
||||||
|
fc.setCurrentDirectory( file );
|
||||||
|
} );
|
||||||
|
|
||||||
|
add( button );
|
||||||
|
buttonGroup.add( button );
|
||||||
|
buttons[i] = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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( IllegalAccessException ex ) {
|
||||||
|
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
|
||||||
|
// get system icon in default size 16x16
|
||||||
|
return fsv.getSystemIcon( file );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
* @uiDefault Component.isIntelliJTheme boolean
|
* @uiDefault Component.isIntelliJTheme boolean
|
||||||
* @uiDefault FormattedTextField.placeholderForeground Color
|
* @uiDefault FormattedTextField.placeholderForeground Color
|
||||||
* @uiDefault FormattedTextField.focusedBackground Color optional
|
* @uiDefault FormattedTextField.focusedBackground Color optional
|
||||||
|
* @uiDefault FormattedTextField.iconTextGap int optional, default is 4
|
||||||
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
||||||
* @uiDefault TextComponent.selectAllOnMouseClick boolean
|
* @uiDefault TextComponent.selectAllOnMouseClick boolean
|
||||||
*
|
*
|
||||||
@@ -59,4 +60,10 @@ public class FlatFormattedTextFieldUI
|
|||||||
protected String getPropertyPrefix() {
|
protected String getPropertyPrefix() {
|
||||||
return "FormattedTextField";
|
return "FormattedTextField";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
String getStyleType() {
|
||||||
|
return "FormattedTextField";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
@@ -146,6 +147,19 @@ public class FlatInternalFrameTitlePane
|
|||||||
closeButton.setVisible( frame.isClosable() );
|
closeButton.setVisible( frame.isClosable() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle getFrameIconBounds() {
|
||||||
|
Icon icon = titleLabel.getIcon();
|
||||||
|
if( icon == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int iconWidth = icon.getIconWidth();
|
||||||
|
int iconHeight = icon.getIconHeight();
|
||||||
|
boolean leftToRight = titleLabel.getComponentOrientation().isLeftToRight();
|
||||||
|
int x = titleLabel.getX() + (leftToRight ? 0 : (titleLabel.getWidth() - iconWidth));
|
||||||
|
int y = titleLabel.getY() + ((titleLabel.getHeight() - iconHeight) / 2);
|
||||||
|
return new Rectangle( x, y, iconWidth, iconHeight );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does nothing because FlatLaf internal frames do not have system menus.
|
* Does nothing because FlatLaf internal frames do not have system menus.
|
||||||
*/
|
*/
|
||||||
@@ -199,6 +213,13 @@ public class FlatInternalFrameTitlePane
|
|||||||
case "componentOrientation":
|
case "componentOrientation":
|
||||||
applyComponentOrientation( frame.getComponentOrientation() );
|
applyComponentOrientation( frame.getComponentOrientation() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "opaque":
|
||||||
|
// Do not invoke super.propertyChange() here because it always
|
||||||
|
// invokes repaint(), which would cause endless repainting.
|
||||||
|
// The opaque flag is temporary changed in FlatUIUtils.hasOpaqueBeenExplicitlySet(),
|
||||||
|
// invoked from FlatInternalFrameUI.update().
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
|
|||||||
@@ -22,12 +22,22 @@ import java.awt.Component;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JInternalFrame;
|
import javax.swing.JInternalFrame;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.MouseInputAdapter;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
|
||||||
@@ -83,9 +93,13 @@ import javax.swing.plaf.basic.BasicInternalFrameUI;
|
|||||||
*/
|
*/
|
||||||
public class FlatInternalFrameUI
|
public class FlatInternalFrameUI
|
||||||
extends BasicInternalFrameUI
|
extends BasicInternalFrameUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected FlatWindowResizer windowResizer;
|
protected FlatWindowResizer windowResizer;
|
||||||
|
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
private AtomicBoolean borderShared;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatInternalFrameUI( (JInternalFrame) c );
|
return new FlatInternalFrameUI( (JInternalFrame) c );
|
||||||
}
|
}
|
||||||
@@ -101,6 +115,8 @@ public class FlatInternalFrameUI
|
|||||||
LookAndFeel.installProperty( frame, "opaque", false );
|
LookAndFeel.installProperty( frame, "opaque", false );
|
||||||
|
|
||||||
windowResizer = createWindowResizer();
|
windowResizer = createWindowResizer();
|
||||||
|
|
||||||
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,6 +127,9 @@ public class FlatInternalFrameUI
|
|||||||
windowResizer.uninstall();
|
windowResizer.uninstall();
|
||||||
windowResizer = null;
|
windowResizer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
borderShared = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -122,15 +141,80 @@ public class FlatInternalFrameUI
|
|||||||
return new FlatWindowResizer.InternalFrameResizer( frame, this::getDesktopManager );
|
return new FlatWindowResizer.InternalFrameResizer( frame, this::getDesktopManager );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MouseInputAdapter createBorderListener( JInternalFrame w ) {
|
||||||
|
return new FlatBorderListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
|
return FlatStylingSupport.createPropertyChangeListener( frame, this::installStyle,
|
||||||
|
super.createPropertyChangeListener() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( frame, "InternalFrame" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
if( borderShared == null )
|
||||||
|
borderShared = new AtomicBoolean( true );
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, frame, borderShared );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this, frame.getBorder() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, frame.getBorder(), key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( Graphics g, JComponent c ) {
|
||||||
|
// The internal frame actually should be opaque and fill its background,
|
||||||
|
// but it must be non-opaque to allow translucent resize handles (outside of visual bounds).
|
||||||
|
// To avoid that parent may shine through internal frame (e.g. if menu bar is non-opaque),
|
||||||
|
// fill background excluding insets (translucent resize handles),
|
||||||
|
// but only if opaque was not set explicitly by application to false.
|
||||||
|
// If applications has set internal frame opacity to false, do not fill background (for compatibility).
|
||||||
|
if( !c.isOpaque() && !FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) ) {
|
||||||
|
Insets insets = c.getInsets();
|
||||||
|
|
||||||
|
g.setColor( c.getBackground() );
|
||||||
|
g.fillRect( insets.left, insets.top,
|
||||||
|
c.getWidth() - insets.left - insets.right,
|
||||||
|
c.getHeight() - insets.top - insets.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.update( g, c );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatInternalFrameBorder --------------------------------------
|
//---- class FlatInternalFrameBorder --------------------------------------
|
||||||
|
|
||||||
public static class FlatInternalFrameBorder
|
public static class FlatInternalFrameBorder
|
||||||
extends FlatEmptyBorder
|
extends FlatEmptyBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
private final Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
@Styleable protected Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
||||||
private final Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
@Styleable protected Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
||||||
private final int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
@Styleable protected int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
||||||
private final boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
@Styleable protected boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
||||||
|
|
||||||
private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder(
|
private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder(
|
||||||
UIManager.getColor( "InternalFrame.activeDropShadowColor" ),
|
UIManager.getColor( "InternalFrame.activeDropShadowColor" ),
|
||||||
@@ -145,6 +229,53 @@ public class FlatInternalFrameUI
|
|||||||
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
switch( key ) {
|
||||||
|
case "borderMargins": return applyStyleProperty( (Insets) value );
|
||||||
|
|
||||||
|
case "activeDropShadowColor": return activeDropShadowBorder.applyStyleProperty( "shadowColor", value );
|
||||||
|
case "activeDropShadowInsets": return activeDropShadowBorder.applyStyleProperty( "shadowInsets", value );
|
||||||
|
case "activeDropShadowOpacity": return activeDropShadowBorder.applyStyleProperty( "shadowOpacity", value );
|
||||||
|
case "inactiveDropShadowColor": return inactiveDropShadowBorder.applyStyleProperty( "shadowColor", value );
|
||||||
|
case "inactiveDropShadowInsets": return inactiveDropShadowBorder.applyStyleProperty( "shadowInsets", value );
|
||||||
|
case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.applyStyleProperty( "shadowOpacity", value );
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
Map<String, Class<?>> infos = new FlatStylingSupport.StyleableInfosMap<>();
|
||||||
|
FlatStylingSupport.collectAnnotatedStyleableInfos( this, infos );
|
||||||
|
infos.put( "borderMargins", Insets.class );
|
||||||
|
infos.put( "activeDropShadowColor", Color.class );
|
||||||
|
infos.put( "activeDropShadowInsets", Insets.class );
|
||||||
|
infos.put( "activeDropShadowOpacity", float.class );
|
||||||
|
infos.put( "inactiveDropShadowColor", Color.class );
|
||||||
|
infos.put( "inactiveDropShadowInsets", Insets.class );
|
||||||
|
infos.put( "inactiveDropShadowOpacity", float.class );
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
switch( key ) {
|
||||||
|
case "borderMargins": return getStyleableValue();
|
||||||
|
|
||||||
|
case "activeDropShadowColor": return activeDropShadowBorder.getStyleableValue( "shadowColor" );
|
||||||
|
case "activeDropShadowInsets": return activeDropShadowBorder.getStyleableValue( "shadowInsets" );
|
||||||
|
case "activeDropShadowOpacity": return activeDropShadowBorder.getStyleableValue( "shadowOpacity" );
|
||||||
|
case "inactiveDropShadowColor": return inactiveDropShadowBorder.getStyleableValue( "shadowColor" );
|
||||||
|
case "inactiveDropShadowInsets": return inactiveDropShadowBorder.getStyleableValue( "shadowInsets" );
|
||||||
|
case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.getStyleableValue( "shadowOpacity" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
||||||
@@ -195,4 +326,27 @@ public class FlatInternalFrameUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatBorderListener -------------------------------------------
|
||||||
|
|
||||||
|
/** @since 1.6 */
|
||||||
|
protected class FlatBorderListener
|
||||||
|
extends BorderListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mouseClicked( MouseEvent e ) {
|
||||||
|
if( e.getClickCount() == 2 && !frame.isIcon() &&
|
||||||
|
e.getSource() instanceof FlatInternalFrameTitlePane )
|
||||||
|
{
|
||||||
|
Rectangle iconBounds = ((FlatInternalFrameTitlePane)e.getSource()).getFrameIconBounds();
|
||||||
|
if( iconBounds != null && iconBounds.contains( e.getX(), e.getY() ) ) {
|
||||||
|
if( frame.isClosable() )
|
||||||
|
frame.doDefaultCloseAction();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.mouseClicked( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.awt.Rectangle;
|
|||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -33,8 +34,12 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicHTML;
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
import javax.swing.plaf.basic.BasicLabelUI;
|
import javax.swing.plaf.basic.BasicLabelUI;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
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.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,13 +59,30 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatLabelUI
|
public class FlatLabelUI
|
||||||
extends BasicLabelUI
|
extends BasicLabelUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
private Color disabledForeground;
|
@Styleable protected Color disabledForeground;
|
||||||
|
|
||||||
|
private final boolean shared;
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
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
|
@Override
|
||||||
@@ -77,7 +99,9 @@ public class FlatLabelUI
|
|||||||
@Override
|
@Override
|
||||||
protected void uninstallDefaults( JLabel c ) {
|
protected void uninstallDefaults( JLabel c ) {
|
||||||
super.uninstallDefaults( c );
|
super.uninstallDefaults( c );
|
||||||
|
|
||||||
defaults_initialized = false;
|
defaults_initialized = false;
|
||||||
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -94,10 +118,52 @@ public class FlatLabelUI
|
|||||||
if( name == "text" || name == "font" || name == "foreground" ) {
|
if( name == "text" || name == "font" || name == "foreground" ) {
|
||||||
JLabel label = (JLabel) e.getSource();
|
JLabel label = (JLabel) e.getSource();
|
||||||
updateHTMLRenderer( label, label.getText(), true );
|
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
|
} else
|
||||||
super.propertyChange( e );
|
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
|
* Checks whether text contains HTML tags that use "absolute-size" keywords
|
||||||
* (e.g. "x-large") for font-size in default style sheet
|
* (e.g. "x-large") for font-size in default style sheet
|
||||||
|
|||||||
@@ -37,15 +37,18 @@ public class FlatLineBorder
|
|||||||
{
|
{
|
||||||
private final Color lineColor;
|
private final Color lineColor;
|
||||||
private final float lineThickness;
|
private final float lineThickness;
|
||||||
|
/** @since 2 */ private final int arc;
|
||||||
|
|
||||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
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 );
|
super( insets );
|
||||||
this.lineColor = lineColor;
|
this.lineColor = lineColor;
|
||||||
this.lineThickness = lineThickness;
|
this.lineThickness = lineThickness;
|
||||||
|
this.arc = arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getLineColor() {
|
public Color getLineColor() {
|
||||||
@@ -56,13 +59,18 @@ public class FlatLineBorder
|
|||||||
return lineThickness;
|
return lineThickness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public int getArc() {
|
||||||
|
return arc;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
Graphics2D g2 = (Graphics2D) g.create();
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
g2.setColor( lineColor );
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0f, scale( lineThickness ), 0f );
|
0, 0, 0, scale( getLineThickness() ), scale( getArc() ), null, getLineColor(), null );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,15 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.ListUI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell border for {@link javax.swing.DefaultListCellRenderer}
|
* Cell border for {@link javax.swing.DefaultListCellRenderer}
|
||||||
@@ -33,12 +37,54 @@ import javax.swing.UIManager;
|
|||||||
public class FlatListCellBorder
|
public class FlatListCellBorder
|
||||||
extends FlatLineBorder
|
extends FlatLineBorder
|
||||||
{
|
{
|
||||||
final boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
/** @since 2 */ protected boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||||
|
|
||||||
|
private Component c;
|
||||||
|
|
||||||
protected FlatListCellBorder() {
|
protected FlatListCellBorder() {
|
||||||
super( UIManager.getInsets( "List.cellMargins" ), UIManager.getColor( "List.cellFocusColor" ) );
|
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 ------------------------------------------------------
|
//---- class Default ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,17 +113,19 @@ public class FlatListCellBorder
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for selected cell that uses margins and paints focus indicator border
|
* 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
|
public static class Selected
|
||||||
extends FlatListCellBorder
|
extends FlatListCellBorder
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
Boolean b = getStyleFromListUI( c, ui -> ui.showCellFocusIndicator );
|
||||||
|
boolean showCellFocusIndicator = (b != null) ? b : this.showCellFocusIndicator;
|
||||||
if( !showCellFocusIndicator )
|
if( !showCellFocusIndicator )
|
||||||
return;
|
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 );
|
JList<?> list = (JList<?>) SwingUtilities.getAncestorOfClass( JList.class, c );
|
||||||
if( list != null && list.getMinSelectionIndex() == list.getMaxSelectionIndex() )
|
if( list != null && list.getMinSelectionIndex() == list.getMaxSelectionIndex() )
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -17,13 +17,34 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.EventQueue;
|
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.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.JComponent;
|
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.UIManager;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||||
import javax.swing.plaf.basic.BasicListUI;
|
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}.
|
* 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.selectionInactiveBackground Color
|
||||||
* @uiDefault List.selectionInactiveForeground Color
|
* @uiDefault List.selectionInactiveForeground Color
|
||||||
|
* @uiDefault List.selectionInsets Insets
|
||||||
|
* @uiDefault List.selectionArc int
|
||||||
*
|
*
|
||||||
* <!-- FlatListCellBorder -->
|
* <!-- FlatListCellBorder -->
|
||||||
*
|
*
|
||||||
@@ -63,16 +86,40 @@ import javax.swing.plaf.basic.BasicListUI;
|
|||||||
*/
|
*/
|
||||||
public class FlatListUI
|
public class FlatListUI
|
||||||
extends BasicListUI
|
extends BasicListUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected Color selectionBackground;
|
@Styleable protected Color selectionBackground;
|
||||||
protected Color selectionForeground;
|
@Styleable protected Color selectionForeground;
|
||||||
protected Color selectionInactiveBackground;
|
@Styleable protected Color selectionInactiveBackground;
|
||||||
protected Color selectionInactiveForeground;
|
@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 ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatListUI();
|
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
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -81,6 +128,8 @@ public class FlatListUI
|
|||||||
selectionForeground = UIManager.getColor( "List.selectionForeground" );
|
selectionForeground = UIManager.getColor( "List.selectionForeground" );
|
||||||
selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" );
|
selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" );
|
||||||
selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" );
|
selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" );
|
||||||
|
selectionInsets = UIManager.getInsets( "List.selectionInsets" );
|
||||||
|
selectionArc = UIManager.getInt( "List.selectionArc" );
|
||||||
|
|
||||||
toggleSelectionColors();
|
toggleSelectionColors();
|
||||||
}
|
}
|
||||||
@@ -93,6 +142,8 @@ public class FlatListUI
|
|||||||
selectionForeground = null;
|
selectionForeground = null;
|
||||||
selectionInactiveBackground = null;
|
selectionInactiveBackground = null;
|
||||||
selectionInactiveForeground = null;
|
selectionInactiveForeground = null;
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.
|
* 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
|
* 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,
|
* already used in applications. Then either the inactive colors are not used,
|
||||||
@@ -141,4 +290,164 @@ public class FlatListUI
|
|||||||
list.setSelectionForeground( selectionInactiveForeground );
|
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, list.hasFocus() && (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 less 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
|
public class FlatMarginBorder
|
||||||
extends BasicBorders.MarginBorder
|
extends BasicBorders.MarginBorder
|
||||||
{
|
{
|
||||||
private final int left, right, top, bottom;
|
protected int left, right, top, bottom;
|
||||||
|
|
||||||
public FlatMarginBorder() {
|
public FlatMarginBorder() {
|
||||||
left = right = top = bottom = 0;
|
left = right = top = bottom = 0;
|
||||||
|
|||||||
@@ -21,8 +21,11 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for {@link javax.swing.JMenuBar}.
|
* Border for {@link javax.swing.JMenuBar}.
|
||||||
@@ -33,11 +36,32 @@ import javax.swing.UIManager;
|
|||||||
*/
|
*/
|
||||||
public class FlatMenuBarBorder
|
public class FlatMenuBarBorder
|
||||||
extends FlatMarginBorder
|
extends FlatMarginBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
private final Color borderColor = UIManager.getColor( "MenuBar.borderColor" );
|
@Styleable protected Color borderColor = UIManager.getColor( "MenuBar.borderColor" );
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
if( !showBottomSeparator( c ) )
|
||||||
|
return;
|
||||||
|
|
||||||
float lineHeight = scale( (float) 1 );
|
float lineHeight = scale( (float) 1 );
|
||||||
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||||
}
|
}
|
||||||
@@ -53,4 +77,9 @@ public class FlatMenuBarBorder
|
|||||||
insets.right = scale( margin.right );
|
insets.right = scale( margin.right );
|
||||||
return insets;
|
return insets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected boolean showBottomSeparator( Component c ) {
|
||||||
|
return !FlatMenuBarUI.useUnifiedBackground( c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,19 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
@@ -35,8 +43,13 @@ import javax.swing.plaf.ActionMapUIResource;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicMenuBarUI;
|
import javax.swing.plaf.basic.BasicMenuBarUI;
|
||||||
|
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuBar}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuBar}.
|
||||||
@@ -47,13 +60,35 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault MenuBar.background Color
|
* @uiDefault MenuBar.background Color
|
||||||
* @uiDefault MenuBar.foreground Color
|
* @uiDefault MenuBar.foreground Color
|
||||||
* @uiDefault MenuBar.border Border
|
* @uiDefault MenuBar.border Border
|
||||||
|
*
|
||||||
|
* <!-- FlatMenuBarUI -->
|
||||||
|
*
|
||||||
* @uiDefault TitlePane.unifiedBackground boolean
|
* @uiDefault TitlePane.unifiedBackground boolean
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatMenuBarUI
|
public class FlatMenuBarUI
|
||||||
extends BasicMenuBarUI
|
extends BasicMenuBarUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
|
// used in FlatMenuItemBorder
|
||||||
|
/** @since 2 */ @Styleable protected Insets itemMargins;
|
||||||
|
|
||||||
|
// used in FlatMenuUI
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionEmbeddedInsets;
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc = -1;
|
||||||
|
/** @since 2 */ @Styleable protected Color hoverBackground;
|
||||||
|
/** @since 2.5 */ @Styleable protected Color selectionBackground;
|
||||||
|
/** @since 2.5 */ @Styleable protected Color selectionForeground;
|
||||||
|
/** @since 2 */ @Styleable protected Color underlineSelectionBackground;
|
||||||
|
/** @since 2 */ @Styleable protected Color underlineSelectionColor;
|
||||||
|
/** @since 2 */ @Styleable protected int underlineSelectionHeight = -1;
|
||||||
|
|
||||||
|
private PropertyChangeListener propertyChangeListener;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
private AtomicBoolean borderShared;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatMenuBarUI();
|
return new FlatMenuBarUI();
|
||||||
}
|
}
|
||||||
@@ -63,11 +98,46 @@ public class FlatMenuBarUI
|
|||||||
* Do not add any functionality here.
|
* Do not add any functionality here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
LookAndFeel.installProperty( menuBar, "opaque", false );
|
LookAndFeel.installProperty( menuBar, "opaque", false );
|
||||||
|
|
||||||
|
LayoutManager layout = menuBar.getLayout();
|
||||||
|
if( layout == null || layout instanceof UIResource )
|
||||||
|
menuBar.setLayout( new FlatMenuBarLayout( menuBar ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void uninstallDefaults() {
|
||||||
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
borderShared = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installListeners() {
|
||||||
|
super.installListeners();
|
||||||
|
|
||||||
|
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( menuBar, this::installStyle, null );
|
||||||
|
menuBar.addPropertyChangeListener( propertyChangeListener );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void uninstallListeners() {
|
||||||
|
super.uninstallListeners();
|
||||||
|
|
||||||
|
menuBar.removePropertyChangeListener( propertyChangeListener );
|
||||||
|
propertyChangeListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -82,6 +152,39 @@ public class FlatMenuBarUI
|
|||||||
map.put( "takeFocus", new TakeFocus() );
|
map.put( "takeFocus", new TakeFocus() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( menuBar, "MenuBar" ) );
|
||||||
|
} 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, menuBar, borderShared );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this, menuBar.getBorder() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, menuBar.getBorder(), key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( Graphics g, JComponent c ) {
|
public void update( Graphics g, JComponent c ) {
|
||||||
// paint background
|
// paint background
|
||||||
@@ -97,20 +200,22 @@ public class FlatMenuBarUI
|
|||||||
protected Color getBackground( JComponent c ) {
|
protected Color getBackground( JComponent c ) {
|
||||||
Color background = c.getBackground();
|
Color background = c.getBackground();
|
||||||
|
|
||||||
// paint background if opaque or if having custom background color
|
// paint background if opaque
|
||||||
if( c.isOpaque() || !(background instanceof UIResource) )
|
if( c.isOpaque() )
|
||||||
return background;
|
return background;
|
||||||
|
|
||||||
// paint background if menu bar is not the "main" menu bar
|
// do not paint background if non-opaque and having custom background color
|
||||||
|
if( !(background instanceof UIResource) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// paint background if menu bar is not the "main" menu bar (e.g. in internal frame)
|
||||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||||
if( rootPane == null || !(rootPane.getParent() instanceof Window) || rootPane.getJMenuBar() != c )
|
if( rootPane == null || !(rootPane.getParent() instanceof Window) || rootPane.getJMenuBar() != c )
|
||||||
return background;
|
return background;
|
||||||
|
|
||||||
// use parent background for unified title pane
|
// use parent background for unified title pane
|
||||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
if( useUnifiedBackground( c ) )
|
||||||
if( UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
background = FlatUIUtils.getParentBackground( c );
|
||||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() ) )
|
|
||||||
background = FlatUIUtils.getParentBackground( c );
|
|
||||||
|
|
||||||
// paint background in full screen mode
|
// paint background in full screen mode
|
||||||
if( FlatUIUtils.isFullScreen( rootPane ) )
|
if( FlatUIUtils.isFullScreen( rootPane ) )
|
||||||
@@ -120,6 +225,146 @@ public class FlatMenuBarUI
|
|||||||
return FlatRootPaneUI.isMenuBarEmbedded( rootPane ) ? null : background;
|
return FlatRootPaneUI.isMenuBarEmbedded( rootPane ) ? null : background;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**@since 2 */
|
||||||
|
static boolean useUnifiedBackground( Component c ) {
|
||||||
|
// check whether:
|
||||||
|
// - TitlePane.unifiedBackground is true and
|
||||||
|
// - menu bar is the "main" menu bar and
|
||||||
|
// - window root pane has custom decoration style
|
||||||
|
|
||||||
|
JRootPane rootPane;
|
||||||
|
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||||
|
return UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||||
|
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||||
|
rootPane.getParent() instanceof Window &&
|
||||||
|
rootPane.getJMenuBar() == c &&
|
||||||
|
rootPane.getWindowDecorationStyle() != JRootPane.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class FlatMenuBarLayout --------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
protected static class FlatMenuBarLayout
|
||||||
|
extends DefaultMenuLayout
|
||||||
|
{
|
||||||
|
public FlatMenuBarLayout( Container target ) {
|
||||||
|
super( target, BoxLayout.LINE_AXIS );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void layoutContainer( Container target ) {
|
||||||
|
super.layoutContainer( target );
|
||||||
|
|
||||||
|
|
||||||
|
// The only purpose of the code below is to make sure that a horizontal glue,
|
||||||
|
// which can be used to move window and displays the window title in embedded menu bar,
|
||||||
|
// is always visible within the menu bar bounds and has a minimum width.
|
||||||
|
// If this is not the case, the horizontal glue is made larger and
|
||||||
|
// components that are on the left side of the glue are made smaller.
|
||||||
|
|
||||||
|
|
||||||
|
// get root pane and check whether this menu bar is the root pane menu bar
|
||||||
|
JRootPane rootPane = SwingUtilities.getRootPane( target );
|
||||||
|
if( rootPane == null || rootPane.getJMenuBar() != target )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get title pane and check whether menu bar is embedded
|
||||||
|
FlatTitlePane titlePane = FlatRootPaneUI.getTitlePane( rootPane );
|
||||||
|
if( titlePane == null || !titlePane.isMenuBarEmbedded() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check whether there is a horizontal glue (used for window title in embedded menu bar)
|
||||||
|
// and check minimum width of horizontal glue
|
||||||
|
Component horizontalGlue = titlePane.findHorizontalGlue( (JMenuBar) target );
|
||||||
|
int minTitleWidth = UIScale.scale( titlePane.titleMinimumWidth );
|
||||||
|
if( horizontalGlue != null && horizontalGlue.getWidth() < minTitleWidth ) {
|
||||||
|
// get index of glue component
|
||||||
|
int glueIndex = -1;
|
||||||
|
Component[] components = target.getComponents();
|
||||||
|
for( int i = components.length - 1; i >= 0; i-- ) {
|
||||||
|
if( components[i] == horizontalGlue ) {
|
||||||
|
glueIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( glueIndex < 0 )
|
||||||
|
return; // should never happen
|
||||||
|
|
||||||
|
if( target.getComponentOrientation().isLeftToRight() ) {
|
||||||
|
// left-to-right
|
||||||
|
|
||||||
|
// make horizontal glue wider (minimum title width)
|
||||||
|
int offset = minTitleWidth - horizontalGlue.getWidth();
|
||||||
|
horizontalGlue.setSize( minTitleWidth, horizontalGlue.getHeight() );
|
||||||
|
|
||||||
|
// check whether glue is fully visible
|
||||||
|
int minGlueX = target.getWidth() - target.getInsets().right - minTitleWidth;
|
||||||
|
if( minGlueX < horizontalGlue.getX() ) {
|
||||||
|
// move glue to the left to make it fully visible
|
||||||
|
offset -= (horizontalGlue.getX() - minGlueX);
|
||||||
|
horizontalGlue.setLocation( minGlueX, horizontalGlue.getY() );
|
||||||
|
|
||||||
|
// shrink and move components that are on the left side of the glue
|
||||||
|
for( int i = glueIndex - 1; i >= 0; i-- ) {
|
||||||
|
Component c = components[i];
|
||||||
|
if( c.getX() > minGlueX ) {
|
||||||
|
// move component and set width to zero
|
||||||
|
c.setBounds( minGlueX, c.getY(), 0, c.getHeight() );
|
||||||
|
} else {
|
||||||
|
// reduce size of component
|
||||||
|
c.setSize( minGlueX - c.getX(), c.getHeight() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move components that are on the right side of the glue
|
||||||
|
for( int i = glueIndex + 1; i < components.length; i++ ) {
|
||||||
|
Component c = components[i];
|
||||||
|
c.setLocation( c.getX() + offset, c.getY() );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// right-to-left
|
||||||
|
|
||||||
|
// make horizontal glue wider (minimum title width)
|
||||||
|
int offset = minTitleWidth - horizontalGlue.getWidth();
|
||||||
|
horizontalGlue.setBounds( horizontalGlue.getX() - offset, horizontalGlue.getY(),
|
||||||
|
minTitleWidth, horizontalGlue.getHeight() );
|
||||||
|
|
||||||
|
// check whether glue is fully visible
|
||||||
|
int minGlueX = target.getInsets().left;
|
||||||
|
if( minGlueX > horizontalGlue.getX() ) {
|
||||||
|
// move glue to the right to make it fully visible
|
||||||
|
offset -= (horizontalGlue.getX() - minGlueX);
|
||||||
|
horizontalGlue.setLocation( minGlueX, horizontalGlue.getY() );
|
||||||
|
|
||||||
|
// shrink and move components that are on the right side of the glue
|
||||||
|
int x = horizontalGlue.getX() + horizontalGlue.getWidth();
|
||||||
|
for( int i = glueIndex - 1; i >= 0; i-- ) {
|
||||||
|
Component c = components[i];
|
||||||
|
if( c.getX() + c.getWidth() < x ) {
|
||||||
|
// move component and set width to zero
|
||||||
|
c.setBounds( x, c.getY(), 0, c.getHeight() );
|
||||||
|
} else {
|
||||||
|
// move component and reduce size
|
||||||
|
c.setBounds( x, c.getY(), c.getWidth() - (x - c.getX()), c.getHeight() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move components that are on the left side of the glue
|
||||||
|
for( int i = glueIndex + 1; i < components.length; i++ ) {
|
||||||
|
Component c = components[i];
|
||||||
|
c.setLocation( c.getX() - offset, c.getY() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- class TakeFocus ----------------------------------------------------
|
//---- class TakeFocus ----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.MenuBarUI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for {@link javax.swing.JMenu}, {@link javax.swing.JMenuItem},
|
* Border for {@link javax.swing.JMenu}, {@link javax.swing.JMenuItem},
|
||||||
@@ -33,15 +35,22 @@ import javax.swing.UIManager;
|
|||||||
public class FlatMenuItemBorder
|
public class FlatMenuItemBorder
|
||||||
extends FlatMarginBorder
|
extends FlatMarginBorder
|
||||||
{
|
{
|
||||||
|
// only used if parent menubar is not an instance of FlatMenuBarUI
|
||||||
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
|
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
if( c.getParent() instanceof JMenuBar ) {
|
Container parent = c.getParent();
|
||||||
insets.top = scale( menuBarItemMargins.top );
|
if( parent instanceof JMenuBar ) {
|
||||||
insets.left = scale( menuBarItemMargins.left );
|
// get margins from FlatMenuBarUI to allow styling
|
||||||
insets.bottom = scale( menuBarItemMargins.bottom );
|
MenuBarUI ui = ((JMenuBar)parent).getUI();
|
||||||
insets.right = scale( menuBarItemMargins.right );
|
Insets margins = (ui instanceof FlatMenuBarUI && ((FlatMenuBarUI)ui).itemMargins != null)
|
||||||
|
? ((FlatMenuBarUI)ui).itemMargins
|
||||||
|
: this.menuBarItemMargins;
|
||||||
|
insets.top = scale( margins.top );
|
||||||
|
insets.left = scale( margins.left );
|
||||||
|
insets.bottom = scale( margins.bottom );
|
||||||
|
insets.right = scale( margins.right );
|
||||||
return insets;
|
return insets;
|
||||||
} else
|
} else
|
||||||
return super.getBorderInsets( c, insets );
|
return super.getBorderInsets( c, insets );
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
@@ -30,7 +31,9 @@ import java.awt.Rectangle;
|
|||||||
import java.awt.event.InputEvent;
|
import java.awt.event.InputEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.text.AttributedCharacterIterator;
|
import java.text.AttributedCharacterIterator;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
@@ -38,7 +41,12 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.basic.BasicHTML;
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
import javax.swing.text.View;
|
import javax.swing.text.View;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon;
|
||||||
|
import com.formdev.flatlaf.icons.FlatMenuArrowIcon;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
import com.formdev.flatlaf.util.DerivedColor;
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
@@ -47,43 +55,54 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
/**
|
/**
|
||||||
* Renderer for menu items.
|
* Renderer for menu items.
|
||||||
*
|
*
|
||||||
|
* @uiDefault MenuItem.verticallyAlignText boolean
|
||||||
* @uiDefault MenuItem.minimumWidth int
|
* @uiDefault MenuItem.minimumWidth int
|
||||||
* @uiDefault MenuItem.minimumIconSize Dimension
|
* @uiDefault MenuItem.minimumIconSize Dimension
|
||||||
* @uiDefault MenuItem.textAcceleratorGap int
|
* @uiDefault MenuItem.textAcceleratorGap int
|
||||||
* @uiDefault MenuItem.textNoAcceleratorGap int
|
* @uiDefault MenuItem.textNoAcceleratorGap int
|
||||||
* @uiDefault MenuItem.acceleratorArrowGap int
|
* @uiDefault MenuItem.acceleratorArrowGap int
|
||||||
* @uiDefault MenuItem.checkBackground Color
|
* @uiDefault MenuItem.checkBackground Color
|
||||||
|
* @uiDefault MenuItem.checkMargins Insets
|
||||||
|
* @uiDefault MenuItem.selectionInsets Insets
|
||||||
|
* @uiDefault MenuItem.selectionArc int
|
||||||
|
* @uiDefault MenuItem.selectionType String null (default) or underline
|
||||||
* @uiDefault MenuItem.underlineSelectionBackground Color
|
* @uiDefault MenuItem.underlineSelectionBackground Color
|
||||||
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
|
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
|
||||||
* @uiDefault MenuItem.underlineSelectionColor Color
|
* @uiDefault MenuItem.underlineSelectionColor Color
|
||||||
* @uiDefault MenuItem.underlineSelectionHeight int
|
* @uiDefault MenuItem.underlineSelectionHeight int
|
||||||
* @uiDefault MenuItem.selectionBackground Color
|
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatMenuItemRenderer
|
public class FlatMenuItemRenderer
|
||||||
{
|
{
|
||||||
|
private static final String KEY_MAX_ICONS_WIDTH = "FlatLaf.internal.FlatMenuItemRenderer.maxIconWidth";
|
||||||
|
|
||||||
protected final JMenuItem menuItem;
|
protected final JMenuItem menuItem;
|
||||||
protected final Icon checkIcon;
|
protected Icon checkIcon;
|
||||||
protected final Icon arrowIcon;
|
protected Icon arrowIcon;
|
||||||
protected final Font acceleratorFont;
|
@Styleable protected Font acceleratorFont;
|
||||||
protected final String acceleratorDelimiter;
|
protected final String acceleratorDelimiter;
|
||||||
|
|
||||||
protected final int minimumWidth = UIManager.getInt( "MenuItem.minimumWidth" );
|
/** @since 2 */ @Styleable protected boolean verticallyAlignText = FlatUIUtils.getUIBoolean( "MenuItem.verticallyAlignText", true );
|
||||||
protected final Dimension minimumIconSize;
|
@Styleable protected int minimumWidth = UIManager.getInt( "MenuItem.minimumWidth" );
|
||||||
protected final int textAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textAcceleratorGap", 28 );
|
@Styleable protected Dimension minimumIconSize;
|
||||||
protected final int textNoAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textNoAcceleratorGap", 6 );
|
@Styleable protected int textAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textAcceleratorGap", 28 );
|
||||||
protected final int acceleratorArrowGap = FlatUIUtils.getUIInt( "MenuItem.acceleratorArrowGap", 2 );
|
@Styleable protected int textNoAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textNoAcceleratorGap", 6 );
|
||||||
|
@Styleable protected int acceleratorArrowGap = FlatUIUtils.getUIInt( "MenuItem.acceleratorArrowGap", 2 );
|
||||||
|
|
||||||
protected final Color checkBackground = UIManager.getColor( "MenuItem.checkBackground" );
|
@Styleable protected Color checkBackground = UIManager.getColor( "MenuItem.checkBackground" );
|
||||||
protected final Insets checkMargins = UIManager.getInsets( "MenuItem.checkMargins" );
|
@Styleable protected Insets checkMargins = UIManager.getInsets( "MenuItem.checkMargins" );
|
||||||
|
|
||||||
protected final Color underlineSelectionBackground = UIManager.getColor( "MenuItem.underlineSelectionBackground" );
|
/** @since 3 */ @Styleable protected Insets selectionInsets = UIManager.getInsets( "MenuItem.selectionInsets" );
|
||||||
protected final Color underlineSelectionCheckBackground = UIManager.getColor( "MenuItem.underlineSelectionCheckBackground" );
|
/** @since 3 */ @Styleable protected int selectionArc = UIManager.getInt( "MenuItem.selectionArc" );
|
||||||
protected final Color underlineSelectionColor = UIManager.getColor( "MenuItem.underlineSelectionColor" );
|
|
||||||
protected final int underlineSelectionHeight = UIManager.getInt( "MenuItem.underlineSelectionHeight" );
|
|
||||||
|
|
||||||
protected final Color selectionBackground = UIManager.getColor( "MenuItem.selectionBackground" );
|
@Styleable protected Color underlineSelectionBackground = UIManager.getColor( "MenuItem.underlineSelectionBackground" );
|
||||||
|
@Styleable protected Color underlineSelectionCheckBackground = UIManager.getColor( "MenuItem.underlineSelectionCheckBackground" );
|
||||||
|
@Styleable protected Color underlineSelectionColor = UIManager.getColor( "MenuItem.underlineSelectionColor" );
|
||||||
|
@Styleable protected int underlineSelectionHeight = UIManager.getInt( "MenuItem.underlineSelectionHeight" );
|
||||||
|
|
||||||
|
private boolean iconsShared = true;
|
||||||
|
private final Font menuFont = UIManager.getFont( "Menu.font" );
|
||||||
|
|
||||||
protected FlatMenuItemRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
protected FlatMenuItemRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
||||||
Font acceleratorFont, String acceleratorDelimiter )
|
Font acceleratorFont, String acceleratorDelimiter )
|
||||||
@@ -98,6 +117,77 @@ public class FlatMenuItemRenderer
|
|||||||
this.minimumIconSize = (minimumIconSize != null) ? minimumIconSize : new Dimension( 16, 16 );
|
this.minimumIconSize = (minimumIconSize != null) ? minimumIconSize : new Dimension( 16, 16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
// style icon
|
||||||
|
if( key.startsWith( "icon." ) || key.equals( "selectionForeground" ) ) {
|
||||||
|
if( iconsShared ) {
|
||||||
|
if( checkIcon instanceof FlatCheckBoxMenuItemIcon )
|
||||||
|
checkIcon = FlatStylingSupport.cloneIcon( checkIcon );
|
||||||
|
if( arrowIcon instanceof FlatMenuArrowIcon )
|
||||||
|
arrowIcon = FlatStylingSupport.cloneIcon( arrowIcon );
|
||||||
|
iconsShared = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( key.startsWith( "icon." ) ) {
|
||||||
|
String key2 = key.substring( "icon.".length() );
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( checkIcon instanceof FlatCheckBoxMenuItemIcon )
|
||||||
|
return ((FlatCheckBoxMenuItemIcon)checkIcon).applyStyleProperty( key2, value );
|
||||||
|
} catch ( UnknownStyleException ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( arrowIcon instanceof FlatMenuArrowIcon )
|
||||||
|
return ((FlatMenuArrowIcon)arrowIcon).applyStyleProperty( key2, value );
|
||||||
|
} catch ( UnknownStyleException ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// keys with prefix "icon." are only for icons
|
||||||
|
throw new UnknownStyleException( key );
|
||||||
|
} else if( key.equals( "selectionForeground" ) ) {
|
||||||
|
// special case: same key is used in icons and in menuitem
|
||||||
|
if( checkIcon instanceof FlatCheckBoxMenuItemIcon )
|
||||||
|
((FlatCheckBoxMenuItemIcon)checkIcon).applyStyleProperty( key, value );
|
||||||
|
if( arrowIcon instanceof FlatMenuArrowIcon )
|
||||||
|
((FlatMenuArrowIcon)arrowIcon).applyStyleProperty( key, value );
|
||||||
|
|
||||||
|
// throw exception because the caller should also apply this key
|
||||||
|
throw new UnknownStyleException( key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
Map<String, Class<?>> infos = FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
if( checkIcon instanceof FlatCheckBoxMenuItemIcon )
|
||||||
|
FlatStylingSupport.putAllPrefixKey( infos, "icon.", ((FlatCheckBoxMenuItemIcon)checkIcon).getStyleableInfos() );
|
||||||
|
infos.remove( "icon.selectionForeground" );
|
||||||
|
if( arrowIcon instanceof FlatMenuArrowIcon )
|
||||||
|
FlatStylingSupport.putAllPrefixKey( infos, "icon.", ((FlatMenuArrowIcon)arrowIcon).getStyleableInfos() );
|
||||||
|
infos.remove( "icon.selectionForeground" );
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
if( key.startsWith( "icon." ) ) {
|
||||||
|
String key2 = key.substring( "icon.".length() );
|
||||||
|
if( checkIcon instanceof FlatCheckBoxMenuItemIcon )
|
||||||
|
return ((FlatCheckBoxMenuItemIcon)checkIcon).getStyleableValue( key2 );
|
||||||
|
if( arrowIcon instanceof FlatMenuArrowIcon )
|
||||||
|
return ((FlatMenuArrowIcon)arrowIcon).getStyleableValue( key2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
protected Dimension getPreferredMenuItemSize() {
|
protected Dimension getPreferredMenuItemSize() {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
@@ -109,7 +199,8 @@ public class FlatMenuItemRenderer
|
|||||||
|
|
||||||
// layout icon and text
|
// layout icon and text
|
||||||
SwingUtilities.layoutCompoundLabel( menuItem,
|
SwingUtilities.layoutCompoundLabel( menuItem,
|
||||||
menuItem.getFontMetrics( menuItem.getFont() ), menuItem.getText(), getIconForLayout(),
|
menuItem.getFontMetrics( isTopLevelMenu ? getTopLevelFont() : menuItem.getFont() ),
|
||||||
|
menuItem.getText(), getIconForLayout(),
|
||||||
menuItem.getVerticalAlignment(), menuItem.getHorizontalAlignment(),
|
menuItem.getVerticalAlignment(), menuItem.getHorizontalAlignment(),
|
||||||
menuItem.getVerticalTextPosition(), menuItem.getHorizontalTextPosition(),
|
menuItem.getVerticalTextPosition(), menuItem.getHorizontalTextPosition(),
|
||||||
viewRect, iconRect, textRect, scale( menuItem.getIconTextGap() ) );
|
viewRect, iconRect, textRect, scale( menuItem.getIconTextGap() ) );
|
||||||
@@ -211,7 +302,8 @@ public class FlatMenuItemRenderer
|
|||||||
|
|
||||||
// layout icon and text
|
// layout icon and text
|
||||||
SwingUtilities.layoutCompoundLabel( menuItem,
|
SwingUtilities.layoutCompoundLabel( menuItem,
|
||||||
menuItem.getFontMetrics( menuItem.getFont() ), menuItem.getText(), getIconForLayout(),
|
menuItem.getFontMetrics( isTopLevelMenu ? getTopLevelFont() : menuItem.getFont() ),
|
||||||
|
menuItem.getText(), getIconForLayout(),
|
||||||
menuItem.getVerticalAlignment(), menuItem.getHorizontalAlignment(),
|
menuItem.getVerticalAlignment(), menuItem.getHorizontalAlignment(),
|
||||||
menuItem.getVerticalTextPosition(), menuItem.getHorizontalTextPosition(),
|
menuItem.getVerticalTextPosition(), menuItem.getHorizontalTextPosition(),
|
||||||
labelRect, iconRect, textRect, scale( menuItem.getIconTextGap() ) );
|
labelRect, iconRect, textRect, scale( menuItem.getIconTextGap() ) );
|
||||||
@@ -250,32 +342,52 @@ public class FlatMenuItemRenderer
|
|||||||
g.setColor( Color.orange ); g.drawRect( arrowRect.x, arrowRect.y, arrowRect.width - 1, arrowRect.height - 1 );
|
g.setColor( Color.orange ); g.drawRect( arrowRect.x, arrowRect.y, arrowRect.width - 1, arrowRect.height - 1 );
|
||||||
debug*/
|
debug*/
|
||||||
|
|
||||||
|
boolean armedOrSelected = isArmedOrSelected( menuItem );
|
||||||
boolean underlineSelection = isUnderlineSelection();
|
boolean underlineSelection = isUnderlineSelection();
|
||||||
paintBackground( g, underlineSelection ? underlineSelectionBackground : selectionBackground );
|
|
||||||
if( underlineSelection && isArmedOrSelected( menuItem ) )
|
paintBackground( g );
|
||||||
paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
|
if( armedOrSelected ) {
|
||||||
paintIcon( g, iconRect, getIconForPainting(), underlineSelection ? underlineSelectionCheckBackground : checkBackground );
|
if( underlineSelection )
|
||||||
|
paintUnderlineSelection( g, underlineSelectionBackground, underlineSelectionColor, underlineSelectionHeight );
|
||||||
|
else
|
||||||
|
paintSelection( g, selectionBackground, selectionInsets, selectionArc );
|
||||||
|
}
|
||||||
|
paintIcon( g, iconRect, getIconForPainting(), underlineSelection ? underlineSelectionCheckBackground : checkBackground, selectionBackground );
|
||||||
paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground );
|
paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground );
|
||||||
paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground );
|
paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground );
|
||||||
if( !isTopLevelMenu( menuItem ) )
|
if( !isTopLevelMenu( menuItem ) )
|
||||||
paintArrowIcon( g, arrowRect, arrowIcon );
|
paintArrowIcon( g, arrowRect, arrowIcon );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintBackground( Graphics g, Color selectionBackground ) {
|
/** @since 3 */
|
||||||
boolean armedOrSelected = isArmedOrSelected( menuItem );
|
protected void paintBackground( Graphics g ) {
|
||||||
if( menuItem.isOpaque() || armedOrSelected ) {
|
if( menuItem.isOpaque() ) {
|
||||||
// paint background
|
g.setColor( menuItem.getBackground() );
|
||||||
g.setColor( armedOrSelected
|
|
||||||
? deriveBackground( selectionBackground )
|
|
||||||
: menuItem.getBackground() );
|
|
||||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
|
/** @since 3 */
|
||||||
|
protected void paintSelection( Graphics g, Color selectionBackground, Insets selectionInsets, int selectionArc ) {
|
||||||
|
float arc = scale( selectionArc / 2f );
|
||||||
|
|
||||||
|
g.setColor( deriveBackground( selectionBackground ) );
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, 0, 0, menuItem.getWidth(), menuItem.getHeight(),
|
||||||
|
scale( selectionInsets ), arc, arc, arc, arc, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionBackground,
|
||||||
|
Color underlineSelectionColor, int underlineSelectionHeight )
|
||||||
|
{
|
||||||
int width = menuItem.getWidth();
|
int width = menuItem.getWidth();
|
||||||
int height = menuItem.getHeight();
|
int height = menuItem.getHeight();
|
||||||
|
|
||||||
|
// paint background
|
||||||
|
g.setColor( deriveBackground( underlineSelectionBackground ) );
|
||||||
|
g.fillRect( 0, 0, width, height );
|
||||||
|
|
||||||
|
// paint underline
|
||||||
int underlineHeight = scale( underlineSelectionHeight );
|
int underlineHeight = scale( underlineSelectionHeight );
|
||||||
g.setColor( underlineSelectionColor );
|
g.setColor( underlineSelectionColor );
|
||||||
if( isTopLevelMenu( menuItem ) ) {
|
if( isTopLevelMenu( menuItem ) ) {
|
||||||
@@ -301,7 +413,7 @@ debug*/
|
|||||||
return FlatUIUtils.deriveColor( background, baseColor );
|
return FlatUIUtils.deriveColor( background, baseColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintIcon( Graphics g, Rectangle iconRect, Icon icon, Color checkBackground ) {
|
protected void paintIcon( Graphics g, Rectangle iconRect, Icon icon, Color checkBackground, Color selectionBackground ) {
|
||||||
// if checkbox/radiobutton menu item is selected and also has a custom icon,
|
// if checkbox/radiobutton menu item is selected and also has a custom icon,
|
||||||
// then use filled icon background to indicate selection (instead of using checkIcon)
|
// then use filled icon background to indicate selection (instead of using checkIcon)
|
||||||
if( menuItem.isSelected() && checkIcon != null && icon != checkIcon ) {
|
if( menuItem.isSelected() && checkIcon != null && icon != checkIcon ) {
|
||||||
@@ -321,9 +433,10 @@ debug*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;
|
int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;
|
||||||
Color foreground = (isTopLevelMenu( menuItem ) ? menuItem.getParent() : menuItem).getForeground();
|
boolean isTopLevelMenu = isTopLevelMenu( menuItem );
|
||||||
|
Color foreground = (isTopLevelMenu ? menuItem.getParent() : menuItem).getForeground();
|
||||||
|
|
||||||
paintText( g, menuItem, textRect, text, mnemonicIndex, menuItem.getFont(),
|
paintText( g, menuItem, textRect, text, mnemonicIndex, isTopLevelMenu ? getTopLevelFont() : menuItem.getFont(),
|
||||||
foreground, isUnderlineSelection() ? foreground : selectionForeground, disabledForeground );
|
foreground, isUnderlineSelection() ? foreground : selectionForeground, disabledForeground );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,11 +456,10 @@ debug*/
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// center because the real icon may be smaller than dimension in iconRect
|
// center because the real icon may be smaller than dimension in iconRect
|
||||||
int x = iconRect.x + centerOffset( iconRect.width, icon.getIconWidth() );
|
|
||||||
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
||||||
|
|
||||||
// paint
|
// paint
|
||||||
icon.paintIcon( menuItem, g, x, y );
|
icon.paintIcon( menuItem, g, iconRect.x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void paintText( Graphics g, JMenuItem menuItem,
|
protected static void paintText( Graphics g, JMenuItem menuItem,
|
||||||
@@ -376,12 +488,29 @@ debug*/
|
|||||||
protected static void paintHTMLText( Graphics g, JMenuItem menuItem,
|
protected static void paintHTMLText( Graphics g, JMenuItem menuItem,
|
||||||
Rectangle textRect, View htmlView, Color selectionForeground )
|
Rectangle textRect, View htmlView, Color selectionForeground )
|
||||||
{
|
{
|
||||||
|
// On Windows, using Segoe UI font, Java 15 or older and scaling greater than 1,
|
||||||
|
// the width of the HTML view may be initially too small (because component
|
||||||
|
// is not connected to a GraphicsConfiguration when getPreferredSize() is invoked).
|
||||||
|
// Since Java 16, this seems to be fixed somehow by doing popup menu layout twice.
|
||||||
|
//
|
||||||
|
// If using a too small width for htmlView.paint(), the view would rearrange
|
||||||
|
// its children and wrap them to two lines. To avoid this, use view preferred X span
|
||||||
|
// for painting. Core Lafs actually do the same in class MenuItemLayoutHelper.
|
||||||
|
//
|
||||||
|
// Example HTML text that causes the problem: "<html>some <b>HTML</b> <i>text</i></html>"
|
||||||
|
textRect = new Rectangle( textRect );
|
||||||
|
textRect.width = (int) htmlView.getPreferredSpan( View.X_AXIS );
|
||||||
|
|
||||||
if( isArmedOrSelected( menuItem ) && selectionForeground != null )
|
if( isArmedOrSelected( menuItem ) && selectionForeground != null )
|
||||||
g = new GraphicsProxyWithTextColor( (Graphics2D) g, selectionForeground );
|
g = new GraphicsProxyWithTextColor( (Graphics2D) g, selectionForeground );
|
||||||
|
|
||||||
htmlView.paint( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ), textRect );
|
htmlView.paint( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ), textRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if either the menu item is armed (mouse over item)
|
||||||
|
* or it is a {@code JMenu} and selected (shows submenu).
|
||||||
|
*/
|
||||||
protected static boolean isArmedOrSelected( JMenuItem menuItem ) {
|
protected static boolean isArmedOrSelected( JMenuItem menuItem ) {
|
||||||
return menuItem.isArmed() || (menuItem instanceof JMenu && menuItem.isSelected());
|
return menuItem.isArmed() || (menuItem instanceof JMenu && menuItem.isSelected());
|
||||||
}
|
}
|
||||||
@@ -394,6 +523,15 @@ debug*/
|
|||||||
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Font getTopLevelFont() {
|
||||||
|
Font font = menuItem.getFont();
|
||||||
|
// menu item parent may be null if JMenu.isTopLevelMenu() is overridden
|
||||||
|
// and does not check parent (e.g. com.jidesoft.swing.JideMenu.isTopLevelMenu())
|
||||||
|
return (font != menuFont || menuItem.getParent() == null)
|
||||||
|
? font
|
||||||
|
: menuItem.getParent().getFont();
|
||||||
|
}
|
||||||
|
|
||||||
private Icon getIconForPainting() {
|
private Icon getIconForPainting() {
|
||||||
Icon icon = menuItem.getIcon();
|
Icon icon = menuItem.getIcon();
|
||||||
|
|
||||||
@@ -412,6 +550,12 @@ debug*/
|
|||||||
return pressedIcon;
|
return pressedIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( isArmedOrSelected( menuItem ) ) {
|
||||||
|
Icon selectedIcon = menuItem.getSelectedIcon();
|
||||||
|
if( selectedIcon != null )
|
||||||
|
return selectedIcon;
|
||||||
|
}
|
||||||
|
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,6 +642,44 @@ debug*/
|
|||||||
shiftGlyph = 0x21E7,
|
shiftGlyph = 0x21E7,
|
||||||
commandGlyph = 0x2318;
|
commandGlyph = 0x2318;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the maximum width of all menu item icons in the popup.
|
||||||
|
*/
|
||||||
|
private int getMaxIconsWidth() {
|
||||||
|
if( !verticallyAlignText )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Container parent = menuItem.getParent();
|
||||||
|
if( !(parent instanceof JComponent) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int maxWidth = FlatClientProperties.clientPropertyInt( (JComponent) parent, KEY_MAX_ICONS_WIDTH, -1 );
|
||||||
|
if( maxWidth >= 0 )
|
||||||
|
return maxWidth;
|
||||||
|
|
||||||
|
maxWidth = 0;
|
||||||
|
|
||||||
|
for( Component c : parent.getComponents() ) {
|
||||||
|
if( !(c instanceof JMenuItem) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Icon icon = ((JMenuItem)c).getIcon();
|
||||||
|
if( icon != null )
|
||||||
|
maxWidth = Math.max( maxWidth, icon.getIconWidth() );
|
||||||
|
}
|
||||||
|
|
||||||
|
((JComponent)parent).putClientProperty( KEY_MAX_ICONS_WIDTH, maxWidth );
|
||||||
|
return maxWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clearClientProperties( Component c ) {
|
||||||
|
if( !(c instanceof JComponent) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
JComponent jc = (JComponent) c;
|
||||||
|
jc.putClientProperty( FlatMenuItemRenderer.KEY_MAX_ICONS_WIDTH, null );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class MinSizeIcon --------------------------------------------------
|
//---- class MinSizeIcon --------------------------------------------------
|
||||||
|
|
||||||
private class MinSizeIcon
|
private class MinSizeIcon
|
||||||
@@ -512,6 +694,7 @@ debug*/
|
|||||||
@Override
|
@Override
|
||||||
public int getIconWidth() {
|
public int getIconWidth() {
|
||||||
int iconWidth = (delegate != null) ? delegate.getIconWidth() : 0;
|
int iconWidth = (delegate != null) ? delegate.getIconWidth() : 0;
|
||||||
|
iconWidth = Math.max( iconWidth, getMaxIconsWidth() );
|
||||||
return Math.max( iconWidth, scale( minimumIconSize.width ) );
|
return Math.max( iconWidth, scale( minimumIconSize.width ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,20 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuItem}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuItem}.
|
||||||
@@ -52,15 +61,30 @@ import javax.swing.plaf.basic.BasicMenuItemUI;
|
|||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionBackground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="disabledForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorSelectionForeground" )
|
||||||
|
|
||||||
public class FlatMenuItemUI
|
public class FlatMenuItemUI
|
||||||
extends BasicMenuItemUI
|
extends BasicMenuItemUI
|
||||||
|
implements StyleableUI, StyleableLookupProvider
|
||||||
{
|
{
|
||||||
private FlatMenuItemRenderer renderer;
|
private FlatMenuItemRenderer renderer;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatMenuItemUI();
|
return new FlatMenuItemUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -74,13 +98,84 @@ public class FlatMenuItemUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||||
renderer = null;
|
renderer = null;
|
||||||
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
|
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "MenuItem" ) );
|
||||||
|
} 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 applyStyleProperty( menuItem, this, renderer, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object applyStyleProperty( JMenuItem menuItem, BasicMenuItemUI ui,
|
||||||
|
FlatMenuItemRenderer renderer, String key, Object value )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return renderer.applyStyleProperty( key, value );
|
||||||
|
} catch ( UnknownStyleException ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( ui, menuItem, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return getStyleableInfos( this, renderer );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, Class<?>> getStyleableInfos( BasicMenuItemUI ui, FlatMenuItemRenderer renderer ) {
|
||||||
|
Map<String, Class<?>> infos = FlatStylingSupport.getAnnotatedStyleableInfos( ui );
|
||||||
|
infos.putAll( renderer.getStyleableInfos() );
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return getStyleableValue( this, renderer, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object getStyleableValue( BasicMenuItemUI ui, FlatMenuItemRenderer renderer, String key ) {
|
||||||
|
Object value = renderer.getStyleableValue( key );
|
||||||
|
if( value == null )
|
||||||
|
value = FlatStylingSupport.getAnnotatedStyleableValue( ui, key );
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public MethodHandles.Lookup getLookupForStyling() {
|
||||||
|
// MethodHandles.lookup() is caller sensitive and must be invoked in this class,
|
||||||
|
// otherwise it is not possible to access protected fields in JRE superclass
|
||||||
|
return MethodHandles.lookup();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||||
return renderer.getPreferredMenuItemSize();
|
return renderer.getPreferredMenuItemSize();
|
||||||
|
|||||||
@@ -20,17 +20,33 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Window;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.swing.ButtonModel;
|
import javax.swing.ButtonModel;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JRootPane;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.MouseInputListener;
|
import javax.swing.event.MouseInputListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.MenuBarUI;
|
||||||
|
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||||
import javax.swing.plaf.basic.BasicMenuUI;
|
import javax.swing.plaf.basic.BasicMenuUI;
|
||||||
|
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.JMenu}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenu}.
|
||||||
@@ -60,26 +76,45 @@ import javax.swing.plaf.basic.BasicMenuUI;
|
|||||||
* <!-- FlatMenuUI -->
|
* <!-- FlatMenuUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault MenuItem.iconTextGap int
|
* @uiDefault MenuItem.iconTextGap int
|
||||||
* @uiDefault MenuBar.hoverBackground Color
|
|
||||||
*
|
*
|
||||||
* <!-- FlatMenuRenderer -->
|
* <!-- FlatMenuRenderer -->
|
||||||
*
|
*
|
||||||
|
* @uiDefault MenuBar.selectionInsets Insets
|
||||||
|
* @uiDefault MenuBar.selectionEmbeddedInsets Insets
|
||||||
|
* @uiDefault MenuBar.selectionArc int
|
||||||
|
* @uiDefault MenuBar.hoverBackground Color
|
||||||
|
* @uiDefault MenuBar.selectionBackground Color optional; defaults to Menu.selectionBackground
|
||||||
|
* @uiDefault MenuBar.selectionForeground Color optional; defaults to Menu.selectionForeground
|
||||||
* @uiDefault MenuBar.underlineSelectionBackground Color
|
* @uiDefault MenuBar.underlineSelectionBackground Color
|
||||||
* @uiDefault MenuBar.underlineSelectionColor Color
|
* @uiDefault MenuBar.underlineSelectionColor Color
|
||||||
* @uiDefault MenuBar.underlineSelectionHeight int
|
* @uiDefault MenuBar.underlineSelectionHeight int
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionBackground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="disabledForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorSelectionForeground" )
|
||||||
|
|
||||||
public class FlatMenuUI
|
public class FlatMenuUI
|
||||||
extends BasicMenuUI
|
extends BasicMenuUI
|
||||||
|
implements StyleableUI, StyleableLookupProvider
|
||||||
{
|
{
|
||||||
private Color hoverBackground;
|
|
||||||
private FlatMenuItemRenderer renderer;
|
private FlatMenuItemRenderer renderer;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatMenuUI();
|
return new FlatMenuUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -88,7 +123,6 @@ public class FlatMenuUI
|
|||||||
|
|
||||||
menuItem.setRolloverEnabled( true );
|
menuItem.setRolloverEnabled( true );
|
||||||
|
|
||||||
hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
|
|
||||||
renderer = createRenderer();
|
renderer = createRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +130,9 @@ public class FlatMenuUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
hoverBackground = null;
|
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||||
renderer = null;
|
renderer = null;
|
||||||
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
@@ -129,6 +164,50 @@ public class FlatMenuUI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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, "Menu" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatMenuItemUI.getStyleableInfos( this, renderer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatMenuItemUI.getStyleableValue( this, renderer, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public MethodHandles.Lookup getLookupForStyling() {
|
||||||
|
// MethodHandles.lookup() is caller sensitive and must be invoked in this class,
|
||||||
|
// otherwise it is not possible to access protected fields in JRE superclass
|
||||||
|
return MethodHandles.lookup();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getMinimumSize( JComponent c ) {
|
public Dimension getMinimumSize( JComponent c ) {
|
||||||
// avoid that top-level menus (in menu bar) are made smaller if horizontal space is rare
|
// avoid that top-level menus (in menu bar) are made smaller if horizontal space is rare
|
||||||
@@ -153,9 +232,15 @@ public class FlatMenuUI
|
|||||||
protected class FlatMenuRenderer
|
protected class FlatMenuRenderer
|
||||||
extends FlatMenuItemRenderer
|
extends FlatMenuItemRenderer
|
||||||
{
|
{
|
||||||
protected final Color menuBarUnderlineSelectionBackground = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionBackground", underlineSelectionBackground );
|
/** @since 3 */ protected Insets menuBarSelectionInsets = UIManager.getInsets( "MenuBar.selectionInsets" );
|
||||||
protected final Color menuBarUnderlineSelectionColor = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionColor", underlineSelectionColor );
|
/** @since 3 */ protected Insets menuBarSelectionEmbeddedInsets = UIManager.getInsets( "MenuBar.selectionEmbeddedInsets" );
|
||||||
protected final int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", underlineSelectionHeight );
|
/** @since 3 */ protected int menuBarSelectionArc = UIManager.getInt( "MenuBar.selectionArc" );
|
||||||
|
protected Color hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
|
||||||
|
/** @since 2.5 */ protected Color menuBarSelectionBackground = UIManager.getColor( "MenuBar.selectionBackground" );
|
||||||
|
/** @since 2.5 */ protected Color menuBarSelectionForeground = UIManager.getColor( "MenuBar.selectionForeground" );
|
||||||
|
protected Color menuBarUnderlineSelectionBackground = UIManager.getColor( "MenuBar.underlineSelectionBackground" );
|
||||||
|
protected Color menuBarUnderlineSelectionColor = UIManager.getColor( "MenuBar.underlineSelectionColor" );
|
||||||
|
protected int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", -1 );
|
||||||
|
|
||||||
protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
||||||
Font acceleratorFont, String acceleratorDelimiter )
|
Font acceleratorFont, String acceleratorDelimiter )
|
||||||
@@ -163,29 +248,85 @@ public class FlatMenuUI
|
|||||||
super( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
super( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g, Color selectionBackground ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
if( isUnderlineSelection() && ((JMenu)menuItem).isTopLevelMenu() )
|
super.paintBackground( g );
|
||||||
selectionBackground = menuBarUnderlineSelectionBackground;
|
|
||||||
|
|
||||||
ButtonModel model = menuItem.getModel();
|
if( ((JMenu)menuItem).isTopLevelMenu() && isHover() ) {
|
||||||
if( model.isRollover() && !model.isArmed() && !model.isSelected() &&
|
// paint hover background
|
||||||
model.isEnabled() && ((JMenu)menuItem).isTopLevelMenu() )
|
Color color = deriveBackground( getStyleFromMenuBarUI( ui -> ui.hoverBackground, hoverBackground ) );
|
||||||
{
|
if( isUnderlineSelection() ) {
|
||||||
g.setColor( deriveBackground( hoverBackground ) );
|
g.setColor( color );
|
||||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||||
} else
|
} else
|
||||||
super.paintBackground( g, selectionBackground );
|
paintSelection( g, color, selectionInsets, selectionArc );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
@Override
|
||||||
|
protected void paintSelection( Graphics g, Color selectionBackground, Insets selectionInsets, int selectionArc ) {
|
||||||
|
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
||||||
|
if( !isHover() )
|
||||||
|
selectionBackground = getStyleFromMenuBarUI( ui -> ui.selectionBackground, menuBarSelectionBackground, selectionBackground );
|
||||||
|
|
||||||
|
JMenuBar menuBar = (JMenuBar) menuItem.getParent();
|
||||||
|
JRootPane rootPane = SwingUtilities.getRootPane( menuBar );
|
||||||
|
if( rootPane != null && rootPane.getParent() instanceof Window &&
|
||||||
|
rootPane.getJMenuBar() == menuBar &&
|
||||||
|
FlatRootPaneUI.isMenuBarEmbedded( rootPane ) )
|
||||||
|
{
|
||||||
|
selectionInsets = getStyleFromMenuBarUI( ui -> ui.selectionEmbeddedInsets, menuBarSelectionEmbeddedInsets );
|
||||||
|
} else
|
||||||
|
selectionInsets = getStyleFromMenuBarUI( ui -> ui.selectionInsets, menuBarSelectionInsets );
|
||||||
|
|
||||||
|
selectionArc = getStyleFromMenuBarUI( ui -> (ui.selectionArc != -1)
|
||||||
|
? ui.selectionArc : null, menuBarSelectionArc );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintSelection( g, selectionBackground, selectionInsets, selectionArc );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
@Override
|
||||||
|
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionBackground,
|
||||||
|
Color underlineSelectionColor, int underlineSelectionHeight )
|
||||||
|
{
|
||||||
|
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
||||||
|
underlineSelectionBackground = getStyleFromMenuBarUI( ui -> ui.underlineSelectionBackground, menuBarUnderlineSelectionBackground, underlineSelectionBackground );
|
||||||
|
underlineSelectionColor = getStyleFromMenuBarUI( ui -> ui.underlineSelectionColor, menuBarUnderlineSelectionColor, underlineSelectionColor );
|
||||||
|
underlineSelectionHeight = getStyleFromMenuBarUI( ui -> (ui.underlineSelectionHeight != -1) ? ui.underlineSelectionHeight : null,
|
||||||
|
(menuBarUnderlineSelectionHeight != -1) ? menuBarUnderlineSelectionHeight : underlineSelectionHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintUnderlineSelection( g, underlineSelectionBackground, underlineSelectionColor, underlineSelectionHeight );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
|
protected void paintText( Graphics g, Rectangle textRect, String text, Color selectionForeground, Color disabledForeground ) {
|
||||||
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
if( ((JMenu)menuItem).isTopLevelMenu() && !isUnderlineSelection() )
|
||||||
underlineSelectionColor = menuBarUnderlineSelectionColor;
|
selectionForeground = getStyleFromMenuBarUI( ui -> ui.selectionForeground, menuBarSelectionForeground, selectionForeground );
|
||||||
underlineSelectionHeight = menuBarUnderlineSelectionHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
|
super.paintText( g, textRect, text, selectionForeground, disabledForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isHover() {
|
||||||
|
ButtonModel model = menuItem.getModel();
|
||||||
|
return model.isRollover() && !model.isArmed() && !model.isSelected() && model.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue, T defaultValue2 ) {
|
||||||
|
return getStyleFromMenuBarUI( f, (defaultValue != null) ? defaultValue : defaultValue2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue ) {
|
||||||
|
MenuBarUI ui = ((JMenuBar)menuItem.getParent()).getUI();
|
||||||
|
if( !(ui instanceof FlatMenuBarUI) )
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
T value = f.apply( (FlatMenuBarUI) ui );
|
||||||
|
return (value != null) ? value : defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user