OSDN Git Service

クラスメンバ定義順統一
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / Monodizer.java
1 /*\r
2  * font monodizer\r
3  *\r
4  * License : The MIT License\r
5  * Copyright(c) 2009 olyutorskii\r
6  */\r
7 \r
8 package jp.sourceforge.jindolf;\r
9 \r
10 import java.awt.Component;\r
11 import java.awt.Font;\r
12 import java.awt.font.TextAttribute;\r
13 import java.beans.PropertyChangeEvent;\r
14 import java.beans.PropertyChangeListener;\r
15 import java.util.Collections;\r
16 import java.util.Map;\r
17 import javax.swing.ComboBoxEditor;\r
18 import javax.swing.JComboBox;\r
19 import javax.swing.JComponent;\r
20 import javax.swing.text.JTextComponent;\r
21 \r
22 /**\r
23  * Swingコンポーネントのフォント等幅化。\r
24  * L&F変更にも対処。\r
25  */\r
26 public final class Monodizer implements PropertyChangeListener{\r
27 \r
28     /** フォント変更時のプロパティ名。 */\r
29     public static final String PROPNAME_FONT = "font";\r
30     /** L&F変更時のプロパティ名。 */\r
31     public static final String PROPNAME_UI = "UI";\r
32     /** Font.MONOSPACED代替品。 */\r
33     public static final String FAMILY_MONO = "Monospaced";\r
34 \r
35     private static final Map<TextAttribute, String> TEXTATTR_MONO =\r
36             Collections.singletonMap(TextAttribute.FAMILY, FAMILY_MONO);\r
37 \r
38     private static final Monodizer CHANGER = new Monodizer();\r
39 \r
40 \r
41     /**\r
42      * 隠しコンストラクタ。\r
43      */\r
44     private Monodizer(){\r
45         super();\r
46         return;\r
47     }\r
48 \r
49 \r
50     /**\r
51      * 等幅フォントか否か判定する。\r
52      * @param font フォント\r
53      * @return 等幅フォントならtrue\r
54      */\r
55     public static boolean isMonospaced(Font font){\r
56         Map<TextAttribute, ?> attrMap = font.getAttributes();\r
57 \r
58         Object attr = attrMap.get(TextAttribute.FAMILY);\r
59         if( ! (attr instanceof String) ) return false;\r
60 \r
61         String family = (String) attr;\r
62         if(family.equals(FAMILY_MONO)) return true;\r
63 \r
64         return false;\r
65     }\r
66 \r
67     /**\r
68      * 任意のフォントの等幅化を行う。\r
69      * 等幅以外の属性は可能な限り保持する。\r
70      * @param font 任意のフォント\r
71      * @return 等幅フォント\r
72      */\r
73     public static Font deriveMonoFont(Font font){\r
74         Font monofont = font.deriveFont(TEXTATTR_MONO);\r
75         return monofont;\r
76     }\r
77 \r
78     /**\r
79      * 任意のコンポーネントをフォント等幅化する。\r
80      * L&F変更に対処するためのリスナ組み込みも行われる。\r
81      * @param comp コンポーネント\r
82      */\r
83     public static void monodize(JComponent comp){\r
84         Font oldFont = comp.getFont();\r
85         Font newFont = deriveMonoFont(oldFont);\r
86         comp.setFont(newFont);\r
87 \r
88         modifyComponent(comp);\r
89 \r
90         comp.addPropertyChangeListener(PROPNAME_FONT, CHANGER);\r
91         comp.addPropertyChangeListener(PROPNAME_UI,   CHANGER);\r
92 \r
93         comp.revalidate();\r
94 \r
95         return;\r
96     }\r
97 \r
98     /**\r
99      * コンポーネントに微修正を加える。\r
100      * @param comp コンポーネント\r
101      */\r
102     private static void modifyComponent(JComponent comp){\r
103         if(comp instanceof JTextComponent){\r
104             JTextComponent textComp = (JTextComponent) comp;\r
105             modifyTextComponent(textComp);\r
106         }else if(comp instanceof JComboBox){\r
107             JComboBox combo = (JComboBox) comp;\r
108             modifyComboBox(combo);\r
109         }\r
110 \r
111         return;\r
112     }\r
113 \r
114     /**\r
115      * テキストコンポーネントへの微修正を行う。\r
116      * @param textComp テキストコンポーネント\r
117      */\r
118     private static void modifyTextComponent(JTextComponent textComp){\r
119         if( ! textComp.isEditable() ){\r
120             textComp.setCaretPosition(0);\r
121         }\r
122         return;\r
123     }\r
124 \r
125     /**\r
126      * コンボボックスのエディタを等幅化する。\r
127      * @param comboBox コンボボックス\r
128      */\r
129     private static void modifyComboBox(JComboBox comboBox){\r
130         ComboBoxEditor editor = comboBox.getEditor();\r
131         if(editor == null) return;\r
132 \r
133         Component editComp = editor.getEditorComponent();\r
134         if( ! (editComp instanceof JTextComponent) ) return;\r
135         JTextComponent textEditor = (JTextComponent) editComp;\r
136 \r
137         Font oldFont = textEditor.getFont();\r
138         Font newFont = deriveMonoFont(oldFont);\r
139         textEditor.setFont(newFont);\r
140 \r
141         modifyTextComponent(textEditor);\r
142 \r
143         return;\r
144     }\r
145 \r
146     /**\r
147      * フォント変更イベントの受信。\r
148      * @param event フォント変更イベント\r
149      */\r
150     public void propertyChange(PropertyChangeEvent event){\r
151         Object source = event.getSource();\r
152         if( ! (source instanceof JComponent) ) return;\r
153         JComponent comp = (JComponent) source;\r
154 \r
155         String propName = event.getPropertyName();\r
156 \r
157         Font newFont;\r
158         if(PROPNAME_FONT.equals(propName)){\r
159             Object newValue = event.getNewValue();\r
160             if( ! (newValue instanceof Font) ) return;\r
161             newFont = (Font) newValue;\r
162         }else if(PROPNAME_UI.equals(propName)){\r
163             newFont = comp.getFont();\r
164         }else{\r
165             return;\r
166         }\r
167 \r
168         Font monoFont = deriveMonoFont(newFont);\r
169         comp.setFont(monoFont);    // 再帰は起きないはず…\r
170 \r
171         modifyComponent(comp);\r
172 \r
173         return;\r
174     }\r
175 \r
176 }\r