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 }