OSDN Git Service

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