1 /* 2 * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. 3 * All rights reserved. 4 * Project URL:https://github.com/JackJiang2011/beautyeye 5 * Version 3.6 6 * 7 * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 8 * 9 * BeautyEyeLNFHelper.java at 2015-2-1 20:25:40, original version by Jack Jiang. 10 * You can contact author with jb2011@163.com. 11 */ 12 package org.jb2011.lnf.beautyeye; 13 14 import java.awt.Color; 15 16 import javax.swing.BorderFactory; 17 import javax.swing.LookAndFeel; 18 import javax.swing.UIManager; 19 import javax.swing.border.Border; 20 21 import org.jb2011.lnf.beautyeye.utils.JVM; 22 import org.jb2011.lnf.beautyeye.widget.border.BEShadowBorder; 23 import org.jb2011.lnf.beautyeye.widget.border.BEShadowBorder3; 24 import org.jb2011.lnf.beautyeye.widget.border.PlainGrayBorder; 25 26 /** 27 * <p> 28 * BeautyEye Swing外观实现方案 - L&F核心辅助类.<br> 29 * <p> 30 * 项目托管地址:https://github.com/JackJiang2011/beautyeye 31 * 32 * @author Jack Jiang(jb2011@163.com), 2012-05 33 * @version 1.0 34 */ 35 public class BeautyEyeLNFHelper 36 { 37 /** 38 * 开关量:用于开启/关闭BeautyEye LNF的调试信息输出. 39 * <p> 40 * 默认false,即不开启调试信息输出. 41 * 42 * @since 3.2 43 */ 44 public static boolean debug = false; 45 /** 46 * 开关量:用于开启/关闭当窗口(包括JFrame、JDialog)处于非活动 47 * 状态(inactivity)时的半透明视觉效果. 48 * <p> 49 * 默认true,即表示默认开启半透明效果. 50 * 51 * @since 3.2 52 */ 53 public static boolean translucencyAtFrameInactive = true; 54 55 /** 56 * BeautyEye LNF 的窗口边框样式. 57 * <p>默认值:运行在java1.6.0_u10及以上版本时使用 {@link FrameBorderStyle#translucencyAppleLike}, 58 * 运行在java1.5版本时使用{@link FrameBorderStyle#generalNoTranslucencyShadow}. 59 * 60 * <p><b>注意:</b>如需设置本参数,请确保它在UIManager.setLookAndFeel前被设置,否则将不会起效哦. 61 * @see FrameBorderStyle 62 */ 63 public static FrameBorderStyle frameBorderStyle = 64 isSurportedTranslucency()?FrameBorderStyle.translucencyAppleLike:FrameBorderStyle.generalNoTranslucencyShadow; 65 66 /** 67 * 颜色全局变量:正常情况下的窗口文本颜色. 68 * <p> 69 * 你可设置本变量,也可直接通过{@code UIManager.put("activeCaptionText",new ColorUIResource(c))}和 70 * {@code UIManager.put("inactiveCaptionText",new ColorUIResource(c))}来实现窗口文本颜色的改变. 71 * <p> 72 * 窗体不活动(inactivite)时的颜色将据此自动计算出来,无需额外设置. 73 * 默认是黑色(new Color(0,0,0)). */ 74 public static Color activeCaptionTextColor = new Color(0,0,0);//黑色 75 76 /** 77 * 颜色全局变量:多数组件的背景色. 78 * <p> 79 * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. 80 * <p> 81 * 默认是浅灰色(new Color(250,250,250)). 82 * @since 3.2 */ 83 public static Color commonBackgroundColor = new Color(250,250,250);//240,240,240); //248,248,248);//255,255,255);// 84 /** 85 * 颜色全局变量:多数组件的前景色(文本颜色). 86 * <p> 87 * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. 88 * <p> 89 * 默认是深灰色(new Color(60,60,60)). 90 * @since 3.2 */ 91 public static Color commonForegroundColor = new Color(60,60,60);//102,102,102); 92 /** 93 * 颜色全局变量:某些组件的焦点边框颜色. 94 * 当前主要用于按钮等焦点边框的绘制颜色. 95 * <p> 96 * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. 97 * <p> 98 * 默认是浅灰色(new Color(250,250,250)). 99 * @since 3.2 */ 100 public static Color commonFocusedBorderColor = new Color(162,162,162); 101 /** 102 * 颜色全局变量:某些组件被禁用时的文本颜色. 103 * 当前主要用于菜单项中. 104 * <p> 105 * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. 106 * <p> 107 * 默认是浅灰色(new Color(172,168,153)). 108 * @since 3.2 */ 109 public static Color commonDisabledForegroundColor = new Color(172,168,153); 110 /** 111 * 颜色全局变量:多数组件中文本被选中时的背景色.当前主要用于各文本组件等. 112 * <p> 113 * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. 114 * <p> 115 * 默认是深灰色(new Color(2,129,216)). 116 * @since 3.2 */ 117 public static Color commonSelectionBackgroundColor = new Color(2,129,216);//78,155,193));//58,135,173));//235,217,147));//new Color(255,237,167)); 118 /** 119 * 颜色全局变量:多数组件中文本被选中时的前景色(文本颜色).当前主要用于各文本组件、菜单项等. 120 * <p> 121 * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. 122 * <p> 123 * 默认是深灰色(new Color(255,255,255)). 124 * @since 3.2 */ 125 public static Color commonSelectionForegroundColor = new Color(255,255,255); 126 127 /** 128 * 开关量:用于默认设置或不设置窗口(Frame及其子类)的设置此窗体的最大化边界. 129 * <p> 130 * 此开关量是它是为了解决这样一个问题 :<br> 131 * 当不使用操作系统的窗口装饰(即使用完全自定义的窗口标题、边框)时,在windows上最 132 * 大化窗口时将会全屏显示从而覆盖了下方的任务栏(task bar),这个问题 据说自2002年 133 * 就已存在,SUN一直未解决或者根本不认为是bug。目前的解决方案是当本变量是true时则 134 * 默认为每一个窗体设置最大化边界,否则保持系统默认。不过这样设置并非完美方案:一旦 135 * 设置了最大边界,则此后无论Task Bar再怎么调 整大小,比如被hide了,则窗体永远是设 136 * 置时的最大边界,不过目前也只能这么折中解决了,因为窗体最大化事件处理并非L&F中实现 137 * ,暂未找到其它更好的方法。 138 * <p> 139 * 默认true,即表示默认开启此设置. 140 * 141 * @since 3.2 142 * @see javax.swing.JFrame#setMaximizedBounds(java.awt.Rectangle) 143 */ 144 public static boolean setMaximizedBoundForFrame = true; 145 146 /** 147 * BeautyEye LNF的外观实现核心方法. 148 * <p> 149 * 本方法可以直接从外部调用,这意味着BeautyEye LNF的外观核心实现无需特定于LookAndFeel的实例. 150 * <p>也就是说任意外观都可应用本方法所作的外观实现(并保证跨平台),以使之可灵活应用. 151 * 152 * @see org.jb2011.lnf.beautyeye.ch1_titlepane.__UI__#uiImpl() 153 * @see org.jb2011.lnf.beautyeye.ch2_tab.__UI__#uiImpl() 154 * @see org.jb2011.lnf.beautyeye.ch3_button.__UI__#uiImpl() 155 * @see org.jb2011.lnf.beautyeye.ch_x.__UI__#uiImpl() 156 * @see org.jb2011.lnf.beautyeye.ch4_scroll.__UI__#uiImpl() 157 * @see org.jb2011.lnf.beautyeye.ch5_table.__UI__#uiImpl() 158 * @see org.jb2011.lnf.beautyeye.ch6_textcoms.__UI__#uiImpl() 159 * @see org.jb2011.lnf.beautyeye.ch7_popup.__UI__#uiImpl() 160 * @see org.jb2011.lnf.beautyeye.ch8_toolbar.__UI__#uiImpl() 161 * @see org.jb2011.lnf.beautyeye.ch9_menu.__UI__#uiImpl() 162 * @see org.jb2011.lnf.beautyeye.ch10_internalframe.__UI__#uiImpl() 163 * @see org.jb2011.lnf.beautyeye.ch12_progress.__UI__#uiImpl() 164 * @see org.jb2011.lnf.beautyeye.ch13_radio$cb_btn.__UI__#uiImpl() 165 * @see org.jb2011.lnf.beautyeye.ch14_combox.__UI__#uiImpl() 166 * @see org.jb2011.lnf.beautyeye.ch15_slider.__UI__#uiImpl() 167 * @see org.jb2011.lnf.beautyeye.ch16_tree.__UI__#uiImpl() 168 * @see org.jb2011.lnf.beautyeye.ch17_split.__UI__#uiImpl() 169 * @see org.jb2011.lnf.beautyeye.ch18_spinner.__UI__#uiImpl() 170 * @see org.jb2011.lnf.beautyeye.ch19_list.__UI__#uiImpl() 171 * @see org.jb2011.lnf.beautyeye.ch20_filechooser.__UI__#uiImpl_win() 172 */ 173 protected static void implLNF() 174 { 175 //自定义窗口的L&F实现 176 org.jb2011.lnf.beautyeye.ch1_titlepane.__UI__.uiImpl(); 177 //自定义JTabbedPane的L&F实现 178 org.jb2011.lnf.beautyeye.ch2_tab.__UI__.uiImpl(); 179 //自定义按钮的L&F实现 180 org.jb2011.lnf.beautyeye.ch3_button.__UI__.uiImpl(); 181 //各种杂七杂八的设置 182 org.jb2011.lnf.beautyeye.ch_x.__UI__.uiImpl(); 183 //自定义滚动条的L&F实现 184 org.jb2011.lnf.beautyeye.ch4_scroll.__UI__.uiImpl(); 185 //自定义表格头的L&F实现 186 org.jb2011.lnf.beautyeye.ch5_table.__UI__.uiImpl(); 187 //自定义文本组件的L&F实现 188 org.jb2011.lnf.beautyeye.ch6_textcoms.__UI__.uiImpl(); 189 //自定义弹出组件(包括toolTip组件和弹出菜单等)的L&F实现 190 org.jb2011.lnf.beautyeye.ch7_popup.__UI__.uiImpl(); 191 //自定义ToggleButton的L&F实现 192 org.jb2011.lnf.beautyeye.ch8_toolbar.__UI__.uiImpl(); 193 //自定义菜单项的L&F实现 194 org.jb2011.lnf.beautyeye.ch9_menu.__UI__.uiImpl(); 195 //自定义DesktopPane及内部窗体的L&F实现 196 org.jb2011.lnf.beautyeye.ch10_internalframe.__UI__.uiImpl(); 197 //自定义进度条的L&F实现 198 org.jb2011.lnf.beautyeye.ch12_progress.__UI__.uiImpl(); 199 //自定义单选按钮的L&F实现 200 org.jb2011.lnf.beautyeye.ch13_radio$cb_btn.__UI__.uiImpl(); 201 //自定义下拉框的L&F实现 202 org.jb2011.lnf.beautyeye.ch14_combox.__UI__.uiImpl(); 203 //自定义JSlider的L&F实现 204 org.jb2011.lnf.beautyeye.ch15_slider.__UI__.uiImpl(); 205 //自定义Jtree的L&F实现 206 org.jb2011.lnf.beautyeye.ch16_tree.__UI__.uiImpl(); 207 //自定义JSplitPane的L&F实现 208 org.jb2011.lnf.beautyeye.ch17_split.__UI__.uiImpl(); 209 //自定义JSpinner的L&F实现 210 org.jb2011.lnf.beautyeye.ch18_spinner.__UI__.uiImpl(); 211 //自定义JList的L&F实现 212 org.jb2011.lnf.beautyeye.ch19_list.__UI__.uiImpl(); 213 //自定义JFileChooser的L&F实现 214 org.jb2011.lnf.beautyeye.ch20_filechooser.__UI__.uiImpl(); 215 } 216 217 /** 218 * Gets the beauty eye lnf str cross platform. 219 * 220 * @return "org.jb2011.lnf.beautyeye.BeautyEyeLookAndFeelCross" 221 */ 222 public static String getBeautyEyeLNFStrCrossPlatform() 223 { 224 return "org.jb2011.lnf.beautyeye.BeautyEyeLookAndFeelCross"; 225 } 226 227 /** 228 * Gets the beauty eye lnf str windows platform. 229 * 230 * @return "org.jb2011.lnf.beautyeye.BeautyEyeLookAndFeelWin" 231 */ 232 public static String getBeautyEyeLNFStrWindowsPlatform() 233 { 234 return "org.jb2011.lnf.beautyeye.BeautyEyeLookAndFeelWin"; 235 } 236 237 /** 238 * Gets the beauty eye lnf cross platform. 239 * 240 * @return {@code new BeautyEyeLookAndFeelCross()} 241 */ 242 public static LookAndFeel getBeautyEyeLNFCrossPlatform() 243 { 244 return new BeautyEyeLookAndFeelCross(); 245 } 246 247 /** 248 * Gets the beauty eye lnf windows platform. 249 * 250 * @return {@code new BeautyEyeLookAndFeelWin()} 251 */ 252 public static LookAndFeel getBeautyEyeLNFWindowsPlatform() 253 { 254 return new BeautyEyeLookAndFeelWin(); 255 } 256 257 /** 258 * 实施BeautyEye外观.<b>开发者使用BeautyEye L&F时应首选本方法.</b> 259 * <p> 260 * 本方法会据操作系统类型不同,来决定主类是使用BeautyEyeLookAndFeelWin还是BeautyEyeLookAndFeelWin. 261 * 使用BeautyEye外观时推荐使用本方法来设置外观.之所以有平台不同主类不同的区分,是为了 262 * 在Windows上平台上能更好的使用与操作系统相同的字体等设置. 263 * 264 * @throws Exception {@link UIManager#setLookAndFeel(String)}过程中出现的任何异常 265 * @see #getBeautyEyeLNFStrWindowsPlatform() 266 * @see #getBeautyEyeLNFStrCrossPlatform() 267 * @see org.jb2011.lnf.beautyeye.utils.Platform 268 */ 269 public static void launchBeautyEyeLNF() throws Exception 270 { 271 if(org.jb2011.lnf.beautyeye.utils.Platform.isWindows()) 272 { 273 if(BeautyEyeLNFHelper.debug) 274 System.out.println("已智能启用Windows平台专用的BeautyEye外观实现(您也可自行启用跨平台实现)."); 275 UIManager.setLookAndFeel(getBeautyEyeLNFStrWindowsPlatform()); 276 } 277 else 278 { 279 if(BeautyEyeLNFHelper.debug) 280 System.out.println("已智能启用跨平台的通用BeautyEye外观实现."); 281 UIManager.setLookAndFeel(getBeautyEyeLNFStrCrossPlatform()); 282 } 283 } 284 285 /** 286 * 当前运行的Java版本是否支持窗口透明、每像素半透明. 287 * <p> 288 * 必须java1.6.0_u12及以后版本才支持(为什么要到u12才支持? 289 * 因u10、u11里的窗口透明存在BUG 6750920). 290 * 291 * @return true表示支持,否则不支持 292 */ 293 public static boolean isSurportedTranslucency() 294 { 295 //是否支持窗口透明:必须java1.6.0_u12及以后版本才支持 296 return JVM.current().isOneDotSixUpdate12OrAfter();//JDK1_6_U10);//为什么要到u12才支持?因u10里的窗口透明存在BUG 6750920 297 } 298 299 /** 300 * <b>开发者无需关注本方法.</b> 301 * <p> 302 * true表示当前正在使用的窗口边框是不透明的,否则表示透明. 303 * 本方法目前作为BERootPaneUI中设置窗口是否透明的开关使用. 304 * <p> 305 * #### 官方API中存的Bug: ####<br> 306 * 在jdk1.6.0_u33下+win7平台下(其它版本是否也有这情况尚未完全验证),JFrame窗口 307 * 被设置成透明后,该窗口内所有文本都会被反走样(不管你有没有要求反走样),真悲具。 308 * 这应该是官方AWTUtilities.setWindowOpaque(..)bug导致的,1.7.0_u6同样存在该问题, 309 * 使用BeautyEye时,遇到这样的问题只能自行使用本方法中指定的不透明边框才行(这样 310 * BERootPaneUI类的设置窗口透明的代码就不用执行,也就不用触发该bug了),但JDialog 311 * 不受此bug影响,诡异! 312 * 313 * @return true, if successful 314 * @since 3.2 315 */ 316 public static boolean __isFrameBorderOpaque() 317 { 318 return frameBorderStyle == FrameBorderStyle.osLookAndFeelDecorated 319 || frameBorderStyle == FrameBorderStyle.generalNoTranslucencyShadow; 320 } 321 /** 322 * <b>开发者无需关注本方法.</b> 323 * <p> 324 * 根据设置的frameBorderStyle来返回正确的窗口边框. 325 * 326 * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated} 327 * 时返回无意义的BorderFactory.createEmptyBorder(),否则返回指定边框对象 328 */ 329 public static Border __getFrameBorder() 330 { 331 switch(frameBorderStyle) 332 { 333 case osLookAndFeelDecorated: 334 return BorderFactory.createEmptyBorder(); 335 case translucencyAppleLike: 336 return new BEShadowBorder3(); 337 case translucencySmallShadow: 338 return new BEShadowBorder(); 339 case generalNoTranslucencyShadow: 340 default: 341 return new PlainGrayBorder(); 342 } 343 } 344 // /** 345 // * <b>开发者无需关注本方法.</b> 346 // * <p> 347 // * 根据设置的frameBorderStyle来返回正确的窗口边框边角的拖动区大小. 348 // * <p> 349 // * <b>重要说明:</b>本方法中的边框类型及其对应的边框类必须与方法 {@link #__getFrameBorder()} 350 // * 完全一致! 351 // * 352 // * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated} 353 // * 时返回null,否则返回指定边框对象 354 // */ 355 // public static int __getFrameBorder_CORNER_DRAG_WIDTH() 356 // { 357 // switch(frameBorderStyle) 358 // { 359 // case osLookAndFeelDecorated: 360 // return 16; 361 // case translucencyAppleLike: 362 // return BEShadowBorder3.CORNER_DRAG_WIDTH(); 363 // case translucencySmallShadow: 364 // return new BEShadowBorder().CORNER_DRAG_WIDTH(); 365 // case generalNoTranslucencyShadow: 366 // default: 367 // return new PlainGrayBorder().CORNER_DRAG_WIDTH(); 368 // } 369 // } 370 // /** 371 // * <b>开发者无需关注本方法.</b> 372 // * <p> 373 // * 根据设置的frameBorderStyle来返回正确的窗口边框拖动区大小. 374 // * <p> 375 // * <b>重要说明:</b>本方法中的边框类型及其对应的边框类必须与方法 {@link #__getFrameBorder()} 376 // * 完全一致! 377 // * 378 // * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated} 379 // * 时返回null,否则返回指定边框对象 380 // */ 381 // public static int __getFrameBorder_BORDER_DRAG_THICKNESS() 382 // { 383 // switch(frameBorderStyle) 384 // { 385 // case osLookAndFeelDecorated: 386 // return 5; 387 // case translucencyAppleLike: 388 // return BEShadowBorder3.BORDER_DRAG_THICKNESS(); 389 // case translucencySmallShadow: 390 // return new BEShadowBorder().BORDER_DRAG_THICKNESS(); 391 // case generalNoTranslucencyShadow: 392 // default: 393 // return new PlainGrayBorder().BORDER_DRAG_THICKNESS(); 394 // } 395 // } 396 397 /** 398 * BeautyEye LNF 的窗口边框样式. 399 */ 400 public enum FrameBorderStyle 401 { 402 403 /** 使用本地系统的窗口装饰样式(本样式将能带来最佳性能,使用操作系统默认窗口样式). */ 404 osLookAndFeelDecorated, 405 406 /** 使用类似于MacOSX的强烈立体感半透明阴影边框(本样式性能尚可,视觉效果最佳). */ 407 translucencyAppleLike, 408 409 /** 使用不太强烈立体感半透明阴影边框(本样式性能尚可,视觉效果较soft). */ 410 translucencySmallShadow, 411 /** 使用不透明的普通边框(这是本LNF在Java1.5版默认使用的样式,因为java1.5不支持窗口透明) */ 412 generalNoTranslucencyShadow 413 } 414 415 /** 416 * <b>开发者暂时无需关注此接口.</b> 417 * <p> 418 * 实现了此接口的UI类意味着用户可以通过自行设置诸如border等,来 419 * 取消默认的NainePatch图实现的边框填充、背景填充等,具体设置哪 420 * 些东西可以取消默认的NinePatch图填充的方式详见各自的类注释。 421 */ 422 public interface __UseParentPaintSurported 423 { 424 425 /** 426 * 是否使用父类的绘制实现方法,true表示是. 427 * <p> 428 * 因为在BE LNF中,进度条和背景都是使用N9图,比如没法通过设置JProgressBar的背景色和前景 429 * 色来控制进度条的颜色,本方法的目的就是当用户设置了进度条的Background或Foreground 430 * 时告之本实现类不使用BE LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 431 * 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 432 * 通过JProgressBar.setUI(new MetalProgressBar())方式来自定义进度的UI哦). 433 * 434 * @return true, if is use parent paint 435 */ 436 boolean isUseParentPaint(); 437 } 438 }