4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sfjp.jindolf.glyph;
10 import java.awt.BorderLayout;
11 import java.awt.Container;
13 import java.awt.GridBagConstraints;
14 import java.awt.GridBagLayout;
15 import java.awt.Insets;
16 import java.awt.Rectangle;
17 import java.awt.event.ActionEvent;
18 import java.awt.event.ActionListener;
19 import java.awt.event.ItemEvent;
20 import java.awt.event.ItemListener;
21 import java.text.MessageFormat;
22 import javax.swing.BorderFactory;
23 import javax.swing.JButton;
24 import javax.swing.JCheckBox;
25 import javax.swing.JComboBox;
26 import javax.swing.JLabel;
27 import javax.swing.JPanel;
28 import javax.swing.JScrollPane;
29 import javax.swing.JTextField;
30 import javax.swing.border.Border;
31 import javax.swing.event.ListSelectionEvent;
32 import javax.swing.event.ListSelectionListener;
33 import jp.sfjp.jindolf.ResourceManager;
34 import jp.sfjp.jindolf.dxchg.TextPopup;
35 import jp.sfjp.jindolf.log.LogWrapper;
36 import jp.sfjp.jindolf.util.Monodizer;
41 @SuppressWarnings("serial")
42 public class FontChooser extends JPanel
43 implements ListSelectionListener,
47 private static final int[] POINT_SIZES = {
48 8, 10, 12, 16, 18, 24, 32, 36, 48, 72, // TODO これで十分?
50 private static final CharSequence PREVIEW_CONTENT;
51 private static final int UNIT_INC = 8;
53 private static final LogWrapper LOGGER = new LogWrapper();
57 ResourceManager.getTextFile("resources/font/preview.txt");
60 private FontInfo fontInfo;
61 private FontInfo lastFontInfo;
63 private final FontSelectList familySelector;
64 private final JComboBox sizeSelector;
65 private final JCheckBox isBoldCheck;
66 private final JCheckBox isItalicCheck;
67 private final JCheckBox useTextAntiAliaseCheck;
68 private final JCheckBox useFractionalCheck;
69 private final JLabel maxBounds;
70 private final JTextField decodeName;
71 private final FontPreviewer preview;
72 private final JButton resetDefault;
74 private boolean maskListener = false;
80 this(FontInfo.DEFAULT_FONTINFO);
86 * @param fontInfo 初期フォント設定
87 * @throws NullPointerException 引数がnull
89 public FontChooser(FontInfo fontInfo)
90 throws NullPointerException{
93 if(fontInfo == null) throw new NullPointerException();
94 this.fontInfo = fontInfo;
95 this.lastFontInfo = fontInfo;
97 logging(this.fontInfo);
99 this.familySelector = new FontSelectList();
101 this.sizeSelector = new JComboBox();
102 this.sizeSelector.setEditable(true);
103 for(int size : POINT_SIZES){
104 this.sizeSelector.addItem(size);
107 this.isBoldCheck = new JCheckBox("ボールド");
108 this.isItalicCheck = new JCheckBox("イタリック");
109 this.useTextAntiAliaseCheck = new JCheckBox("アンチエイリアス");
110 this.useFractionalCheck = new JCheckBox("サブピクセル精度");
112 this.maxBounds = new JLabel();
114 this.decodeName = new JTextField();
115 this.decodeName.setEditable(false);
116 this.decodeName.setMargin(new Insets(1, 4, 1, 4));
117 this.decodeName.setComponentPopupMenu(new TextPopup());
118 Monodizer.monodize(this.decodeName);
120 this.preview = new FontPreviewer(PREVIEW_CONTENT, this.fontInfo);
122 this.resetDefault = new JButton("出荷時に戻す");
127 this.familySelector.addListSelectionListener(this);
128 this.sizeSelector .addActionListener(this);
130 this.isBoldCheck .addItemListener(this);
131 this.isItalicCheck .addItemListener(this);
132 this.useTextAntiAliaseCheck.addItemListener(this);
133 this.useFractionalCheck .addItemListener(this);
135 this.resetDefault.addActionListener(this);
144 private static void logging(FontInfo info){
148 form = "発言表示フォントに{0}が選択されました。";
149 logMsg = MessageFormat.format(form, info.getFont());
152 form = "発言表示のアンチエイリアス指定に{0}が指定されました。";
153 logMsg = MessageFormat.format(form, info.isAntiAliased());
156 form = "発言表示のFractional指定に{0}が指定されました。";
157 logMsg = MessageFormat.format(form, info.usesFractionalMetrics());
165 * @param content コンテナ
167 private void design(Container content){
168 GridBagLayout layout = new GridBagLayout();
169 content.setLayout(layout);
171 GridBagConstraints constraints = new GridBagConstraints();
172 constraints.insets = new Insets(5, 5, 5, 5);
174 constraints.weightx = 1.0;
175 constraints.weighty = 0.0;
176 constraints.gridwidth = GridBagConstraints.REMAINDER;
177 constraints.fill = GridBagConstraints.BOTH;
178 content.add(createFontPrefPanel(), constraints);
180 constraints.weightx = 1.0;
181 constraints.weighty = 1.0;
182 constraints.gridwidth = GridBagConstraints.REMAINDER;
183 constraints.fill = GridBagConstraints.BOTH;
184 content.add(createPreviewPanel(), constraints);
186 constraints.weightx = 1.0;
187 constraints.weighty = 0.0;
188 constraints.gridwidth = GridBagConstraints.REMAINDER;
189 constraints.fill = GridBagConstraints.HORIZONTAL;
190 content.add(createFontDecodePanel(), constraints);
192 constraints.weightx = 1.0;
193 constraints.weighty = 0.0;
194 constraints.gridwidth = 1;
195 constraints.fill = GridBagConstraints.HORIZONTAL;
196 content.add(this.maxBounds, constraints);
198 constraints.weightx = 0.0;
199 constraints.weighty = 0.0;
200 constraints.gridwidth = GridBagConstraints.REMAINDER;
201 constraints.fill = GridBagConstraints.HORIZONTAL;
202 content.add(this.resetDefault, constraints);
211 private JPanel createFontPrefPanel(){
212 JPanel result = new JPanel();
214 GridBagLayout layout = new GridBagLayout();
215 GridBagConstraints constraints = new GridBagConstraints();
216 result.setLayout(layout);
218 JPanel familyBorderPanel = new JPanel();
219 Border familyBorder =
220 BorderFactory.createTitledBorder("フォントファミリ選択");
221 familyBorderPanel.setBorder(familyBorder);
223 JPanel sizeBorderPanel = new JPanel();
225 BorderFactory.createTitledBorder("ポイントサイズ指定");
226 sizeBorderPanel.setBorder(sizeBorder);
228 Border scrollBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1);
229 this.familySelector.setBorder(scrollBorder);
230 JScrollPane familyScroller = new JScrollPane(this.familySelector);
232 familyBorderPanel.setLayout(new BorderLayout());
233 familyBorderPanel.add(familyScroller);
234 constraints.insets = new Insets(0, 0, 0, 5);
235 constraints.weightx = 1.0;
236 constraints.weighty = 0.0;
237 constraints.gridheight = GridBagConstraints.REMAINDER;
238 constraints.fill = GridBagConstraints.BOTH;
239 result.add(familyBorderPanel, constraints);
241 sizeBorderPanel.setLayout(new BorderLayout());
242 sizeBorderPanel.add(this.sizeSelector);
243 constraints.insets = new Insets(0, 0, 0, 0);
244 constraints.weightx = 0.0;
245 constraints.gridheight = 1;
246 constraints.fill = GridBagConstraints.HORIZONTAL;
247 constraints.anchor = GridBagConstraints.WEST;
248 result.add(sizeBorderPanel, constraints);
250 constraints.anchor = GridBagConstraints.NORTHWEST;
251 result.add(this.isBoldCheck, constraints);
252 result.add(this.isItalicCheck, constraints);
253 result.add(this.useTextAntiAliaseCheck, constraints);
254 result.add(this.useFractionalCheck, constraints);
263 private JPanel createPreviewPanel(){
264 JPanel result = new JPanel();
266 BorderFactory.createTitledBorder("フォントプレビュー");
267 result.setBorder(border);
269 JScrollPane scroller = new JScrollPane(this.preview);
270 scroller.getVerticalScrollBar().setUnitIncrement(UNIT_INC);
272 result.setLayout(new BorderLayout());
273 result.add(scroller);
279 * フォントデコード名表示パネルを生成する。
280 * @return フォントデコード名表示パネル
282 private JPanel createFontDecodePanel(){
283 JPanel result = new JPanel();
285 GridBagLayout layout = new GridBagLayout();
286 result.setLayout(layout);
288 GridBagConstraints constraints = new GridBagConstraints();
290 JLabel label = new JLabel("Font.deode() 識別名:");
292 constraints.weightx = 0.0;
293 constraints.weighty = 0.0;
294 constraints.gridwidth = 1;
295 constraints.fill = GridBagConstraints.NONE;
296 result.add(label, constraints);
298 constraints.weightx = 1.0;
299 constraints.gridwidth = GridBagConstraints.REMAINDER;
300 constraints.fill = GridBagConstraints.HORIZONTAL;
301 result.add(this.decodeName, constraints);
310 public FontInfo getFontInfo(){
311 return this.fontInfo;
317 * @throws NullPointerException 引数がnull
319 public void setFontInfo(FontInfo newInfo) throws NullPointerException{
320 if(newInfo == null) throw new NullPointerException();
322 FontInfo old = this.fontInfo;
323 if(old.equals(newInfo)) return;
325 this.fontInfo = newInfo;
333 * フォント設定に合わせてGUIを更新する。
336 private void updateControlls(){
337 this.maskListener = true;
339 Font currentFont = getFontInfo().getFont();
342 String defaultFamily = currentFont.getFamily();
343 this.familySelector.setSelectedFamily(defaultFamily);
346 Integer selectedInteger = Integer.valueOf(currentFont.getSize());
347 this.sizeSelector.setSelectedItem(selectedInteger);
348 int sizeItems = this.sizeSelector.getItemCount();
349 for(int index = 0; index < sizeItems; index++){
350 Object sizeItem = this.sizeSelector.getItemAt(index);
351 if(sizeItem.equals(selectedInteger)){
352 this.sizeSelector.setSelectedIndex(index);
358 this.isBoldCheck .setSelected(currentFont.isBold());
359 this.isItalicCheck.setSelected(currentFont.isItalic());
360 this.useTextAntiAliaseCheck
361 .setSelected(this.fontInfo.isAntiAliased());
362 this.useFractionalCheck
363 .setSelected(this.fontInfo.usesFractionalMetrics());
366 this.decodeName.setText(FontUtils.getFontDecodeName(currentFont));
367 this.decodeName.setCaretPosition(0);
370 String form = "最大文字寸法\u0020:\u0020"
374 Rectangle rect = this.fontInfo.getMaxCharBounds();
376 MessageFormat.format(form, rect.width, rect.height);
377 this.maxBounds.setText(boundInfo);
380 this.preview.setFontInfo(this.fontInfo);
382 this.maskListener = false;
389 * @param isVisible trueなら表示 {@inheritDoc}
392 public void setVisible(boolean isVisible){
396 this.lastFontInfo = this.fontInfo;
398 super.setVisible(isVisible);
405 * フォントファミリリスト選択操作のリスナ。
406 * @param event 操作イベント {@inheritDoc}
409 public void valueChanged(ListSelectionEvent event){
410 if(this.maskListener) return;
412 if(event.getSource() != this.familySelector) return;
413 if(event.getValueIsAdjusting()) return;
415 String familyName = this.familySelector.getSelectedFamily();
416 if(familyName == null) return;
418 Font currentFont = getFontInfo().getFont();
419 int style = currentFont.getStyle();
420 int size = currentFont.getSize();
422 Font newFont = new Font(familyName, style, size);
423 FontInfo newInfo = this.fontInfo.deriveFont(newFont);
425 setFontInfo(newInfo);
432 * ボタン操作及びフォントサイズ指定コンボボックス操作のリスナ。
433 * @param event 操作イベント {@inheritDoc}
436 public void actionPerformed(ActionEvent event){
437 if(this.maskListener) return;
439 Object source = event.getSource();
441 if(source == this.sizeSelector){
442 actionFontSizeSelected();
443 }else if(source == this.resetDefault){
444 setFontInfo(FontInfo.DEFAULT_FONTINFO);
453 private void actionFontSizeSelected(){
454 Object selected = this.sizeSelector.getSelectedItem();
455 if(selected == null) return;
457 Integer selectedInteger;
458 if(selected instanceof Integer){
459 selectedInteger = (Integer) selected;
462 selectedInteger = Integer.valueOf(selected.toString());
463 }catch(NumberFormatException e){
464 selectedInteger = this.lastFontInfo.getFont().getSize();
468 if(selectedInteger <= 0){
469 selectedInteger = this.lastFontInfo.getFont().getSize();
472 float fontSize = selectedInteger.floatValue();
473 Font newFont = getFontInfo().getFont().deriveFont(fontSize);
474 FontInfo newInfo = getFontInfo().deriveFont(newFont);
476 setFontInfo(newInfo);
484 * @param event 操作イベント {@inheritDoc}
487 public void itemStateChanged(ItemEvent event){
488 if(this.maskListener) return;
490 Object source = event.getSource();
492 if( source != this.isBoldCheck
493 && source != this.isItalicCheck
494 && source != this.useTextAntiAliaseCheck
495 && source != this.useFractionalCheck ){
499 FontInfo newInfo = getFontInfo();
501 int style = 0 | Font.PLAIN;
502 if(this.isBoldCheck.isSelected()){
503 style = style | Font.BOLD;
505 if(this.isItalicCheck.isSelected()){
506 style = style | Font.ITALIC;
508 Font newFont = newInfo.getFont();
509 if(newFont.getStyle() != style){
510 newFont = newFont.deriveFont(style);
511 newInfo = newInfo.deriveFont(newFont);
514 boolean isAntiAliases = this.useTextAntiAliaseCheck.isSelected();
515 boolean useFractional = this.useFractionalCheck .isSelected();
516 newInfo = newInfo.deriveRenderContext(isAntiAliases, useFractional);
518 setFontInfo(newInfo);