4 * License : The MIT License
\r
5 * Copyright(c) 2009 olyutorskii
\r
8 package jp.sourceforge.jindolf;
\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
23 * Swingコンポーネントのフォント等幅化。
\r
26 public final class Monodizer implements PropertyChangeListener{
\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
35 private static final Map<TextAttribute, String> TEXTATTR_MONO =
\r
36 Collections.singletonMap(TextAttribute.FAMILY, FAMILY_MONO);
\r
38 private static final Monodizer CHANGER = new Monodizer();
\r
44 private Monodizer(){
\r
53 * @return 等幅フォントならtrue
\r
55 public static boolean isMonospaced(Font font){
\r
56 Map<TextAttribute, ?> attrMap = font.getAttributes();
\r
58 Object attr = attrMap.get(TextAttribute.FAMILY);
\r
59 if( ! (attr instanceof String) ) return false;
\r
61 String family = (String) attr;
\r
62 if(family.equals(FAMILY_MONO)) return true;
\r
69 * 等幅以外の属性は可能な限り保持する。
\r
70 * @param font 任意のフォント
\r
73 public static Font deriveMonoFont(Font font){
\r
74 Font monofont = font.deriveFont(TEXTATTR_MONO);
\r
79 * 任意のコンポーネントをフォント等幅化する。
\r
80 * L&F変更に対処するためのリスナ組み込みも行われる。
\r
81 * @param comp コンポーネント
\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
88 modifyComponent(comp);
\r
90 comp.addPropertyChangeListener(PROPNAME_FONT, CHANGER);
\r
91 comp.addPropertyChangeListener(PROPNAME_UI, CHANGER);
\r
100 * @param comp コンポーネント
\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
115 * テキストコンポーネントへの微修正を行う。
\r
116 * @param textComp テキストコンポーネント
\r
118 private static void modifyTextComponent(JTextComponent textComp){
\r
119 if( ! textComp.isEditable() ){
\r
120 textComp.setCaretPosition(0);
\r
126 * コンボボックスのエディタを等幅化する。
\r
127 * @param comboBox コンボボックス
\r
129 private static void modifyComboBox(JComboBox comboBox){
\r
130 ComboBoxEditor editor = comboBox.getEditor();
\r
131 if(editor == null) return;
\r
133 Component editComp = editor.getEditorComponent();
\r
134 if( ! (editComp instanceof JTextComponent) ) return;
\r
135 JTextComponent textEditor = (JTextComponent) editComp;
\r
137 Font oldFont = textEditor.getFont();
\r
138 Font newFont = deriveMonoFont(oldFont);
\r
139 textEditor.setFont(newFont);
\r
141 modifyTextComponent(textEditor);
\r
148 * @param event フォント変更イベント
\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
155 String propName = event.getPropertyName();
\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
168 Font monoFont = deriveMonoFont(newFont);
\r
169 comp.setFont(monoFont); // 再帰は起きないはず…
\r
171 modifyComponent(comp);
\r