OSDN Git Service

cc9c2256717321953216aaf760ed8a9fe2d07f83
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / Monodizer.java
1 /*\r
2  * font monodizer\r
3  *\r
4  * Copyright(c) 2009 olyutorskii\r
5  * $Id: Monodizer.java 963 2009-12-20 12:55:11Z 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      * @param font フォント\r
44      * @return 等幅フォントならtrue\r
45      */\r
46     public static boolean isMonospaced(Font font){\r
47         Map<TextAttribute, ?> attrMap = font.getAttributes();\r
48 \r
49         Object attr = attrMap.get(TextAttribute.FAMILY);\r
50         if( ! (attr instanceof String) ) return false;\r
51 \r
52         String family = (String) attr;\r
53         if(family.equals(FAMILY_MONO)) return true;\r
54 \r
55         return false;\r
56     }\r
57 \r
58     /**\r
59      * 任意のフォントの等幅化を行う。\r
60      * 等幅以外の属性は可能な限り保持する。\r
61      * @param font 任意のフォント\r
62      * @return 等幅フォント\r
63      */\r
64     public static Font deriveMonoFont(Font font){\r
65         Font monofont = font.deriveFont(TEXTATTR_MONO);\r
66         return monofont;\r
67     }\r
68 \r
69     /**\r
70      * 任意のコンポーネントをフォント等幅化する。\r
71      * L&F変更に対処するためのリスナ組み込みも行われる。\r
72      * @param comp コンポーネント\r
73      */\r
74     public static void monodize(JComponent comp){\r
75         Font oldFont = comp.getFont();\r
76         Font newFont = deriveMonoFont(oldFont);\r
77         comp.setFont(newFont);\r
78 \r
79         modifyComponent(comp);\r
80 \r
81         comp.addPropertyChangeListener(PROPNAME_FONT, CHANGER);\r
82         comp.addPropertyChangeListener(PROPNAME_UI,   CHANGER);\r
83 \r
84         comp.revalidate();\r
85 \r
86         return;\r
87     }\r
88 \r
89     /**\r
90      * コンポーネントに微修正を加える。\r
91      * @param comp コンポーネント\r
92      */\r
93     private static void modifyComponent(JComponent comp){\r
94         if(comp instanceof JTextComponent){\r
95             JTextComponent textComp = (JTextComponent) comp;\r
96             modifyTextComponent(textComp);\r
97         }else if(comp instanceof JComboBox){\r
98             JComboBox combo = (JComboBox) comp;\r
99             modifyComboBox(combo);\r
100         }\r
101 \r
102         return;\r
103     }\r
104 \r
105     /**\r
106      * テキストコンポーネントへの微修正を行う。\r
107      * @param textComp テキストコンポーネント\r
108      */\r
109     private static void modifyTextComponent(JTextComponent textComp){\r
110         if( ! textComp.isEditable() ){\r
111             textComp.setCaretPosition(0);\r
112         }\r
113         return;\r
114     }\r
115 \r
116     /**\r
117      * コンボボックスのエディタを等幅化する。\r
118      * @param comboBox コンボボックス\r
119      */\r
120     private static void modifyComboBox(JComboBox comboBox){\r
121         ComboBoxEditor editor = comboBox.getEditor();\r
122         if(editor == null) return;\r
123 \r
124         Component editComp = editor.getEditorComponent();\r
125         if( ! (editComp instanceof JTextComponent) ) return;\r
126         JTextComponent textEditor = (JTextComponent) editComp;\r
127 \r
128         Font oldFont = textEditor.getFont();\r
129         Font newFont = deriveMonoFont(oldFont);\r
130         textEditor.setFont(newFont);\r
131 \r
132         modifyTextComponent(textEditor);\r
133 \r
134         return;\r
135     }\r
136 \r
137     /**\r
138      * フォント変更イベントの受信。\r
139      * @param event フォント変更イベント\r
140      */\r
141     public void propertyChange(PropertyChangeEvent event){\r
142         Object source = event.getSource();\r
143         if( ! (source instanceof JComponent) ) return;\r
144         JComponent comp = (JComponent) source;\r
145 \r
146         String propName = event.getPropertyName();\r
147 \r
148         Font newFont;\r
149         if(PROPNAME_FONT.equals(propName)){\r
150             Object newValue = event.getNewValue();\r
151             if( ! (newValue instanceof Font) ) return;\r
152             newFont = (Font) newValue;\r
153         }else if(PROPNAME_UI.equals(propName)){\r
154             newFont = comp.getFont();\r
155         }else{\r
156             return;\r
157         }\r
158 \r
159         Font monoFont = deriveMonoFont(newFont);\r
160         comp.setFont(monoFont);    // 再帰は起きないはず…\r
161 \r
162         modifyComponent(comp);\r
163 \r
164         return;\r
165     }\r
166 \r
167     /**\r
168      * 隠しコンストラクタ。\r
169      */\r
170     private Monodizer(){\r
171         super();\r
172         return;\r
173     }\r
174 \r
175 }\r