查看本类的 API文档即时通讯网 - 即时通讯开发者社区!
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 }