From 2ea3d9d09dbfbfb3a4d9a90b47ba2e5b090c88d4 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 31 Jan 2013 14:52:30 +0400 Subject: [PATCH] IDEA-97665 Provide an option to specify fall back fonts It's possible to configure list of fonts to use. That instructs the IDE to try them sequentially if current font is unable to display particular symbol (old behavior - try the single configured font, randomly choose a fallback font able to display a symbol that can't be displayed by the configured one) --- platform/icons/src/actions/allLeft.png | Bin 0 -> 262 bytes platform/icons/src/actions/allLeft@2x.png | Bin 0 -> 413 bytes .../icons/src/actions/allLeft@2x_dark.png | Bin 0 -> 412 bytes platform/icons/src/actions/allLeft_dark.png | Bin 0 -> 262 bytes platform/icons/src/actions/allRight.png | Bin 0 -> 267 bytes platform/icons/src/actions/allRight@2x.png | Bin 0 -> 416 bytes .../icons/src/actions/allRight@2x_dark.png | Bin 0 -> 415 bytes platform/icons/src/actions/allRight_dark.png | Bin 0 -> 261 bytes platform/icons/src/actions/down.png | Bin 0 -> 201 bytes platform/icons/src/actions/down@2x.png | Bin 0 -> 286 bytes platform/icons/src/actions/down@2x_dark.png | Bin 0 -> 286 bytes platform/icons/src/actions/down_dark.png | Bin 0 -> 202 bytes platform/icons/src/actions/left.png | Bin 0 -> 212 bytes platform/icons/src/actions/left@2x.png | Bin 0 -> 306 bytes platform/icons/src/actions/left@2x_dark.png | Bin 0 -> 306 bytes platform/icons/src/actions/left_dark.png | Bin 0 -> 213 bytes platform/icons/src/actions/right.png | Bin 0 -> 209 bytes platform/icons/src/actions/right@2x.png | Bin 0 -> 306 bytes platform/icons/src/actions/right@2x_dark.png | Bin 0 -> 306 bytes platform/icons/src/actions/right_dark.png | Bin 0 -> 209 bytes platform/icons/src/actions/up.png | Bin 0 -> 203 bytes platform/icons/src/actions/up@2x.png | Bin 0 -> 276 bytes platform/icons/src/actions/up@2x_dark.png | Bin 0 -> 276 bytes platform/icons/src/actions/up_dark.png | Bin 0 -> 203 bytes .../colors/ColorAndFontDescriptionPanel.java | 2 +- .../options/colors/ColorAndFontOptions.java | 113 +--- .../options/colors/ConsoleFontOptions.java | 25 +- .../options/colors/FontEditorPreview.java | 9 +- .../options/colors/FontOptions.java | 513 +++++++++++------- .../editor/colors/EditorColorsScheme.java | 36 +- .../editor/colors/FontPreferences.java | 150 +++++ .../intellij/ui/components/JBMovePanel.java | 162 ------ .../application/options/SelectFontDialog.java | 136 ----- .../execution/impl/ConsoleViewUtil.java | 9 +- .../colors/impl/AbstractColorsScheme.java | 225 +++++--- .../colors/impl/DelegateColorScheme.java | 19 +- .../openapi/editor/ex/util/EditorUtil.java | 2 +- .../impl/ComplementaryFontsRegistry.java | 55 +- .../openapi/editor/impl/EditorImpl.java | 36 +- .../intellij/ui/components/JBMovePanel.java | 396 ++++++++++++++ .../src/messages/ApplicationBundle.properties | 3 + .../util/src/com/intellij/icons/AllIcons.java | 8 +- 42 files changed, 1174 insertions(+), 725 deletions(-) create mode 100644 platform/icons/src/actions/allLeft.png create mode 100644 platform/icons/src/actions/allLeft@2x.png create mode 100644 platform/icons/src/actions/allLeft@2x_dark.png create mode 100644 platform/icons/src/actions/allLeft_dark.png create mode 100644 platform/icons/src/actions/allRight.png create mode 100644 platform/icons/src/actions/allRight@2x.png create mode 100644 platform/icons/src/actions/allRight@2x_dark.png create mode 100644 platform/icons/src/actions/allRight_dark.png create mode 100644 platform/icons/src/actions/down.png create mode 100644 platform/icons/src/actions/down@2x.png create mode 100644 platform/icons/src/actions/down@2x_dark.png create mode 100644 platform/icons/src/actions/down_dark.png create mode 100644 platform/icons/src/actions/left.png create mode 100644 platform/icons/src/actions/left@2x.png create mode 100644 platform/icons/src/actions/left@2x_dark.png create mode 100644 platform/icons/src/actions/left_dark.png create mode 100644 platform/icons/src/actions/right.png create mode 100644 platform/icons/src/actions/right@2x.png create mode 100644 platform/icons/src/actions/right@2x_dark.png create mode 100644 platform/icons/src/actions/right_dark.png create mode 100644 platform/icons/src/actions/up.png create mode 100644 platform/icons/src/actions/up@2x.png create mode 100644 platform/icons/src/actions/up@2x_dark.png create mode 100644 platform/icons/src/actions/up_dark.png create mode 100644 platform/platform-api/src/com/intellij/openapi/editor/colors/FontPreferences.java delete mode 100644 platform/platform-api/src/com/intellij/ui/components/JBMovePanel.java delete mode 100644 platform/platform-impl/src/com/intellij/application/options/SelectFontDialog.java create mode 100644 platform/platform-impl/src/com/intellij/ui/components/JBMovePanel.java diff --git a/platform/icons/src/actions/allLeft.png b/platform/icons/src/actions/allLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..f3c7f65a641b6fe454c95201681df9b2ed9efb35 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XR(QHNhE&{2`t$$4J+o>4%P)$t308`oen9Lk zVi%hP|3NnxX1EbL>SO=F=|n#~=!3&UcVh`fo#JUGn( z-McgIJ``*8lm7bt)!7+Tz~b#cPOi{J^g z!2W(J)qxi$p@{#H7FZSNe0mOI_FWp zf*VjboRSQ12cAI*Jc2GsostZo$LWFN6@q&(Fr1POAX#&;c4jm?i;Qk9YFE8 zzqn-d6;wdaa77nakam7-OvKu7PI}-SG`WBpTs~XFIcdTVE}#{c&yve1bxx)r=Fz{g zDd!pIWDIxUmW!!$z={4EruEIK__R3xpU?;J0nRtTj{pMz4dHIKzK*zl00000NkvXX Hu0mjf`XQ_@ literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/allLeft@2x_dark.png b/platform/icons/src/actions/allLeft@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0913dd7402a6538c4de2b76c88264feda182a238 GIT binary patch literal 412 zcmV;N0b~A&P)$t308_-{D9b7 zXcwC_A)u+!1=+^hO8-LqgfwfgvkHL_3!B)*B7M?lZ7j61S?|DI7#3v|d85TVIL!gw zyEE@S&BSr6&RH2Bzz6UFYyrYBw0;NZgI?MNLC~{(ID6s?CL51NBpP&Ay94506I%A@`S zcc5Z8B^lruynzB3fk%=!B^f}E(<{eo09v49I3*oGv<{hq0Y~kHr=jn=ZMd9t0L9~8 zaLMQ^xCT##%e%OOr1K+VB7O|#qzAr1oeQYO<+C)LlP3J-0-AIA%(#pa=VS^Z9{q$( zIZZhyW4HoME~df`C;Drc)P_^>Z*l%Vp%35#TyB7^00RIq32wIcj?;Vq0000?ANQu}$WohRg4@ijTPJi+Dsco1@^N& zign0w3z2AOVqA4YxMMxz$FiDP8(SS^1m?F%E$KX>ev4tkR literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/allRight.png b/platform/icons/src/actions/allRight.png new file mode 100644 index 0000000000000000000000000000000000000000..f8df8bacdab6c751f33e23c9de0bbf8bb89cf11b GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X)_S@)hE&{2`t$$4J+o>uE%;Rg%zM(K{^#vkHS>;-%KnIzil;uhRsXkcJwIR8gWc9qC2U!cPo NJYD@<);T3K0RW%VU!DK} literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/allRight@2x.png b/platform/icons/src/actions/allRight@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f97485ad2b9b6107039cc4418ff8c0d10b566cca GIT binary patch literal 416 zcmV;R0bl-!P)qK?{>N-~k-8)c2~O<#Siy z8T1Y9qd`|OAaxEl;E4C9ps3N+3`iY=Ef|0doPc*rS2Z9t1Svn7gE7sRx~c(>?M~Q! z*@iRlYU!#5qz*ZNGf;v{5L>#c0gp%Ukw@|qT!V$Bs~YHBy^in8s^?s-tooi^Fm*Kp z5=2uDp9IkphtJg2Iv|rj0dJiA7cjDPwJng~xnKrJ@T`~trmmI)8G|Qh;H3PxsjDU7 znt@aBK4JT9UBy7my)CUEs?&enz|uHcZFKja&>3(B{+EHB00RIQzjlCgxP1)(0000< KMNUMnLSTZz3a+I9 literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/allRight@2x_dark.png b/platform/icons/src/actions/allRight@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d58e406048e63ec35ae4d6281197613e4359a7a3 GIT binary patch literal 415 zcmV;Q0bu@#P)Jym;!hB2Ic^+O_j#^BmH7o+2F{G5YmqHWckaE z|IW^S#jmQ$`^)m30cXG&_{l&NMGv^#1N*@y{Y!;m`0eipElf_q0vxo|_o|@fb2nfG z`iAz|psN^=x&W`>i1+89sL|C7NS%N;FaQ}i10R;IYC!53r2J?OhBRa9ss=o^J7N1} z8%E&S(p3#e9dZD#K?yEFZ0V{7JRZR(9?31Z1v5)mHPE?w9p9H#-*L6F>PL3L)YS|~ z5M6QjB#4$AK2ulgfK2`bymRu`;MCI9wm^bs%nXp=*)Ri4T`dPP22akwN%?V8S4+Yd z22R2IgzdL=6$3H%wzPt%PXBcSbK_{W(cOPSXTTZwUj}vp3;;bpc7UCE;gZ+~;RbuBe~E+z<3~M(ee6fV9M*6@ z?Vcpmk+vX#@lm$IdgYIuW)Dn47ORCQ_xMj?{M~Rvv}0<+4-0|#womcG$p?ZIzOg*& zcc|g$*sk!AlP$?y;5gGqeT{l0DS1`{zQ22b&S79=V|aK*T~;FPRwvNO44$rjF6*2U Fng9jTTpIuY literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/down.png b/platform/icons/src/actions/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1eba24f5449a49bcc941d5494242f8ab7f299f0c GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XvOQfKLn>}1{rUgjo>{e_v(d>Qi-DP$dzV9LX{q&uRRk6-KG{22y6SdTC|)Cirj=RM*WP`HTs xqp`qmrjL9I-`F1Y-w-kEQ%gO?%fMm4U_4Xe)2}1{rUgj{;&hnu|W17tAs0zi}@r<8SL0aL_|uM zRvK}=eKF4C%CIhd0be$~ywMgC4V9J?x;%-f$pW;akh4DJv9jGaB6g$@EcO zr)d7dqH+(z37tJhN`*R@FFq1K!q;%h@WL&|7n*Y>%{g?yDN$~^Yf}F;R*=gMtYCJN gH87E75J+G+UYzxJ@f9aCpkEj~UHx3vIVCg!0PE&yX8-^I literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/down@2x_dark.png b/platform/icons/src/actions/down@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5169155e79a3b50a36619ef65bcce9ed375cdbb9 GIT binary patch literal 286 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G2RvOILn>}1{rUgj{;&hnu|W17tAs0zi}@r<8SL0~qPDCM z_Lv%&;a(mSBjaa0gCk=d!=t4l5qy`T`}`Rd*&CYFIXk{jO#ErL;@69!yD!!}1{rUgjo>{e_v(d>Qi-DP$d)I+QuHCm9Ls;c( z?-mvorv8WtU_Ihpn8DULUHB7|MxqMiM>~^`wE-XhA89$LufWIfXmY^6Oa;ECE@9b@ w`HeTkJIWb0nhVq)S=Lc#q8XgW;LyOx;KD2MX@|$g44}OXp00i_>zopr0N;#6?EnA( literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/left.png b/platform/icons/src/actions/left.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1248bd9ba1c030aef4d755c6b78611b793f82f GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X$~;{hLn>}1{rUgjo>{e_v(d?6Bcsj@mes3QPu$t#aOc{s zTTz~U+&3C33S;f>2C@dgKx4s+&>mOC4FbV!{2!PCL~=<*ba4^kbm zjTQ2$FCQoiR5N`HDq<33t79zG5wJhJw4w0DbJi|i1`Y#;Pwz#2ip@@~0lI*})78&q Iol`;+01&}UPyhe` literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/left@2x.png b/platform/icons/src/actions/left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..32a0c91ae3b30b49bf2f40b7a58ab124e0a116ae GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GS3F%DLn>}1{rUgj{;&hnu|W17tArC43l=PBSPmt+LT*Kt&NdwiNyluj^xH4 z*B#mp1Sx!Dd32sxlJ$4P4bhHx{uC(-&Ld$CHR%e%4`o*k*;e| zJF}EIQ2NjT{S2{Mvs-F1r3Y3pyU99eF>n|#WL)}1{rUgj{;&hnu|W17tArC42^SZ+vYcgl)VE{D zj-nu$11_rl8yG((Dd;JODszkKJZFDY>hQ*;FU?CmdKI;Vst0Qt6S AC;$Ke literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/left_dark.png b/platform/icons/src/actions/left_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc88a4af8bb5980fe9ae39d7acb25677ec40fdc GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X$~|2iLn>}1{rUgjo>{e_v(d?6Bcsj@7IEFEmNTg=kGAdD zvBRq<<^bD~?#3NWD&h`|`U3e3N$QjKGO#Ri*dy6-_9X8S*CQFn(j8<3<}W+aaNXez z*OA{Ep6v3CH-tN;PZI7h_`uzf-1tLMkG03yUOym*!J&bX;g7JWkK0}MIG__4JYD@< J);T3K0RUcrNudA$ literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/right.png b/platform/icons/src/actions/right.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b97679a6218c6abe676f134fcf900235f41645 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XialK%Ln>}1{rUgjo>{e_v(d?6Bcsj^l~t=(-);;M6*&C& z#;sdkleo1SDhvfS2R>@eP`Jl;WY3hAMqz>XY)OG$Oc!N3!~>HKWGeJ2UvH>&c*AvM z{Yk?FO@V5rkM2cG8>Ksv8-Iw~NlUcX#VxqO(7?dV@M61|T%Z`sLZI~wp00i_>zopr E0Nue!SO5S3 literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/right@2x.png b/platform/icons/src/actions/right@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..29e3a8abf27ef627c2f9efb32051714c27900efe GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GS3F%DLn>}1{rUgj{;&hnu|W17tArDl3xI&zV=A*@T(7X2 zkHRS%H6xi=t|Q%zGkT>I54bGbm!WWv@5mqKrwjrGOpk0GbgTmS7#M{W?AVTI0R`Ds zJXLU?!9RsrV!_1?(o(w2j~E0Vw5pwX(OAU5Y?9ryDdVVvWkbpVr_|4NjDpUXO@geCyY%WeMv literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/right@2x_dark.png b/platform/icons/src/actions/right@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7d6a180c2272442d7c74cfef9fdb0f3025971731 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GS3F%DLn>}1{rUgj{;&hnu|W17tArDl2^SZ+#yYH$>G+t{ z)7`Cn%0|sdCYI|+cjJs+Da8XW%l2g`+~Yg)hxsXkKmpSuTL&Gh06qprVFf$3BU(T~ zwiQnm+-LAlVU}2Maf7s!F7qP>fd{Q>XI?ZGF)*8CH*Lx|>R{QBa=`z;IVh{}t>sdQKD!^|M$w(qf?qKN#O!u#p8u}&U{J<} zdYO(}0#_6|Thn%4G<&#$*-h5q6+;)JLjxlNi>Oz#=f0v#K>sm#y85}Sb4q9e06N=l ArvLx| literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/right_dark.png b/platform/icons/src/actions/right_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..297da5a4a61bbdde93d6272f3778b4374caa9156 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XialK%Ln>}1{rUgjo>{e_v(d?6Bcsj^6*1kYD||~&JX@;5GpC`#T%bEhsN>m!goQ^ME-x@px!zFg@P_Ni z`jdtUngZ2KAKi}1{rUgjo>{e_v(d?bhbO^Ne8swTZqK@yJ}N2n zF+aL)aPZo-uthNkxR1%ohFYL5- yJSxd4d4cW7MT;0Vq4zEub4^tFn3x%uco-He7IIlrv+*;~Vg^rFKbLh*2~7YVBtxSB literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/up@2x.png b/platform/icons/src/actions/up@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6f8823c49783dc056022d912523fc837fccbaf0d GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G+dN$yLn>}1{rUgj{;&hnu|W17tAs0zi}@t3@M&mhC@k5} zG4*d*}~%bX$|5eqx1j@t{~9Cz3=MaFr?i7j_HJDxW>33NSoJo@4hL$N{}|B)Pz zB!zEmD`b3S7cd=}-8h54TSh;`uQiNMfc4SafLTJODV7cL9oq$7T2Gjj8(Yo zopGZi=fYH`tB2iIGHZA~JYm_I!(QU>*;+N#^?63D!K((iyAH53F!3}1{rUgj{;&hnu|W17tAs0zi}@t3@I`FN5LEmt z8nBCb{-PZ_EanvHh*;Q3b=+R?=D5S2DKgG8PHefu+3~#5NucYwX6*_>bgx zBq@AjTOs2syMXD)?8X`V-7@+ieyw4A0<4eT2FwyNO|fi{@7ONz(t5(I+yL8x>&EITxlfT|Ml!l3By^;R(yu9QG22&(^A`uFo@K4PG_C-F1MSfr*EqNF#Eg%=%;e QKp!x8y85}Sb4q9e0A@R5*Z=?k literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/up_dark.png b/platform/icons/src/actions/up_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d26e1a4556ecda14df97a3e047711424ae9969ab GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xay?xfLn>}1{rUgjo>{e_v(d?bhbO^NJYq|Rpi#Jp3d@l~ zhd)wk65`_SQ@AS{D~tuI89s(7JX1f)o#U{FvE%H*nqY-Ec2V^V24#Ws%t`7dh3YFT xlogq8HCRZspLTdOS7Tf6vLlWO3=R#93>(FTT#kgx{svmi;OXk;vd$@?2>>!EKP~_O literal 0 HcmV?d00001 diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java index 0bd02363ea4f..3a3eb6338030 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java @@ -64,7 +64,7 @@ public class ColorAndFontDescriptionPanel extends JPanel { private ActionListener myActionListener; private JLabel myLabelFont; - private JLabel myInheritanceLabel = new JLabel(); + private JLabel myInheritanceLabel = new JLabel("X"); private final static Icon INHERITED_ICON = AllIcons.Ide.Link; diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index 07feda12dc6c..7008ef294702 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -234,11 +234,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract myColorsManager.removeAllSchemes(); for (MyColorScheme scheme : mySchemes.values()) { - if (!scheme.isDefault()) { - scheme.apply(); - myColorsManager.addColorsScheme(scheme.getOriginalScheme()); - } + if (!scheme.isDefault()) { + scheme.apply(); + myColorsManager.addColorsScheme(scheme.getOriginalScheme()); } + } EditorColorsScheme originalScheme = mySelectedScheme.getOriginalScheme(); myColorsManager.setGlobalScheme(originalScheme); @@ -990,27 +990,18 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } private static class MyColorScheme extends EditorColorsSchemeImpl { - private int myFontSize; - private float myLineSpacing; - private String myFontName; - - private int myConsoleFontSize; - private float myConsoleLineSpacing; - private String myConsoleFontName; private EditorSchemeAttributeDescriptor[] myDescriptors; - private String myName; + private String myName; private boolean myIsNew = false; private MyColorScheme(EditorColorsScheme parentScheme) { super(parentScheme, DefaultColorSchemesManager.getInstance()); - myFontSize = parentScheme.getEditorFontSize(); - myLineSpacing = parentScheme.getLineSpacing(); - myFontName = parentScheme.getEditorFontName(); + parentScheme.getFontPreferences().copyTo(getFontPreferences()); + setLineSpacing(parentScheme.getLineSpacing()); - myConsoleFontSize = parentScheme.getConsoleFontSize(); - myConsoleLineSpacing = parentScheme.getConsoleLineSpacing(); - myConsoleFontName = parentScheme.getConsoleFontName(); + parentScheme.getConsoleFontPreferences().copyTo(getConsoleFontPreferences()); + setConsoleLineSpacing(parentScheme.getConsoleLineSpacing()); setQuickDocFontSize(parentScheme.getQuickDocFontSize()); myName = parentScheme.getName(); @@ -1059,17 +1050,15 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } private boolean isFontModified() { - if (myFontSize != myParentScheme.getEditorFontSize()) return true; - if (myLineSpacing != myParentScheme.getLineSpacing()) return true; - if (!myFontName.equals(myParentScheme.getEditorFontName())) return true; - if (myQuickDocFontSize != myParentScheme.getQuickDocFontSize()) return true; + if (!getFontPreferences().equals(myParentScheme.getFontPreferences())) return true; + if (getLineSpacing() != myParentScheme.getLineSpacing()) return true; + if (getQuickDocFontSize() != myParentScheme.getQuickDocFontSize()) return true; return false; } private boolean isConsoleFontModified() { - if (myConsoleFontSize != myParentScheme.getConsoleFontSize()) return true; - if (myConsoleLineSpacing != myParentScheme.getConsoleLineSpacing()) return true; - if (!myConsoleFontName.equals(myParentScheme.getConsoleFontName())) return true; + if (!getConsoleFontPreferences().equals(myParentScheme.getConsoleFontPreferences())) return true; + if (getConsoleLineSpacing() != myParentScheme.getConsoleLineSpacing()) return true; return false; } @@ -1078,85 +1067,17 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } public void apply(EditorColorsScheme scheme) { - scheme.setEditorFontSize(myFontSize); - scheme.setEditorFontName(myFontName); + getFontPreferences().copyTo(scheme.getFontPreferences()); scheme.setLineSpacing(myLineSpacing); scheme.setQuickDocFontSize(getQuickDocFontSize()); - scheme.setConsoleFontSize(myConsoleFontSize); - scheme.setConsoleFontName(myConsoleFontName); - scheme.setConsoleLineSpacing(myConsoleLineSpacing); + getConsoleFontPreferences().copyTo(scheme.getConsoleFontPreferences()); + scheme.setConsoleLineSpacing(getConsoleLineSpacing()); for (EditorSchemeAttributeDescriptor descriptor : myDescriptors) { descriptor.apply(scheme); } } - @Override - public String getEditorFontName() { - return myFontName; - } - - @Override - public int getEditorFontSize() { - return myFontSize; - } - - @Override - public float getLineSpacing() { - return myLineSpacing; - } - - @Override - public void setEditorFontSize(int fontSize) { - myFontSize = fontSize; - initFonts(); - } - - @Override - public void setLineSpacing(float lineSpacing) { - assert lineSpacing >= 0 : lineSpacing; - myLineSpacing = lineSpacing; - } - - @Override - public void setEditorFontName(String fontName) { - myFontName = fontName; - initFonts(); - } - - @Override - public String getConsoleFontName() { - return myConsoleFontName; - } - - @Override - public void setConsoleFontName(String fontName) { - myConsoleFontName = fontName; - initFonts(); - } - - @Override - public int getConsoleFontSize() { - return myConsoleFontSize; - } - - @Override - public void setConsoleFontSize(int fontSize) { - myConsoleFontSize = fontSize; - initFonts(); - } - - @Override - public float getConsoleLineSpacing() { - return myConsoleLineSpacing; - } - - @Override - public void setConsoleLineSpacing(float lineSpacing) { - assert lineSpacing >= 0 : lineSpacing; - myConsoleLineSpacing = lineSpacing; - } - @Override public Object clone() { return null; diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java index 43b99ef3aef8..59e36910097b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,9 @@ */ package com.intellij.application.options.colors; +import com.intellij.openapi.editor.colors.FontPreferences; +import org.jetbrains.annotations.NotNull; + /** * User: anna */ @@ -23,24 +26,10 @@ public class ConsoleFontOptions extends FontOptions { super(options, "Console Font"); } + @NotNull @Override - protected String getCurrentFontName() { - return getCurrentScheme().getConsoleFontName(); - } - - @Override - protected void setCurrentFontName(String fontName) { - getCurrentScheme().setConsoleFontName(fontName); - } - - @Override - protected int getCurrentFontSize() { - return getCurrentScheme().getConsoleFontSize(); - } - - @Override - protected void setCurrentFontSize(int fontSize) { - getCurrentScheme().setConsoleFontSize(fontSize); + protected FontPreferences getFontPreferences() { + return getCurrentScheme().getConsoleFontPreferences(); } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontEditorPreview.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontEditorPreview.java index 94650dde6ef7..ddd24150b395 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/FontEditorPreview.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontEditorPreview.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,12 @@ public class FontEditorPreview implements PreviewPanel{ "advanced code editing and refactoring support.\n" + "\n" + "abcdefghijklmnopqrstuvwxyz 0123456789 (){}[]\n" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ +-*/= .,;:!? #&$%@|^"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ +-*/= .,;:!? #&$%@|^\n" + + // Create empty lines in order to make the gutter wide enough to display two-digits line numbers (other previews use long text + // and we don't want different gutter widths on color pages switching). + "\n" + + "\n" + + "\n"; } static void installTrafficLights(@NotNull EditorEx editor) { diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java index 2c91544a1724..ebe94f5bac8a 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2009 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,196 +17,198 @@ package com.intellij.application.options.colors; import com.intellij.application.options.OptionsConstants; -import com.intellij.application.options.SelectFontDialog; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.ui.FixedSizeButton; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ListSpeedSearch; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.ui.components.JBList; +import com.intellij.ui.components.JBMovePanel; import com.intellij.util.EventDispatcher; +import com.intellij.util.containers.ContainerUtilRt; +import com.intellij.util.ui.GridBag; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.DocumentEvent; +import javax.swing.event.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; +import java.util.*; +import java.util.List; public class FontOptions extends JPanel implements OptionsPanel{ - private final ColorAndFontOptions myOptions; - private JTextField myEditorFontSizeField; + private static List myFontNames; + private static List myMonospacedFontNames; - private JTextField myLineSpacingField; - private JTextField myFontNameField; - - private static ArrayList myFontNames; - private static ArrayList myMonospacedFontNames; private final EventDispatcher myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class); - private boolean myIsInSchemeChange = false; - private String myTitle; + + @NotNull private final ColorAndFontOptions myOptions; + + @NotNull private final DefaultListModel myAllFontsModel = new DefaultListModel(); + @NotNull private final JBList myAllFontsList = new JBList(myAllFontsModel); + @NotNull private final DefaultListModel mySelectedFontsModel = new DefaultListModel(); + @NotNull private final JBList mySelectedFontsList = new JBList(mySelectedFontsModel); + @NotNull private final JBMovePanel myFontsControl = new JBMovePanel(myAllFontsList, mySelectedFontsList) { + @SuppressWarnings("SSBasedInspection") + @Override + public void paint(Graphics g) { + super.paint(g); + if (myFontNames == null) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + initFontTables(); + } + }); + } + } + }; + + @NotNull private final JTextField myEditorFontSizeField = new MyTextField(4); + @NotNull private final JTextField myLineSpacingField = new MyTextField(4); + + @NotNull private final JBCheckBox myOnlyMonospacedCheckBox = + new JBCheckBox(ApplicationBundle.message("checkbox.show.only.monospaced.fonts")); + @Nullable private final Dimension myPreferredSize; + + private boolean myIsInSchemeChange; + private String myTitle; public FontOptions(ColorAndFontOptions options) { this(options, ApplicationBundle.message("group.editor.font")); } - protected FontOptions(ColorAndFontOptions options, final String title) { - super(new BorderLayout()); + protected FontOptions(@NotNull ColorAndFontOptions options, final String title) { + super(new GridBagLayout()); myOptions = options; myTitle = title; + add(createEditorFontPanel(), new GridBag().weightx(1).weighty(1).fillCell().coverLine()); + add(new JLabel(ApplicationBundle.message("label.fallback.fonts.list.description"), + MessageType.INFO.getDefaultIcon(), + SwingConstants.LEFT), + new GridBag().anchor(GridBagConstraints.WEST)); + myFontsControl.setShowButtons(JBMovePanel.ButtonType.LEFT, JBMovePanel.ButtonType.RIGHT); + myFontsControl.setListLabels(ApplicationBundle.message("title.font.available"), ApplicationBundle.message("title.font.selected")); + myFontsControl.setEnabled(false); // Disable the controls until fonts are loaded. + myFontsControl.setLeftInsertionStrategy(JBMovePanel.NATURAL_ORDER); + myOnlyMonospacedCheckBox.setSelected(EditorColorsManager.getInstance().isUseOnlyMonospacedFonts()); + new ListSpeedSearch(myAllFontsList); + new ListSpeedSearch(mySelectedFontsList); - JPanel schemesGroup = new JPanel(new BorderLayout()); - - JPanel panel = new JPanel(new BorderLayout()); - panel.add(createEditorFontPanel(), BorderLayout.NORTH); - schemesGroup.add(panel, BorderLayout.CENTER); - add(schemesGroup, BorderLayout.CENTER); + // Almost all other color scheme pages use the following pattern: + // + // __________________________________________ + // | color keys | color and font settings | + // + // Here page's height is calculated on the 'color and font settings' preferred height (debugged a lot to ensure that). + // The idea is to configure current page to use the same height as other pages. That's why we set it up to use the same preferred + // size as 'color and font settings' control. + myPreferredSize = new ColorAndFontDescriptionPanel().getPreferredSize(); + if (myFontNames != null) { + onFontsInit(); + } + initListeners(); } @Override - public void updateOptionsList() { - myIsInSchemeChange = true; - - myLineSpacingField.setText(Float.toString(getLineSpacing())); - myEditorFontSizeField.setText(Integer.toString(getCurrentFontSize())); - myFontNameField.setText(getCurrentFontName()); - - boolean enabled = !ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme()); - myLineSpacingField.setEnabled(enabled); - myEditorFontSizeField.setEditable(enabled); - myFontNameField.setEnabled(enabled); - - myIsInSchemeChange = false; - - } - - protected String getCurrentFontName() { - return getCurrentScheme().getEditorFontName(); - } - - protected void setCurrentFontName(String fontName) { - getCurrentScheme().setEditorFontName(fontName); - } - - - protected int getCurrentFontSize() { - return getCurrentScheme().getEditorFontSize(); - } - - protected void setCurrentFontSize(int fontSize) { - getCurrentScheme().setEditorFontSize(fontSize); - } - - protected float getLineSpacing() { - return getCurrentScheme().getLineSpacing(); - } - - protected void setCurrentLineSpacing(float lineSpacing) { - getCurrentScheme().setLineSpacing(lineSpacing); + public Dimension getMinimumSize() { + return getPreferredSize(); } @Override - @Nullable - public Runnable showOption(final String option) { - return null; + public Dimension getPreferredSize() { + return myPreferredSize == null ? super.getPreferredSize() : myPreferredSize; } - @Override - public void applyChangesToScheme() { - } - - @Override - public void selectOption(final String typeToSelect) { - } - - protected EditorColorsScheme getCurrentScheme() { - return myOptions.getSelectedScheme(); - } - - private JPanel createEditorFontPanel() { - JPanel editorFontPanel = new JPanel(); - editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(myTitle, false)); - editorFontPanel.setLayout(new GridBagLayout()); - GridBagConstraints gbConstraints = new GridBagConstraints(); - gbConstraints.fill = GridBagConstraints.HORIZONTAL; - gbConstraints.weightx = 0; - gbConstraints.weighty = 1; - gbConstraints.gridx = 0; - gbConstraints.gridy = 0; - gbConstraints.gridwidth = 1; - - gbConstraints.insets = new Insets(0, 0, 0, 0); - gbConstraints.gridwidth = 1; - editorFontPanel.add(new JLabel(ApplicationBundle.message("label.font.name")), gbConstraints); - - myFontNameField = new MyTextField(20); - myFontNameField.setEditable(false); - myFontNameField.setFocusable(false); - - gbConstraints.gridx = 1; - gbConstraints.insets = new Insets(0, 0, 0, 2); - editorFontPanel.add(myFontNameField, gbConstraints); - - JButton myFontNameButton = new FixedSizeButton(myFontNameField); - gbConstraints.gridx = 2; - gbConstraints.insets = new Insets(0, 0, 0, 8); - editorFontPanel.add(myFontNameButton, gbConstraints); - - gbConstraints.gridx = 3; - gbConstraints.insets = new Insets(0, 0, 0, 0); - editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.font.size")), gbConstraints); - gbConstraints.gridx = 4; - gbConstraints.insets = new Insets(0, 0, 0, 8); - myEditorFontSizeField = new MyTextField(4); - gbConstraints.gridx = 5; - editorFontPanel.add(myEditorFontSizeField, gbConstraints); - gbConstraints.insets = new Insets(0, 0, 0, 0); - gbConstraints.gridx = 6; - editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), gbConstraints); - gbConstraints.insets = new Insets(0, 0, 0, 0); - gbConstraints.gridx = 7; - myLineSpacingField = new MyTextField(4); - editorFontPanel.add(myLineSpacingField, gbConstraints); - gbConstraints.weightx = 1; - gbConstraints.gridx = 8; - editorFontPanel.add(new TailPanel(), gbConstraints); - - myFontNameButton.addActionListener(new ActionListener() { + private void initListeners() { + myOnlyMonospacedCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - EditorColorsScheme current = getCurrentScheme(); - if (ColorAndFontOptions.isReadOnly(current) || ColorSettingsUtil.isSharedScheme(current)) { - showReadOnlyMessage(FontOptions.this, ColorSettingsUtil.isSharedScheme(current)); - return; - } - - selectFont(); + boolean onlyMonospaced = myOnlyMonospacedCheckBox.isSelected(); + EditorColorsManager.getInstance().setUseOnlyMonospacedFonts(onlyMonospaced); + onFontsInit(); } }); + + mySelectedFontsModel.addListDataListener(new ListDataListener() { + @Override + public void intervalAdded(ListDataEvent e) { + syncFontFamilies(); + } + @Override + public void intervalRemoved(ListDataEvent e) { + syncFontFamilies(); + } + + @Override + public void contentsChanged(ListDataEvent e) { + syncFontFamilies(); + } + + private void syncFontFamilies() { + if (myIsInSchemeChange) { + return; + } + FontPreferences fontPreferences = getFontPreferences(); + fontPreferences.clearFonts(); + Enumeration elements = mySelectedFontsModel.elements(); + while (elements.hasMoreElements()) { + String fontFamily = (String)elements.nextElement(); + // Don't save a single 'default' font family at the font preferences. + if (mySelectedFontsModel.getSize() > 1 || !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily)) { + fontPreferences.addFontFamily(fontFamily); + } + } + } + }); + + mySelectedFontsList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + Object value = mySelectedFontsList.getSelectedValue(); + if (value != null) { + boolean toRestore = myIsInSchemeChange; + myIsInSchemeChange = true; + try { + myEditorFontSizeField.setText(String.valueOf(getFontPreferences().getSize((String)value))); + } + finally { + myIsInSchemeChange = toRestore; + } + } + } + }); + myEditorFontSizeField.getDocument().addDocumentListener(new DocumentAdapter() { @Override public void textChanged(DocumentEvent event) { - if (myIsInSchemeChange) return; - int fontSize = OptionsConstants.DEFAULT_EDITOR_FONT_SIZE; + if (myIsInSchemeChange || !SwingUtilities.isEventDispatchThread()) return; try { - fontSize = Integer.parseInt(myEditorFontSizeField.getText()); + int fontSize = Integer.parseInt(myEditorFontSizeField.getText()); + if (fontSize < 1) fontSize = 1; + if (fontSize > OptionsConstants.MAX_EDITOR_FONT_SIZE) fontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE; + Object selectedFont = mySelectedFontsList.getSelectedValue(); + if (selectedFont != null) { + FontPreferences fontPreferences = getFontPreferences(); + fontPreferences.register((String)selectedFont, fontSize); + } } catch (NumberFormatException e) { // OK, ignore } finally { - if (fontSize < 1) fontSize = 1; - if (fontSize > OptionsConstants.MAX_EDITOR_FONT_SIZE) fontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE; - - setCurrentFontSize(fontSize); updateDescription(true); } } @@ -234,32 +236,151 @@ public class FontOptions extends JPanel implements OptionsPanel{ } }); - return editorFontPanel; + } + + public static void showReadOnlyMessage(JComponent parent, final boolean sharedScheme) { + if (!sharedScheme) { + Messages.showMessageDialog( + parent, + ApplicationBundle.message("error.readonly.scheme.cannot.be.modified"), + ApplicationBundle.message("title.cannot.modify.readonly.scheme"), + Messages.getInformationIcon() + ); + } + else { + Messages.showMessageDialog( + parent, + ApplicationBundle.message("error.shared.scheme.cannot.be.modified"), + ApplicationBundle.message("title.cannot.modify.readonly.scheme"), + Messages.getInformationIcon() + ); + } } - private void selectFont() { - initFontTables(); + @Override + public void updateOptionsList() { + myIsInSchemeChange = true; - ArrayList fontNames = new ArrayList(myFontNames); - ArrayList monospacedFontNames = new ArrayList(myMonospacedFontNames); - String initialFontName = myFontNameField.getText(); - if (!fontNames.contains(EditorSettingsExternalizable.DEFAULT_FONT_NAME)) { - fontNames.add(0, EditorSettingsExternalizable.DEFAULT_FONT_NAME); + myLineSpacingField.setText(Float.toString(getLineSpacing())); + mySelectedFontsModel.clear(); + FontPreferences fontPreferences = getFontPreferences(); + List fontFamilies = fontPreferences.getFontFamilies(); + Set selectedFonts = ContainerUtilRt.newHashSet(); + Object selectedValue = mySelectedFontsList.getSelectedValue(); + mySelectedFontsModel.clear(); + if (fontFamilies.isEmpty()) { + // Add default font. + mySelectedFontsModel.addElement(fontPreferences.getFontFamily()); + selectedFonts.add(fontPreferences.getFontFamily()); } - if (!fontNames.contains(initialFontName)) { - fontNames.add(0, initialFontName); + else { + for (String fontFamily : fontFamilies) { + mySelectedFontsModel.addElement(fontFamily); + selectedFonts.add(fontFamily); + } } - SelectFontDialog selectFontDialog = new SelectFontDialog(this, fontNames, initialFontName, monospacedFontNames); - selectFontDialog.show(); - if (!selectFontDialog.isOK()) { - return; + + int newSelectionIndex = 0; + if (selectedValue != null) { + newSelectionIndex = Math.max(0, mySelectedFontsModel.indexOf(selectedValue)); } - String fontName = selectFontDialog.getFontName(); - if (fontName != null) { - myFontNameField.setText(fontName); - setCurrentFontName(fontName); - updateDescription(true); + mySelectedFontsList.setSelectedIndex(newSelectionIndex); + + for (int i = myAllFontsModel.size() - 1; i >= 0; i--) { + if (selectedFonts.contains(myAllFontsModel.getElementAt(i))) { + myAllFontsModel.remove(i); + } } + myEditorFontSizeField.setText(String.valueOf(fontPreferences.getSize(fontPreferences.getFontFamily()))); + + boolean enabled = !ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme()); + myOnlyMonospacedCheckBox.setEnabled(enabled); + myLineSpacingField.setEnabled(enabled); + myEditorFontSizeField.setEditable(enabled); + myFontsControl.setEnabled(enabled); + + myIsInSchemeChange = false; + } + + private void onFontsInit() { + assert myFontNames != null; + Object selectedValue = myAllFontsList.getSelectedValue(); + myAllFontsModel.clear(); + List availableFonts = myOnlyMonospacedCheckBox.isSelected() ? myMonospacedFontNames : myFontNames; + int newSelectionIndex = 0; + int i = 0; + for (String name : availableFonts) { + if (!mySelectedFontsModel.contains(name)) { // Don't bother with performance here in assumption that fallback fonts sequence is short + myAllFontsModel.addElement(name); + if (name.equals(selectedValue)) { + newSelectionIndex = i; + } + i++; + } + } + myAllFontsList.setSelectedIndex(newSelectionIndex); + } + + @NotNull + protected FontPreferences getFontPreferences() { + return getCurrentScheme().getFontPreferences(); + } + + protected float getLineSpacing() { + return getCurrentScheme().getLineSpacing(); + } + + protected void setCurrentLineSpacing(float lineSpacing) { + getCurrentScheme().setLineSpacing(lineSpacing); + } + + @Override + @Nullable + public Runnable showOption(final String option) { + return null; + } + + @Override + public void applyChangesToScheme() { + } + + @Override + public void selectOption(final String typeToSelect) { + } + + protected EditorColorsScheme getCurrentScheme() { + return myOptions.getSelectedScheme(); + } + + private JPanel createEditorFontPanel() { + JPanel editorFontPanel = new JPanel(new GridBagLayout()); + Insets borderInsets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET, + IdeBorderFactory.TITLED_BORDER_LEFT_INSET, + 0, + IdeBorderFactory.TITLED_BORDER_RIGHT_INSET); + editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(myTitle, false, borderInsets)); + + Insets insets = new Insets(0, 0, 5, 0); + GridBag constraints = new GridBag().insets(insets); + editorFontPanel.add(myOnlyMonospacedCheckBox, constraints); + + insets.left = 8; + editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.font.size")), constraints); + + insets.left = 2; + editorFontPanel.add(myEditorFontSizeField, constraints); + + insets.left = 8; + editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), constraints); + + insets.left = 2; + editorFontPanel.add(myLineSpacingField, constraints); + + editorFontPanel.add(new JLabel(""), new GridBag().insets(insets).weightx(1).fillCellHorizontally().coverLine()); + + editorFontPanel.add(myFontsControl, new GridBag().weightx(1).weighty(1).fillCell().coverLine().insets(insets)); + + return editorFontPanel; } @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"}) @@ -285,22 +406,29 @@ public class FontOptions extends JPanel implements OptionsPanel{ return true; } - public static void showReadOnlyMessage(JComponent parent, final boolean sharedScheme) { - if (!sharedScheme) { - Messages.showMessageDialog( - parent, - ApplicationBundle.message("error.readonly.scheme.cannot.be.modified"), - ApplicationBundle.message("title.cannot.modify.readonly.scheme"), - Messages.getInformationIcon() - ); + @Override + public void addListener(ColorAndFontSettingsListener listener) { + myDispatcher.addListener(listener); + } + + @Override + public JPanel getPanel() { + return this; + } + + @Override + public Set processListOptions() { + return new HashSet(); + } + + private static class MyTextField extends JTextField { + private MyTextField(int size) { + super(size); } - else { - Messages.showMessageDialog( - parent, - ApplicationBundle.message("error.shared.scheme.cannot.be.modified"), - ApplicationBundle.message("title.cannot.modify.readonly.scheme"), - Messages.getInformationIcon() - ); + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); } } @@ -350,32 +478,13 @@ public class FontOptions extends JPanel implements OptionsPanel{ // JRE has problems working with the font. Just skip. } } + + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + onFontsInit(); + } + }); } } - - private static class MyTextField extends JTextField { - private MyTextField(int size) { - super(size); - } - - @Override - public Dimension getMinimumSize() { - return getPreferredSize(); - } - } - - @Override - public void addListener(ColorAndFontSettingsListener listener) { - myDispatcher.addListener(listener); - } - - @Override - public JPanel getPanel() { - return this; - } - - @Override - public Set processListOptions() { - return new HashSet(); - } } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java b/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java index 40f539235acc..d0e32bc0e239 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2009 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,15 +40,30 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, Schem Color getColor(ColorKey key); void setColor(ColorKey key, Color color); - int getEditorFontSize(); - void setEditorFontSize(int fontSize); - - FontSize getQuickDocFontSize(); - void setQuickDocFontSize(@NotNull FontSize fontSize); + /** + * The IDE has allowed to configure only a single font family for a while. However, that doesn't handle a situation when + * that font family is unable to display particular char - fallback font family was chosen randomly from the whole collection + * of all registered fonts. + *

+ * Now it's possible to specify more than one font, i.e. directly indicated 'fallback fonts sequence' (see {@link FontPreferences}). + * However, old single font-based API is still here in order to preserve backward compatibility ({@link #getEditorFontName()} and + * {@link #getEditorFontSize()}). I.e. those methods are just re-written in order to use {@link FontPreferences} object exposed + * by this method. + * + * @return font preferences to use + */ + @NotNull + FontPreferences getFontPreferences(); String getEditorFontName(); void setEditorFontName(String fontName); - + + int getEditorFontSize(); + void setEditorFontSize(int fontSize); + + FontSize getQuickDocFontSize(); + void setQuickDocFontSize(@NotNull FontSize fontSize); + Font getFont(EditorFontType key); void setFont(EditorFontType key, Font font); @@ -57,6 +72,13 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, Schem Object clone(); + /** + * @return console font preferences to use + * @see #getFontPreferences() + */ + @NotNull + FontPreferences getConsoleFontPreferences(); + String getConsoleFontName(); void setConsoleFontName(String fontName); diff --git a/platform/platform-api/src/com/intellij/openapi/editor/colors/FontPreferences.java b/platform/platform-api/src/com/intellij/openapi/editor/colors/FontPreferences.java new file mode 100644 index 000000000000..bc384e7b5bd7 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/editor/colors/FontPreferences.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * 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 + * + * http://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.intellij.openapi.editor.colors; + +import com.intellij.openapi.options.FontSize; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.util.containers.ContainerUtilRt; +import gnu.trove.TObjectIntHashMap; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.List; + +/** + * Utility class which holds collection of font families and theirs sizes. + *

+ * The basic idea is to allow end-user to configure not a single font but fonts list instead - every time particular font is unable + * to display particular char, next font is tried. This is an improvement over an old approach when it was possible to configure + * only a single font family. Fallback fonts were chosen randomly when that font family was unable to display particular char then. + * + * @author Denis Zhdanov + * @since 12/20/12 9:37 PM + */ +public class FontPreferences { + + @NonNls @NotNull public static final String DEFAULT_FONT_NAME = getDefaultFontName(); + public static final int DEFAULT_FONT_SIZE = FontSize.SMALL.getSize(); + + @NotNull private final TObjectIntHashMap myFontSizes = new TObjectIntHashMap(); + @NotNull private final List myFontFamilies = ContainerUtilRt.newArrayList(); + + /** + * Font size to use by default. Default value is {@link #DEFAULT_FONT_SIZE}. + */ + private int myTemplateFontSize = DEFAULT_FONT_SIZE; + + public void clear() { + myFontFamilies.clear(); + myFontSizes.clear(); + } + + public void clearFonts() { + myFontFamilies.clear(); + } + + public boolean hasSize(@NotNull String fontName) { + return myFontSizes.containsKey(fontName); + } + + public int getSize(@NotNull String fontFamily) { + int result = myFontSizes.get(fontFamily); + if (result <= 0) { + result = myTemplateFontSize; + } + return result > 0 ? result : DEFAULT_FONT_SIZE; + } + + public void setSize(@NotNull String fontFamily, int size) { + myFontSizes.put(fontFamily, size); + myTemplateFontSize = size; + } + + @NotNull + public List getFontFamilies() { + return myFontFamilies; + } + + public void register(@NotNull String fontFamily, int size) { + if (!myFontFamilies.contains(fontFamily)) { + myFontFamilies.add(fontFamily); + } + setSize(fontFamily, size); + } + + /** + * @return first element of the {@link #getFontFamilies() registered font families} (if any); + * {@link #DEFAULT_FONT_NAME} otherwise + */ + @NotNull + public String getFontFamily() { + return myFontFamilies.isEmpty() ? DEFAULT_FONT_NAME : myFontFamilies.get(0); + } + + public void addFontFamily(@NotNull String fontFamily) { + if (!myFontFamilies.contains(fontFamily)) { + myFontFamilies.add(fontFamily); + } + } + + public void copyTo(@NotNull final FontPreferences preferences) { + preferences.myFontFamilies.clear(); + preferences.myFontFamilies.addAll(myFontFamilies); + preferences.myFontSizes.clear(); + for (String fontFamily : myFontFamilies) { + if (myFontSizes.containsKey(fontFamily)) { + preferences.myFontSizes.put(fontFamily, myFontSizes.get(fontFamily)); + } + } + } + + @Override + public int hashCode() { + return myFontFamilies.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FontPreferences that = (FontPreferences)o; + + if (!myFontFamilies.equals(that.myFontFamilies)) return false; + for (String fontFamily : myFontFamilies) { + if (myFontSizes.get(fontFamily) != that.myFontSizes.get(fontFamily)) { + return false; + } + } + + return true; + } + + @NotNull + private static String getDefaultFontName() { + if (SystemInfo.isMacOSSnowLeopard) return "Menlo"; + if (SystemInfo.isXWindow) { + for (Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) { + if ("DejaVu Sans Mono".equals(font.getName())) { + return font.getFontName(); + } + } + } + return "Monospaced"; + } + +} diff --git a/platform/platform-api/src/com/intellij/ui/components/JBMovePanel.java b/platform/platform-api/src/com/intellij/ui/components/JBMovePanel.java deleted file mode 100644 index 069f8fc60f11..000000000000 --- a/platform/platform-api/src/com/intellij/ui/components/JBMovePanel.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * 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 - * - * http://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.intellij.ui.components; - -import com.intellij.openapi.ui.VerticalFlowLayout; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * @author Konstantin Bulenkov - */ -public class JBMovePanel extends JBPanel { - protected final JButton myMoveLeftButton; - protected final JButton myMoveAllLeftButton; - protected final JButton myMoveRightButton; - protected final JButton myMoveAllRightButton; - @NotNull protected final JList myLeft; - @NotNull protected final JList myRight; - - protected enum ButtonType {MOVE_LEFT, MOVE_RIGHT, MOVE_ALL_LEFT, MOVE_ALL_RIGHT} - - public JBMovePanel(@NotNull JList left, @NotNull JList right) { - setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - assertModelIsEditable(left); - assertModelIsEditable(right); - myLeft = left; - myRight = right; - final JPanel buttonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE)); - buttonsPanel.add(myMoveLeftButton = createButton(ButtonType.MOVE_RIGHT)); - buttonsPanel.add(myMoveRightButton = createButton(ButtonType.MOVE_LEFT)); - buttonsPanel.add(myMoveAllLeftButton = createButton(ButtonType.MOVE_ALL_RIGHT)); - buttonsPanel.add(myMoveAllRightButton = createButton(ButtonType.MOVE_ALL_LEFT)); - final Dimension size = new Dimension(getButtonsWidth(), buttonsPanel.getPreferredSize().height); - buttonsPanel.setPreferredSize(size); - buttonsPanel.setMaximumSize(size); - - add(new JBScrollPane(left)); - add(buttonsPanel); - add(new JBScrollPane(right)); - } - - private static void assertModelIsEditable(JList list) { - assert list.getModel() instanceof DefaultListModel: String.format("List model should extends %s interface", DefaultListModel.class.getName()); - } - - protected JButton createButton(@NotNull final ButtonType type) { - final int size = 20; - final JButton button = new JButton(getButtonText(type)) { - @Override - public Dimension getPreferredSize() { - return new Dimension(getButtonsWidth(), size); - } - - @Override - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - @Override - public Dimension getMaximumSize() { - return getPreferredSize(); - } - }; - - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - switch (type) { - case MOVE_LEFT: - doMoveLeft(); - break; - case MOVE_RIGHT: - doMoveRight(); - break; - case MOVE_ALL_LEFT: - doMoveAllLeft(); - break; - case MOVE_ALL_RIGHT: - doMoveAllRight(); - break; - } - } - }); - return button; - } - - protected int getButtonsWidth() { - return 150; - } - - protected void doMoveRight() { - move(myRight, myLeft); - } - - protected void doMoveLeft() { - move(myLeft, myRight); - } - - protected void doMoveAllLeft() { - moveAll(myLeft, myRight); - } - - protected void doMoveAllRight() { - moveAll(myRight, myLeft); - } - - private static void move(JList to, JList from) { - final Object[] values = from.getSelectedValues(); - final int[] indices = from.getSelectedIndices(); - for (int i = indices.length - 1; i >=0; i--) { - ((DefaultListModel)from.getModel()).remove(i); - } - for (Object value : values) { - ((DefaultListModel)to.getModel()).addElement(value); - } - } - - private static void moveAll(JList to, JList from) { - final DefaultListModel fromModel = (DefaultListModel)from.getModel(); - final DefaultListModel toModel = (DefaultListModel)to.getModel(); - while (fromModel.getSize() > 0) { - toModel.addElement(fromModel.remove(0)); - } - } - - protected String getButtonText(@NotNull ButtonType type) { - switch (type) { - case MOVE_LEFT: return "Move <<"; - case MOVE_RIGHT: return "Move >>"; - case MOVE_ALL_LEFT: return "Move All <<"; - case MOVE_ALL_RIGHT: return "Move All >>"; - } - throw new IllegalArgumentException("Unknown button type: " + type); - } - - public static void main(String[] args) { - final JBMovePanel panel = new JBMovePanel(new JBList("asdas", "weqrwe", "ads12312", "aZSD23"), - new JBList("123412", "as2341", "aaaaaaaaaaa", "ZZZZZZZZZZ", "12")); - final JFrame test = new JFrame("Test"); - test.setContentPane(panel); - test.setSize(500, 500); - test.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - test.setVisible(true); - } -} diff --git a/platform/platform-impl/src/com/intellij/application/options/SelectFontDialog.java b/platform/platform-impl/src/com/intellij/application/options/SelectFontDialog.java deleted file mode 100644 index 4e2488302c9c..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/SelectFontDialog.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * 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 - * - * http://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.intellij.application.options; - -import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.ui.DoubleClickListener; -import com.intellij.ui.ListScrollingUtil; -import com.intellij.ui.ListSpeedSearch; -import com.intellij.ui.ScrollPaneFactory; -import com.intellij.ui.components.JBList; - -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.util.List; - -public class SelectFontDialog extends DialogWrapper { - private JList myFontList; - private JCheckBox myShowMonospacedCheckbox; - private final List myFontNames; - private final String myInitialFontName; - private final List myMonospacedFontNames; - - public SelectFontDialog(Component parent, List fontNames, String initialFontName, List monospacedFontNames) { - super(parent, true); - myMonospacedFontNames = monospacedFontNames; - setTitle(ApplicationBundle.message("title.select.font")); - myFontNames = fontNames; - myInitialFontName = initialFontName; - init(); - } - - protected JComponent createCenterPanel() { - myShowMonospacedCheckbox = new JCheckBox(ApplicationBundle.message("checkbox.show.only.monospaced.fonts")); - final boolean useOnlyMonospacedFonts = EditorColorsManager.getInstance().isUseOnlyMonospacedFonts(); - myFontList = new JBList(); - new ListSpeedSearch(myFontList); - myFontList.setModel(new DefaultListModel()); - fillList(useOnlyMonospacedFonts); - - new DoubleClickListener() { - @Override - protected boolean onDoubleClick(MouseEvent e) { - doOKAction(); - return true; - } - }.installOn(myFontList); - - myFontList.setCellRenderer(new MyListCellRenderer()); - - myShowMonospacedCheckbox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - boolean onlyMonospaced = myShowMonospacedCheckbox.isSelected(); - EditorColorsManager.getInstance().setUseOnlyMonospacedFonts(onlyMonospaced); - String selection = (String) myFontList.getSelectedValue(); - fillList(onlyMonospaced); - if (selection != null) { - myFontList.setSelectedValue(selection, true); - myFontList.ensureIndexIsVisible(myFontList.getSelectedIndex()); - } - } - }); - - JPanel panel = new JPanel(new BorderLayout()); - - panel.add(myShowMonospacedCheckbox, BorderLayout.NORTH); - panel.add(ScrollPaneFactory.createScrollPane(myFontList), BorderLayout.CENTER); - myShowMonospacedCheckbox.setSelected(useOnlyMonospacedFonts); - myFontList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - setOKActionEnabled(myFontList.getSelectedValue() != null); - } - }); - - return panel; - } - - private void fillList(boolean onlyMonospaced) { - DefaultListModel model = (DefaultListModel) myFontList.getModel(); - model.removeAllElements(); - for (String fontName : myFontNames) { - if (!onlyMonospaced || myMonospacedFontNames.contains(fontName)) { - model.addElement(fontName); - } - } - } - - public void show() { - ListScrollingUtil.selectItem(myFontList, myInitialFontName); - super.show(); - } - - - - public JComponent getPreferredFocusedComponent() { - return myFontList; - } - - public String getFontName() { - return (String)myFontList.getSelectedValue(); - } - - private static class MyListCellRenderer extends DefaultListCellRenderer { - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - String fontName = (String) value; - c.setFont(new Font(fontName, Font.PLAIN, 14)); - return c; - } - } -} diff --git a/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java b/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java index 32311a47d7aa..6cd11dc3e3d2 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import com.intellij.openapi.editor.EditorSettings; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.EditorFontType; +import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.editor.colors.impl.DelegateColorScheme; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.EditorFactoryImpl; @@ -81,6 +82,12 @@ public class ConsoleViewUtil { return color == null ? super.getDefaultBackground() : color; } + @NotNull + @Override + public FontPreferences getFontPreferences() { + return getConsoleFontPreferences(); + } + @Override public int getEditorFontSize() { return getConsoleFontSize(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index 8f1e9093a4fc..a336256af812 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -27,8 +27,8 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.WriteExternalException; +import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.HashMap; import gnu.trove.THashMap; import org.jdom.Element; @@ -42,50 +42,49 @@ import java.util.List; public abstract class AbstractColorsScheme implements EditorColorsScheme { private static final int CURR_VERSION = 124; - - private static final FontSize DEFAULT_FONT_SIZE = FontSize.SMALL; - - protected EditorColorsScheme myParentScheme; - protected int myEditorFontSize; + private static final FontSize DEFAULT_FONT_SIZE = FontSize.SMALL; + + protected EditorColorsScheme myParentScheme; + protected FontSize myQuickDocFontSize = DEFAULT_FONT_SIZE; protected float myLineSpacing; - private final Map myFonts = new EnumMap(EditorFontType.class); - private String myEditorFontName; + @NotNull private final Map myFonts = new EnumMap(EditorFontType.class); + @NotNull private final FontPreferences myFontPreferences = new FontPreferences(); + @NotNull private final FontPreferences myConsoleFontPreferences = new FontPreferences(); + private String myFallbackFontName; private String mySchemeName; - private String myConsoleFontName; - private int myConsoleFontSize = -1; private float myConsoleLineSpacing = -1; // version influences XML format and triggers migration private int myVersion = CURR_VERSION; - protected Map myColorsMap = new HashMap(); - protected Map myAttributesMap = new HashMap(); + protected Map myColorsMap = ContainerUtilRt.newHashMap(); + protected Map myAttributesMap = ContainerUtilRt.newHashMap(); - @NonNls private static final String DEFAULT_FONT_NAME = getDefaultFontName(); - @NonNls private static final String EDITOR_FONT_NAME = "EDITOR_FONT_NAME"; + @NonNls private static final String EDITOR_FONT = "font"; + @NonNls private static final String CONSOLE_FONT = "console-font"; + @NonNls private static final String EDITOR_FONT_NAME = "EDITOR_FONT_NAME"; @NonNls private static final String CONSOLE_FONT_NAME = "CONSOLE_FONT_NAME"; - @NonNls protected static final String SCHEME_NAME = "SCHEME_NAME"; protected DefaultColorSchemesManager myDefaultColorSchemesManager; - private Color myDeprecatedBackgroundColor = null; - @NonNls private static final String SCHEME_ELEMENT = "scheme"; - @NonNls public static final String NAME_ATTR = "name"; - @NonNls private static final String VERSION_ATTR = "version"; - @NonNls private static final String DEFAULT_SCHEME_ATTR = "default_scheme"; - @NonNls private static final String PARENT_SCHEME_ATTR = "parent_scheme"; - @NonNls private static final String OPTION_ELEMENT = "option"; - @NonNls private static final String COLORS_ELEMENT = "colors"; - @NonNls private static final String ATTRIBUTES_ELEMENT = "attributes"; - @NonNls private static final String VALUE_ELEMENT = "value"; - @NonNls private static final String BACKGROUND_COLOR_NAME = "BACKGROUND"; - @NonNls private static final String LINE_SPACING = "LINE_SPACING"; - @NonNls private static final String CONSOLE_LINE_SPACING = "CONSOLE_LINE_SPACING"; - @NonNls private static final String EDITOR_FONT_SIZE = "EDITOR_FONT_SIZE"; - @NonNls private static final String CONSOLE_FONT_SIZE = "CONSOLE_FONT_SIZE"; + private Color myDeprecatedBackgroundColor = null; + @NonNls private static final String SCHEME_ELEMENT = "scheme"; + @NonNls public static final String NAME_ATTR = "name"; + @NonNls private static final String VERSION_ATTR = "version"; + @NonNls private static final String DEFAULT_SCHEME_ATTR = "default_scheme"; + @NonNls private static final String PARENT_SCHEME_ATTR = "parent_scheme"; + @NonNls private static final String OPTION_ELEMENT = "option"; + @NonNls private static final String COLORS_ELEMENT = "colors"; + @NonNls private static final String ATTRIBUTES_ELEMENT = "attributes"; + @NonNls private static final String VALUE_ELEMENT = "value"; + @NonNls private static final String BACKGROUND_COLOR_NAME = "BACKGROUND"; + @NonNls private static final String LINE_SPACING = "LINE_SPACING"; + @NonNls private static final String CONSOLE_LINE_SPACING = "CONSOLE_LINE_SPACING"; + @NonNls private static final String EDITOR_FONT_SIZE = "EDITOR_FONT_SIZE"; + @NonNls private static final String CONSOLE_FONT_SIZE = "CONSOLE_FONT_SIZE"; @NonNls private static final String EDITOR_QUICK_JAVADOC_FONT_SIZE = "EDITOR_QUICK_DOC_FONT_SIZE"; protected AbstractColorsScheme(EditorColorsScheme parentScheme, DefaultColorSchemesManager defaultColorSchemesManager) { @@ -125,12 +124,10 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { public abstract Object clone(); public void copyTo(AbstractColorsScheme newScheme) { - newScheme.myEditorFontSize = myEditorFontSize; + myFontPreferences.copyTo(newScheme.myFontPreferences); newScheme.myLineSpacing = myLineSpacing; - newScheme.setEditorFontName(getEditorFontName()); newScheme.myQuickDocFontSize = myQuickDocFontSize; - newScheme.myConsoleFontName = myConsoleFontName; - newScheme.myConsoleFontSize = myConsoleFontSize; + myConsoleFontPreferences.copyTo(newScheme.myConsoleFontPreferences); newScheme.myConsoleLineSpacing = myConsoleLineSpacing; final Set types = myFonts.keySet(); @@ -146,13 +143,14 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { @Override public void setEditorFontName(String fontName) { - myEditorFontName = fontName; + myFontPreferences.clear(); + myFontPreferences.register(fontName, getEditorFontSize()); initFonts(); } @Override public void setEditorFontSize(int fontSize) { - myEditorFontSize = fontSize; + myFontPreferences.setSize(getEditorFontName(), fontSize); initFonts(); } @@ -176,17 +174,23 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { mySchemeName = name; } + @NotNull + @Override + public FontPreferences getFontPreferences() { + return myFontPreferences; + } + @Override public String getEditorFontName() { if (myFallbackFontName != null) { return myFallbackFontName; } - return myEditorFontName == null ? DEFAULT_FONT_NAME : myEditorFontName; + return myFontPreferences.getFontFamily(); } @Override public int getEditorFontSize() { - return myEditorFontSize; + return myFontPreferences.getSize(getEditorFontName()); } @NotNull @@ -207,7 +211,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize); if (plainFont.getFamily().equals("Dialog") && !editorFontName.equals("Dialog")) { - editorFontName = myParentScheme != null ? myParentScheme.getEditorFontName() : DEFAULT_FONT_NAME; + editorFontName = myParentScheme != null ? myParentScheme.getEditorFontName() : FontPreferences.DEFAULT_FONT_NAME; myFallbackFontName = editorFontName; plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize); } @@ -272,13 +276,20 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { for (final Object o : node.getChildren()) { Element childNode = (Element)o; - if (OPTION_ELEMENT.equals(childNode.getName())) { + String childName = childNode.getName(); + if (OPTION_ELEMENT.equals(childName)) { readSettings(childNode); } - else if (COLORS_ELEMENT.equals(childNode.getName())) { + else if (EDITOR_FONT.equals(childName)) { + readFontSettings(childNode, myFontPreferences); + } + else if (CONSOLE_FONT.equals(childName)) { + readFontSettings(childNode, myConsoleFontPreferences); + } + else if (COLORS_ELEMENT.equals(childName)) { readColors(childNode); } - else if (ATTRIBUTES_ELEMENT.equals(childNode.getName())) { + else if (ATTRIBUTES_ELEMENT.equals(childName)) { readAttributes(childNode); } } @@ -365,7 +376,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { myLineSpacing = Float.parseFloat(value); } else if (EDITOR_FONT_SIZE.equals(name)) { - myEditorFontSize = Integer.parseInt(value); + setEditorFontSize(Integer.parseInt(value)); } else if (EDITOR_FONT_NAME.equals(name)) { setEditorFontName(value); @@ -384,6 +395,32 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { } } + private static void readFontSettings(@NotNull Element element, @NotNull FontPreferences preferences) { + List children = element.getChildren(OPTION_ELEMENT); + String fontFamily = null; + int size = -1; + for (Object child : children) { + Element e = (Element)child; + if (EDITOR_FONT_NAME.equals(e.getAttributeValue(NAME_ATTR))) { + fontFamily = e.getAttributeValue(VALUE_ELEMENT); + } + else if (EDITOR_FONT_SIZE.equals(e.getAttributeValue(NAME_ATTR))) { + try { + size = Integer.parseInt(e.getAttributeValue(VALUE_ELEMENT)); + } + catch (NumberFormatException ex) { + // ignore + } + } + } + if (fontFamily != null && size > 1) { + preferences.register(fontFamily, size); + } + else if (fontFamily != null) { + preferences.addFontFamily(fontFamily); + } + } + @Override public void writeExternal(Element parentNode) throws WriteExternalException { parentNode.setAttribute(NAME_ATTR, getName()); @@ -398,23 +435,37 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { element.setAttribute(VALUE_ELEMENT, String.valueOf(getLineSpacing())); parentNode.addContent(element); - element = new Element(OPTION_ELEMENT); - element.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE); - element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize())); - parentNode.addContent(element); - - if (!Comparing.strEqual(getConsoleFontName(), getEditorFontName())) { + // IJ has used a 'single customizable font' mode for ages. That's why we want to support that format now, when it's possible + // to specify fonts sequence (see getFontPreferences()), there are big chances that many clients still will use a single font. + // That's why we want to use old format when zero or one font is selected and 'extended' format otherwise. + boolean useOldFontFormat = myFontPreferences.getFontFamilies().size() <= 1; + if (useOldFontFormat) { element = new Element(OPTION_ELEMENT); - element.setAttribute(NAME_ATTR, CONSOLE_FONT_NAME); - element.setAttribute(VALUE_ELEMENT, getConsoleFontName()); + element.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE); + element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize())); parentNode.addContent(element); } + else { + writeFontPreferences(EDITOR_FONT, parentNode, myFontPreferences); + } - if (getConsoleFontSize() != getEditorFontSize()) { - element = new Element(OPTION_ELEMENT); - element.setAttribute(NAME_ATTR, CONSOLE_FONT_SIZE); - element.setAttribute(VALUE_ELEMENT, Integer.toString(getConsoleFontSize())); - parentNode.addContent(element); + if (!myFontPreferences.equals(myConsoleFontPreferences)) { + if (myConsoleFontPreferences.getFontFamilies().size() <= 1) { + element = new Element(OPTION_ELEMENT); + element.setAttribute(NAME_ATTR, CONSOLE_FONT_NAME); + element.setAttribute(VALUE_ELEMENT, getConsoleFontName()); + parentNode.addContent(element); + + if (getConsoleFontSize() != getEditorFontSize()) { + element = new Element(OPTION_ELEMENT); + element.setAttribute(NAME_ATTR, CONSOLE_FONT_SIZE); + element.setAttribute(VALUE_ELEMENT, Integer.toString(getConsoleFontSize())); + parentNode.addContent(element); + } + } + else { + writeFontPreferences(CONSOLE_FONT, parentNode, myConsoleFontPreferences); + } } if (getConsoleLineSpacing() != getLineSpacing()) { @@ -431,10 +482,12 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { parentNode.addContent(element); } - element = new Element(OPTION_ELEMENT); - element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME); - element.setAttribute(VALUE_ELEMENT, getEditorFontName()); - parentNode.addContent(element); + if (useOldFontFormat) { + element = new Element(OPTION_ELEMENT); + element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME); + element.setAttribute(VALUE_ELEMENT, getEditorFontName()); + parentNode.addContent(element); + } Element colorElements = new Element(COLORS_ELEMENT); Element attrElements = new Element(ATTRIBUTES_ELEMENT); @@ -446,6 +499,23 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { parentNode.addContent(attrElements); } + private static void writeFontPreferences(@NotNull String key, @NotNull Element parent, @NotNull FontPreferences preferences) { + for (String fontFamily : preferences.getFontFamilies()) { + Element element = new Element(key); + Element e = new Element(OPTION_ELEMENT); + e.setAttribute(NAME_ATTR, EDITOR_FONT_NAME); + e.setAttribute(VALUE_ELEMENT, fontFamily); + element.addContent(e); + + e = new Element(OPTION_ELEMENT); + e.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE); + e.setAttribute(VALUE_ELEMENT, String.valueOf(preferences.getSize(fontFamily))); + element.addContent(e); + + parent.addContent(element); + } + } + private boolean haveToWrite(final TextAttributesKey key, final TextAttributes value, final TextAttributes defaultAttribute) { if (key.getFallbackAttributeKey() != null && value.isFallbackEnabled()) return false; boolean hasDefaultValue = value.equals(defaultAttribute); @@ -507,30 +577,37 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { } + @NotNull + @Override + public FontPreferences getConsoleFontPreferences() { + return myConsoleFontPreferences; + } + @Override public String getConsoleFontName() { - if (myConsoleFontName == null) { - return getEditorFontName(); - } - return myConsoleFontName; + return myConsoleFontPreferences.getFontFamily(); } @Override public void setConsoleFontName(String fontName) { - myConsoleFontName = fontName; + myConsoleFontPreferences.clear(); + myConsoleFontPreferences.register(fontName, getConsoleFontSize()); } @Override public int getConsoleFontSize() { - if (myConsoleFontSize == -1) { + String font = getConsoleFontName(); + if (myConsoleFontPreferences.hasSize(font)) { + return myConsoleFontPreferences.getSize(font); + } + else { return getEditorFontSize(); } - return myConsoleFontSize; } @Override public void setConsoleFontSize(int fontSize) { - myConsoleFontSize = fontSize; + myConsoleFontPreferences.setSize(getConsoleFontName(), fontSize); initFonts(); } @@ -548,18 +625,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { myConsoleLineSpacing = lineSpacing; } - private static String getDefaultFontName() { - if (SystemInfo.isMacOSSnowLeopard) return "Menlo"; - if (SystemInfo.isXWindow) { - for (Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) { - if ("DejaVu Sans Mono".equals(font.getName())) { - return font.getFontName(); - } - } - } - return "Monospaced"; - } - protected TextAttributes getFallbackAttributes(TextAttributesKey fallbackKey) { if (fallbackKey == null) return null; if (myAttributesMap.containsKey(fallbackKey)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java index ec87288cdace..1e0b2e285007 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,7 @@ */ package com.intellij.openapi.editor.colors.impl; -import com.intellij.openapi.editor.colors.ColorKey; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.EditorFontType; -import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.util.InvalidDataException; @@ -81,6 +78,12 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { myDelegate.setColor(key, color); } + @NotNull + @Override + public FontPreferences getFontPreferences() { + return myDelegate.getFontPreferences(); + } + @Override public int getEditorFontSize() { return myDelegate.getEditorFontSize(); @@ -149,6 +152,12 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { return myDelegate.clone(); } + @NotNull + @Override + public FontPreferences getConsoleFontPreferences() { + return myDelegate.getConsoleFontPreferences(); + } + @Override public String getConsoleFontName() { return myDelegate.getConsoleFontName(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index 39c02174ec2f..d0f01dac2554 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -509,7 +509,7 @@ public class EditorUtil { public static FontInfo fontForChar(final char c, @JdkConstants.FontStyle int style, @NotNull Editor editor) { EditorColorsScheme colorsScheme = editor.getColorsScheme(); - return ComplementaryFontsRegistry.getFontAbleToDisplay(c, colorsScheme.getEditorFontSize(), style, colorsScheme.getEditorFontName()); + return ComplementaryFontsRegistry.getFontAbleToDisplay(c, style, colorsScheme.getFontPreferences()); } public static int charWidth(char c, @JdkConstants.FontStyle int fontType, @NotNull Editor editor) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java index 61eb84c04597..bf951719f926 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,14 @@ package com.intellij.openapi.editor.impl; import com.intellij.ide.ui.UISettings; import com.intellij.ide.ui.UISettingsListener; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import gnu.trove.TIntHashSet; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.*; @@ -140,8 +142,43 @@ public class ComplementaryFontsRegistry { boolean found = ourStyledFontNames.contains(styledFamilyName); return Pair.create(found ? styledFamilyName : familyName, found ? Font.PLAIN : style); } + + @NotNull + public static FontInfo getFontAbleToDisplay(char c, @JdkConstants.FontStyle int style, @NotNull FontPreferences preferences) { + boolean tryDefaultFont = true; + List fontFamilies = preferences.getFontFamilies(); + FontInfo result; + for (String fontFamily : fontFamilies) { + result = doGetFontAbleToDisplay(c, preferences.getSize(fontFamily), style, fontFamily); + if (result != null) { + return result; + } + tryDefaultFont &= !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily); + } + int size = FontPreferences.DEFAULT_FONT_SIZE; + if (!fontFamilies.isEmpty()) { + size = preferences.getSize(fontFamilies.get(0)); + } + if (tryDefaultFont) { + result = doGetFontAbleToDisplay(c, size, style, FontPreferences.DEFAULT_FONT_NAME); + if (result != null) { + return result; + } + } + return doGetFontAbleToDisplay(c, size, style); + } + @NotNull public static FontInfo getFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) { + FontInfo result = doGetFontAbleToDisplay(c, size, style, defaultFontFamily); + if (result != null) { + return result; + } + return doGetFontAbleToDisplay(c, size, style); + } + + @Nullable + private static FontInfo doGetFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) { synchronized (lock) { Pair p = fontFamily(defaultFontFamily, style); if (ourSharedKeyInstance.mySize == size && @@ -152,7 +189,7 @@ public class ComplementaryFontsRegistry { ( c < 128 || ourSharedDefaultFont.canDisplay(c) ) - ) { + ) { return ourSharedDefaultFont; } @@ -171,8 +208,16 @@ public class ComplementaryFontsRegistry { if (c < 128 || defaultFont.canDisplay(c)) { return defaultFont; } - - if (ourUndisplayableChars.contains(c)) return defaultFont; + else { + return null; + } + } + } + + @NotNull + private static FontInfo doGetFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style) { + synchronized (lock) { + if (ourUndisplayableChars.contains(c)) return ourSharedDefaultFont; final Collection descriptors = ourUsedFonts.values(); for (FontInfo font : descriptors) { @@ -193,7 +238,7 @@ public class ComplementaryFontsRegistry { ourUndisplayableChars.add(c); - return defaultFont; + return ourSharedDefaultFont; } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index a3ca917cd634..abcf5c5333e9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -81,6 +81,7 @@ import com.intellij.util.IJSwingUtilities; import com.intellij.util.Processor; import com.intellij.util.Producer; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.HashMap; import com.intellij.util.messages.MessageBusConnection; @@ -5683,13 +5684,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } private class MyColorSchemeDelegate implements EditorColorsScheme { - private final HashMap myOwnAttributes = new HashMap(); - private final HashMap myOwnColors = new HashMap(); + + private final FontPreferences myFontPreferences = new FontPreferences(); + private final Map myOwnAttributes = ContainerUtilRt.newHashMap(); + private final Map myOwnColors = ContainerUtilRt.newHashMap(); private final EditorColorsScheme myCustomGlobalScheme; - private Map myFontsMap = null; - private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE; - private int myFontSize = -1; - private String myFaceName = null; + private Map myFontsMap = null; + private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE; + private int myFontSize = -1; + private String myFaceName = null; private EditorColorsScheme myGlobalScheme; private MyColorSchemeDelegate(@Nullable final EditorColorsScheme globalScheme) { @@ -5711,6 +5714,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi String editorFontName = getEditorFontName(); int editorFontSize = getEditorFontSize(); + myFontPreferences.clear(); + myFontPreferences.register(editorFontName, editorFontSize); + myFontsMap = new EnumMap(EditorFontType.class); Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize); @@ -5796,6 +5802,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myGlobalScheme.setQuickDocFontSize(fontSize); } + @NotNull + @Override + public FontPreferences getFontPreferences() { + return myFontPreferences.getFontFamilies().isEmpty() ? getGlobal().getFontPreferences() : myFontPreferences; + } + @Override public String getEditorFontName() { if (myFaceName == null) { @@ -5858,6 +5870,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myMaxFontSize = Math.max(OptionsConstants.MAX_EDITOR_FONT_SIZE, globalFontSize); } + @NotNull + @Override + public FontPreferences getConsoleFontPreferences() { + return getGlobal().getConsoleFontPreferences(); + } + @Override public String getConsoleFontName() { return getGlobal().getConsoleFontName(); @@ -6282,7 +6300,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi for ( FoldRegion region = myFoldingModel.getCollapsedRegionAtOffset(endOffset); region != null && endOffset < myDocument.getTextLength(); - region = myFoldingModel.getCollapsedRegionAtOffset(endOffset)) { + region = myFoldingModel.getCollapsedRegionAtOffset(endOffset)) + { final int lineNumber = myDocument.getLineNumber(region.getEndOffset()); endOffset = myDocument.getLineEndOffset(lineNumber); } @@ -6583,7 +6602,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int x, int y, Color color, - @NotNull FontInfo fontInfo) { + @NotNull FontInfo fontInfo) + { drawCharsCached(g, data, start, end, x, y, fontInfo, color); } } diff --git a/platform/platform-impl/src/com/intellij/ui/components/JBMovePanel.java b/platform/platform-impl/src/com/intellij/ui/components/JBMovePanel.java new file mode 100644 index 000000000000..f530875475ad --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/components/JBMovePanel.java @@ -0,0 +1,396 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * 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 + * + * http://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.intellij.ui.components; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.impl.ActionButton; +import com.intellij.openapi.actionSystem.impl.PresentationFactory; +import com.intellij.openapi.ui.VerticalFlowLayout; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ListUtil; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.util.ui.GridBag; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.EnumMap; +import java.util.Enumeration; +import java.util.Map; + +/** + * A UI control which consists of two lists with ability to move elements between them. + *

+ * It looks as here. + * + * @author Konstantin Bulenkov + */ +public class JBMovePanel extends JBPanel { + + public static final String MOVE_PANEL_PLACE = "MOVE_PANEL"; + + public static final InsertPositionStrategy ANCHORING_SELECTION = new InsertPositionStrategy() { + @Override + public int getInsertionIndex(@NotNull Object data, @NotNull JList list) { + int index = list.getSelectedIndex(); + DefaultListModel model = (DefaultListModel)list.getModel(); + return index < 0 ? model.getSize() : index + 1; + } + }; + + public static final InsertPositionStrategy NATURAL_ORDER = new InsertPositionStrategy() { + @SuppressWarnings("unchecked") + @Override + public int getInsertionIndex(@NotNull Object data, @NotNull JList list) { + Enumeration elements = ((DefaultListModel)list.getModel()).elements(); + int index = 0; + while (elements.hasMoreElements()) { + Object e = elements.nextElement(); + // DefaultListModel is type-aware only since java7, so, use raw types until we're on java6. + if (((Comparable)e).compareTo(data) >= 0) { + break; + } + index++; + } + return index; + } + }; + + @NotNull private final Map myButtons = new EnumMap(ButtonType.class); + + @NotNull private final ListPanel myLeftPanel = new ListPanel(); + @NotNull private final ListPanel myRightPanel = new ListPanel(); + + @NotNull protected final JList myLeftList; + @NotNull protected final JList myRightList; + @NotNull protected final ActionButton myLeftButton; + @NotNull protected final ActionButton myAllLeftButton; + @NotNull protected final ActionButton myRightButton; + @NotNull protected final ActionButton myAllRightButton; + @NotNull protected final ActionButton myUpButton; + @NotNull protected final ActionButton myDownButton; + + @NotNull private InsertPositionStrategy myLeftInsertionStrategy = ANCHORING_SELECTION; + @NotNull private InsertPositionStrategy myRightInsertionStrategy = ANCHORING_SELECTION; + + private boolean myActivePreferredSizeProcessing; + + public enum ButtonType {LEFT, RIGHT, ALL_LEFT, ALL_RIGHT} + + public JBMovePanel(@NotNull JList left, @NotNull JList right) { + super(new GridBagLayout()); + assertModelIsEditable(left); + assertModelIsEditable(right); + myLeftList = left; + myRightList = right; + + final JPanel leftRightButtonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE)); + leftRightButtonsPanel.add(myRightButton = createButton(ButtonType.RIGHT)); + leftRightButtonsPanel.add(myAllRightButton = createButton(ButtonType.ALL_RIGHT)); + leftRightButtonsPanel.add(myLeftButton = createButton(ButtonType.LEFT)); + leftRightButtonsPanel.add(myAllLeftButton = createButton(ButtonType.ALL_LEFT)); + + myUpButton = createButton(new UpAction()); + myDownButton = createButton(new DownAction()); + final JPanel upDownButtonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE)); + upDownButtonsPanel.add(myUpButton); + upDownButtonsPanel.add(myDownButton); + + MouseListener mouseListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() != 2 || e.getButton() != MouseEvent.BUTTON1) { + return; + } + if (e.getSource() == myLeftList) { + doRight(); + } + else if (e.getSource() == myRightList) { + doLeft(); + } + } + }; + myLeftList.addMouseListener(mouseListener); + myRightList.addMouseListener(mouseListener); + + GridBag listConstraints = new GridBag().weightx(1).weighty(1).fillCell(); + GridBag buttonConstraints = new GridBag().anchor(GridBagConstraints.CENTER); + myLeftPanel.add(ScrollPaneFactory.createScrollPane(left), listConstraints); + add(myLeftPanel, listConstraints); + add(leftRightButtonsPanel, buttonConstraints); + myRightPanel.add(ScrollPaneFactory.createScrollPane(right), listConstraints); + add(myRightPanel, listConstraints); + add(upDownButtonsPanel, buttonConstraints); + } + + private static void assertModelIsEditable(@NotNull JList list) { + assert list.getModel() instanceof DefaultListModel : String + .format("List model should extends %s interface", DefaultListModel.class.getName()); + } + + public void setShowButtons(@NotNull ButtonType... types) { + for (ActionButton button : myButtons.values()) { + button.setVisible(false); + } + for (ButtonType type : types) { + myButtons.get(type).setVisible(true); + } + } + + public void setListLabels(@NotNull String left, @NotNull String right) { + // Border insets are used as a component insets (see JComponent.getInsets()). That's why an ugly bottom inset is used when + // we create a border with default insets. That is the reason why we explicitly specify bottom inset as zero. + Insets insets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET, + IdeBorderFactory.TITLED_BORDER_LEFT_INSET, + 0, + IdeBorderFactory.TITLED_BORDER_RIGHT_INSET); + myLeftPanel.setBorder(IdeBorderFactory.createTitledBorder(left, false, insets)); + myRightPanel.setBorder(IdeBorderFactory.createTitledBorder(right, false, insets)); + } + + public void setLeftInsertionStrategy(@NotNull InsertPositionStrategy leftInsertionStrategy) { + myLeftInsertionStrategy = leftInsertionStrategy; + } + + // Commented to preserve green code policy until this method is not used. Uncomment when necessary. + //public void setRightInsertionStrategy(@NotNull InsertPositionStrategy rightInsertionStrategy) { + // myRightInsertionStrategy = rightInsertionStrategy; + //} + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + myLeftList.setEnabled(enabled); + myRightList.setEnabled(enabled); + for (ActionButton button : myButtons.values()) { + button.setEnabled(enabled); + } + } + + @NotNull + private ActionButton createButton(@NotNull final ButtonType type) { + final AnAction action; + switch (type) { + case LEFT: + action = new LeftAction(); + break; + case RIGHT: + action = new RightAction(); + break; + case ALL_LEFT: + action = new AllLeftAction(); + break; + case ALL_RIGHT: + action = new AllRightAction(); + break; + default: throw new IllegalArgumentException("Unsupported button type: " + type); + } + + + ActionButton button = createButton(action); + myButtons.put(type, button); + return button; + } + + @NotNull + private static ActionButton createButton(@NotNull final AnAction action) { + PresentationFactory presentationFactory = new PresentationFactory(); + Icon icon = AllIcons.Actions.AllLeft; + Dimension size = new Dimension(icon.getIconWidth(), icon.getIconHeight()); + return new ActionButton(action, presentationFactory.getPresentation(action), MOVE_PANEL_PLACE, size); + } + + protected void doRight() { + moveBetween(myRightList, myRightInsertionStrategy, myLeftList); + } + + protected void doLeft() { + moveBetween(myLeftList, myLeftInsertionStrategy, myRightList); + } + + protected void doAllLeft() { + moveAllBetween(myLeftList, myRightList); + } + + protected void doAllRight() { + moveAllBetween(myRightList, myLeftList); + } + + private static void moveBetween(@NotNull JList to, @NotNull InsertPositionStrategy strategy, @NotNull JList from) { + final int[] indices = from.getSelectedIndices(); + if (indices.length <= 0) { + return; + } + + final Object[] values = from.getSelectedValues(); + for (int i = indices.length - 1; i >= 0; i--) { + ((DefaultListModel)from.getModel()).remove(indices[i]); + } + if (from.getModel().getSize() > 0) { + int newSelectionIndex = indices[0]; + newSelectionIndex = Math.min(from.getModel().getSize() - 1, newSelectionIndex); + from.setSelectedIndex(newSelectionIndex); + } + + to.clearSelection(); + DefaultListModel toModel = (DefaultListModel)to.getModel(); + int newSelectionIndex = -1; + for (Object value : values) { + if (!toModel.contains(value)) { + int i = strategy.getInsertionIndex(value, to); + if (newSelectionIndex < 0) { + newSelectionIndex = i; + } + toModel.add(i, value); + to.addSelectionInterval(i, i); + } + } + } + + private static void moveAllBetween(@NotNull JList to, @NotNull JList from) { + final DefaultListModel fromModel = (DefaultListModel)from.getModel(); + final DefaultListModel toModel = (DefaultListModel)to.getModel(); + while (fromModel.getSize() > 0) { + Object element = fromModel.remove(0); + if (!toModel.contains(element)) { + toModel.addElement(element); + } + } + } + + public static void main(String[] args) { + final JBMovePanel panel = new JBMovePanel(new JBList("asdas", "weqrwe", "ads12312", "aZSD23"), + new JBList("123412", "as2341", "aaaaaaaaaaa", "ZZZZZZZZZZ", "12")); + final JFrame test = new JFrame("Test"); + test.setContentPane(panel); + test.setSize(500, 500); + test.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + test.setVisible(true); + } + + public interface InsertPositionStrategy { + int getInsertionIndex(@NotNull Object data, @NotNull JList list); + } + + /** + * The general idea is to layout target lists to use the same width. This wrapper panel controls that. + */ + private class ListPanel extends JPanel { + + ListPanel() { + super(new GridBagLayout()); + } + + @Override + public Dimension getPreferredSize() { + Dimension d1 = super.getPreferredSize(); + if (myActivePreferredSizeProcessing) { + return d1; + } + myActivePreferredSizeProcessing = true; + try { + final Dimension d2; + if (myLeftPanel == this) { + d2 = myRightPanel.getPreferredSize(); + } + else { + d2 = myLeftPanel.getPreferredSize(); + } + return new Dimension(Math.max(d1.width, d2.width), Math.max(d1.height, d2.height)); + } + finally { + myActivePreferredSizeProcessing = false; + } + } + } + + private class LeftAction extends AnAction { + + LeftAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.Left); + } + + @Override + public void actionPerformed(AnActionEvent e) { + doLeft(); + } + } + + private class RightAction extends AnAction { + + RightAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.Right); + } + + @Override + public void actionPerformed(AnActionEvent e) { + doRight(); + } + } + + private class AllLeftAction extends AnAction { + + AllLeftAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.AllLeft); + } + + @Override + public void actionPerformed(AnActionEvent e) { + doAllLeft(); + } + } + + private class AllRightAction extends AnAction { + + AllRightAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.AllRight); + } + + @Override + public void actionPerformed(AnActionEvent e) { + doAllRight(); + } + } + + private class UpAction extends AnAction { + + UpAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.Up); + } + + @Override + public void actionPerformed(AnActionEvent e) { + ListUtil.moveSelectedItemsUp(myRightList); + } + } + + private class DownAction extends AnAction { + + DownAction() { + getTemplatePresentation().setIcon(AllIcons.Actions.Down); + } + + @Override + public void actionPerformed(AnActionEvent e) { + ListUtil.moveSelectedItemsDown(myRightList); + } + } +} diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 066dfb5b4814..7b1c93d43389 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -492,6 +492,9 @@ title.colors.and.fonts=Colors \\& Fonts progress.analysing.font=Analysing font: {0} button.edit.scopes=Edit Scopes... group.editor.font=Editor Font +title.font.available=Available fonts: +title.font.selected=Selected fonts: +label.fallback.fonts.list.description=The ide tries to use the next font from 'Selected fonts' list for displaying a symbol if the current font fails to do that quickdoc.tooltip.font.size.by.wheel=Slider or Ctrl+Wheel change font size label.font.size=Font size: label.font.name=Name: diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index 588153f25405..d13fa7dd4072 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -27,6 +27,8 @@ public class AllIcons { public static class Actions { public static final Icon AddFacesSupport = IconLoader.getIcon("/actions/addFacesSupport.png"); // 16x16 + public static final Icon AllLeft = IconLoader.getIcon("/actions/allLeft.png"); // 16x16 + public static final Icon AllRight = IconLoader.getIcon("/actions/allRight.png"); // 16x16 public static final Icon Annotate = IconLoader.getIcon("/actions/annotate.png"); // 16x16 public static final Icon Back = IconLoader.getIcon("/actions/back.png"); // 16x16 public static final Icon Browser_externalJavaDoc = IconLoader.getIcon("/actions/browser-externalJavaDoc.png"); // 16x16 @@ -53,6 +55,7 @@ public class AllIcons { public static final Icon Delete = IconLoader.getIcon("/actions/delete.png"); // 16x16 public static final Icon Diff = IconLoader.getIcon("/actions/diff.png"); // 16x16 public static final Icon DiffWithCurrent = IconLoader.getIcon("/actions/diffWithCurrent.png"); // 16x16 + public static final Icon Down = IconLoader.getIcon("/actions/down.png"); // 16x16 public static final Icon Download = IconLoader.getIcon("/actions/download.png"); // 16x16 public static final Icon Dump = IconLoader.getIcon("/actions/dump.png"); // 16x16 public static final Icon Edit = IconLoader.getIcon("/actions/edit.png"); // 14x14 @@ -78,6 +81,7 @@ public class AllIcons { public static final Icon Help = IconLoader.getIcon("/actions/help.png"); // 16x16 public static final Icon Install = IconLoader.getIcon("/actions/install.png"); // 16x16 public static final Icon IntentionBulb = IconLoader.getIcon("/actions/intentionBulb.png"); // 16x16 + public static final Icon Left = IconLoader.getIcon("/actions/left.png"); // 16x16 public static final Icon Lightning = IconLoader.getIcon("/actions/lightning.png"); // 16x16 public static final Icon Menu_cut = IconLoader.getIcon("/actions/menu-cut.png"); // 16x16 public static final Icon Menu_find = IconLoader.getIcon("/actions/menu-find.png"); // 16x16 @@ -120,6 +124,7 @@ public class AllIcons { public static final Icon Reset = IconLoader.getIcon("/actions/reset.png"); // 16x16 public static final Icon Restart = IconLoader.getIcon("/actions/restart.png"); // 16x16 public static final Icon Resume = IconLoader.getIcon("/actions/resume.png"); // 16x16 + public static final Icon Right = IconLoader.getIcon("/actions/right.png"); // 16x16 public static final Icon Rollback = IconLoader.getIcon("/actions/rollback.png"); // 16x16 public static final Icon RunToCursor = IconLoader.getIcon("/actions/runToCursor.png"); // 16x16 public static final Icon Search = IconLoader.getIcon("/actions/search.png"); // 16x16 @@ -150,7 +155,8 @@ public class AllIcons { public static final Icon Uninstall = IconLoader.getIcon("/actions/uninstall.png"); // 16x16 public static final Icon Unselectall = IconLoader.getIcon("/actions/unselectall.png"); // 16x16 public static final Icon Unshare = IconLoader.getIcon("/actions/unshare.png"); // 14x14 - + public static final Icon Up = IconLoader.getIcon("/actions/up.png"); // 16x16 + } public static class Ant {