001: /*
002: ** $Id: FontChooser.java,v 1.8 2000/10/26 08:34:15 mrw Exp $
003: **
004: ** Mike Wilson, October 2000, mrw@whisperingwind.co.uk
005: **
006: ** (C) Copyright 2000, Mike Wilson, Reading, Berkshire, UK
007: **
008: ** This program is free software; you can redistribute it and/or modify
009: ** it under the terms of the GNU General Public License as published by
010: ** the Free Software Foundation; either version 2 of the License, or
011: ** (at your option) any later version.
012: **
013: ** This program is distributed in the hope that it will be useful,
014: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
015: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: ** GNU General Public License for more details.
017: **
018: ** You should have received a copy of the GNU Library General
019: ** Public License along with this library; if not, write to the
020: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
021: ** Boston, MA 02111-1307 USA.
022: */
023:
024: package uk.co.whisperingwind.framework;
025:
026: import java.awt.BorderLayout;
027: import java.awt.Color;
028: import java.awt.event.ActionEvent;
029: import java.awt.event.ActionListener;
030: import java.awt.event.WindowAdapter;
031: import java.awt.event.WindowEvent;
032: import java.awt.Font;
033: import java.awt.GraphicsEnvironment;
034: import java.awt.GridBagConstraints;
035: import java.awt.GridBagLayout;
036: import java.awt.Insets;
037: import java.util.ArrayList;
038: import javax.swing.BorderFactory;
039: import javax.swing.event.ChangeEvent;
040: import javax.swing.event.ChangeListener;
041: import javax.swing.event.ListDataListener;
042: import javax.swing.event.ListSelectionEvent;
043: import javax.swing.event.ListSelectionListener;
044: import javax.swing.JButton;
045: import javax.swing.JCheckBox;
046: import javax.swing.JComboBox;
047: import javax.swing.JFrame;
048: import javax.swing.JLabel;
049: import javax.swing.JList;
050: import javax.swing.JPanel;
051: import javax.swing.JScrollPane;
052: import javax.swing.JTextField;
053: import javax.swing.ListModel;
054:
055: /**
056: ** Crude but effective Font Chooser dialog.
057: */
058:
059: public class FontChooser extends PanelDialogView implements
060: ActionListener {
061: private static FontChooser instance = null;
062: private boolean modalResult = true;
063: private ChooserPanel chooserPanel = new ChooserPanel();
064: private ActionFactory.DefaultAction okAction = null;
065: private ActionFactory.DefaultAction cancelAction = null;
066:
067: /**
068: ** Pop up an instance of FontChooser and get a font selection.
069: **
070: ** @param parent the parent frame.
071: ** @param original the original font. This font will be used to
072: ** set the initial selection in the list, the initial size etc.
073: ** @return the new selected Font, null if the user clicks
074: ** "Cancel".
075: */
076:
077: public static Font chooseFont(JFrame parent, Font original) {
078: if (instance == null)
079: instance = new FontChooser(parent);
080:
081: instance.setSelectedFont(original);
082: instance.setVisible(true);
083:
084: if (instance.modalResult)
085: return instance.getSelectedFont();
086: else
087: return null;
088: }
089:
090: /**
091: ** Constructor is private as only chooseFont should be used to
092: ** construct instances.
093: */
094:
095: private FontChooser(JFrame parent) {
096: super (parent, true);
097: createActions();
098:
099: content.setTitle("Select font");
100: panel.add(chooserPanel, BorderLayout.CENTER);
101:
102: JButton okButton = okAction.toolButtonFactory(buttonPanel);
103: cancelAction.toolButtonFactory(buttonPanel);
104:
105: content.pack();
106: content.getRootPane().setDefaultButton(okButton);
107: }
108:
109: private void createActions() {
110: ActionFactory factory = new ActionFactory(
111: "/uk/co/whisperingwind/images");
112:
113: okAction = factory.createAction("ok");
114: cancelAction = factory.createAction("cancel");
115:
116: okAction.addActionListener(this );
117: cancelAction.addActionListener(this );
118: }
119:
120: public void setSelectedFont(Font font) {
121: chooserPanel.setSelectedFont(font);
122: }
123:
124: public Font getSelectedFont() {
125: return chooserPanel.getSelectedFont();
126: }
127:
128: public void actionPerformed(ActionEvent event) {
129: String action = event.getActionCommand();
130:
131: if (action.equals("ok")) {
132: getSelectedFont();
133: modalResult = true;
134: setVisible(false);
135: } else if (action.equals("cancel")) {
136: modalResult = false;
137: setVisible(false);
138: }
139: }
140:
141: /**
142: ** List model to list all available fonts.
143: */
144:
145: private class FontListModel implements ListModel {
146: private String fontFamilies[] = null;
147:
148: public FontListModel() {
149: fontFamilies = getFontFamilies();
150: }
151:
152: public void addListDataListener(ListDataListener l) {
153: }
154:
155: public Object getElementAt(int index) {
156: return fontFamilies[index];
157: }
158:
159: public int getSize() {
160: return fontFamilies.length;
161: }
162:
163: public void removeListDataListener(ListDataListener l) {
164: }
165:
166: private String[] getFontFamilies() {
167: GraphicsEnvironment ge = GraphicsEnvironment
168: .getLocalGraphicsEnvironment();
169: String[] families = ge.getAvailableFontFamilyNames();
170:
171: return families;
172: }
173:
174: public int indexOf(String family) {
175: int found = -1;
176:
177: for (int i = 0; i < fontFamilies.length && found == -1; i++)
178: if (family.equalsIgnoreCase(fontFamilies[i]))
179: found = i;
180:
181: return found;
182: }
183: }
184:
185: /**
186: ** Panel containing the font chooser components.
187: */
188:
189: private class ChooserPanel extends JPanel implements
190: ActionListener, ChangeListener, ListSelectionListener {
191: private FontListModel fontListModel = new FontListModel();
192: private JList fontList = new JList(fontListModel);
193: private JComboBox sizeCombo = null;
194: private JCheckBox checkBold = new JCheckBox("Bold");
195: private JCheckBox checkItalic = new JCheckBox("Italic");
196: private JLabel sampleLabel = new JLabel("Sample");
197: private Font currentFont = null;
198:
199: public ChooserPanel() {
200: setLayout(new GridBagLayout());
201: GridBagConstraints constraints = new GridBagConstraints();
202:
203: constraints.insets = new Insets(4, 4, 4, 4);
204: constraints.fill = GridBagConstraints.BOTH;
205: constraints.gridheight = 4;
206: constraints.weightx = 1.0;
207: constraints.weighty = 1.0;
208: constraints.gridx = 0;
209: constraints.gridy = 0;
210: JScrollPane scroller = new JScrollPane(fontList);
211: add(scroller, constraints);
212:
213: constraints.anchor = GridBagConstraints.WEST;
214: constraints.fill = GridBagConstraints.HORIZONTAL;
215: constraints.gridheight = 1;
216: constraints.weightx = 0.0;
217: constraints.weighty = 0.0;
218: constraints.gridx = 2;
219: constraints.gridy = 0;
220: add(checkBold, constraints);
221:
222: constraints.gridy = 1;
223: add(checkItalic, constraints);
224:
225: constraints.fill = GridBagConstraints.NONE;
226: constraints.gridx = 1;
227: constraints.gridy = 2;
228: add(new JLabel("Size"), constraints);
229:
230: constraints.fill = GridBagConstraints.HORIZONTAL;
231: constraints.gridx = 2;
232: constraints.gridy = 2;
233:
234: ArrayList sizeItems = new ArrayList();
235: sizeItems.add(new String("9"));
236: sizeItems.add(new String("10"));
237: sizeItems.add(new String("12"));
238: sizeItems.add(new String("15"));
239: sizeItems.add(new String("18"));
240: sizeItems.add(new String("22"));
241:
242: sizeCombo = new JComboBox(sizeItems.toArray());
243: sizeCombo.setEditable(true);
244: add(sizeCombo, constraints);
245:
246: constraints.gridx = 0;
247: constraints.gridy = 4;
248: constraints.gridwidth = 3;
249: sampleLabel.setBorder(BorderFactory.createEtchedBorder());
250: sampleLabel.setForeground(Color.black);
251: add(sampleLabel, constraints);
252:
253: fontList.addListSelectionListener(this );
254: checkBold.addChangeListener(this );
255: checkItalic.addChangeListener(this );
256: sizeCombo.addActionListener(this );
257: }
258:
259: public void setSelectedFont(Font font) {
260: int i = fontListModel.indexOf(font.getName());
261:
262: if (i >= 0)
263: fontList.setSelectedIndex(i);
264: else
265: fontList.setSelectedIndex(0);
266:
267: checkBold.setSelected(font.isBold());
268: checkItalic.setSelected(font.isItalic());
269:
270: sampleLabel.setFont(font);
271: sizeCombo.setSelectedItem("" + font.getSize());
272:
273: currentFont = font;
274: }
275:
276: public Font getSelectedFont() {
277: return changeFont();
278: }
279:
280: public void actionPerformed(ActionEvent event) {
281: changeFont();
282: }
283:
284: public void stateChanged(ChangeEvent event) {
285: changeFont();
286: }
287:
288: public void valueChanged(ListSelectionEvent event) {
289: changeFont();
290: }
291:
292: private Font changeFont() {
293: String family = (String) fontList.getSelectedValue();
294:
295: /*
296: ** Eeek! Get the size value from the size combo. This
297: ** really does work for an editable JComboBox (dunno about
298: ** a non-editable as I haven't tried it). This always gets
299: ** the value shown in the editable combo which isn't the
300: ** case with getSelectedValue ().
301: */
302:
303: JTextField textField = (JTextField) sizeCombo.getEditor()
304: .getEditorComponent();
305: int size = Integer.parseInt(textField.getText());
306:
307: int style = Font.PLAIN;
308:
309: if (checkBold.isSelected())
310: style += Font.BOLD;
311:
312: if (checkItalic.isSelected())
313: style += Font.ITALIC;
314:
315: Font changeTo = new Font(family, style, size);
316:
317: if (!changeTo.equals(currentFont)) {
318: currentFont = changeTo;
319: sampleLabel.setFont(currentFont);
320: }
321:
322: return currentFont;
323: }
324: }
325:
326: public void modelEvent(ModelEvent event) {
327: }
328:
329: protected void cleanUp() {
330: instance = null;
331: }
332:
333: /**
334: ** When the window dies, behave like the Cancel button was
335: ** clicked.
336: */
337:
338: private class DeadleyWindowListener extends WindowAdapter {
339: public void windowClosing(WindowEvent event) {
340: fireEvent("cancel");
341: }
342: }
343: }
|