API for custom color schemes was extracted Two ruby dark schemes schemes were bundled
[fedora-idea.git] / lang-impl / src / com / intellij / application / options / colors / FontOptions.java
blob176d9bcb07f3adf3c68dae64dcfbd0848b782be7
1 package com.intellij.application.options.colors;
3 import com.intellij.application.options.SelectFontDialog;
4 import com.intellij.openapi.application.ApplicationBundle;
5 import com.intellij.openapi.editor.colors.EditorColorsScheme;
6 import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
7 import com.intellij.openapi.progress.ProgressIndicator;
8 import com.intellij.openapi.progress.ProgressManager;
9 import com.intellij.openapi.ui.FixedSizeButton;
10 import com.intellij.ui.DocumentAdapter;
11 import com.intellij.ui.IdeBorderFactory;
12 import com.intellij.util.EventDispatcher;
13 import com.intellij.util.containers.HashMap;
15 import javax.swing.*;
16 import javax.swing.event.DocumentEvent;
17 import java.awt.*;
18 import java.awt.event.ActionEvent;
19 import java.awt.event.ActionListener;
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.Set;
24 public class FontOptions extends JPanel implements OptionsPanel{
25 private ColorAndFontOptions myOptions;
27 private JTextField myEditorFontSizeField;
29 private JTextField myLineSpacingField;
30 private JTextField myFontNameField;
32 private static ArrayList<String> myFontNamesVector;
33 private static HashMap<String, Boolean> myFontNameToIsMonospaced;
34 private final EventDispatcher<ColorAndFontSettingsListener> myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class);
35 private boolean myIsInSchemeChange = false;
38 public FontOptions(ColorAndFontOptions options) {
39 super(new BorderLayout());
40 myOptions = options;
42 JPanel schemesGroup = new JPanel(new BorderLayout());
44 JPanel panel = new JPanel(new BorderLayout());
45 panel.add(createFontPanel(), BorderLayout.NORTH);
46 schemesGroup.add(panel, BorderLayout.CENTER);
47 add(schemesGroup, BorderLayout.CENTER);
50 public void updateOptionsList() {
51 myIsInSchemeChange = true;
53 myLineSpacingField.setText(Float.toString(getCurrentScheme().getLineSpacing()));
54 myEditorFontSizeField.setText(Integer.toString(getCurrentScheme().getEditorFontSize()));
55 myFontNameField.setText(getCurrentScheme().getEditorFontName());
57 if (ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme())) {
58 myLineSpacingField.setEnabled(false);
59 myEditorFontSizeField.setEditable(false);
60 myFontNameField.setEnabled(false);
62 else {
63 myLineSpacingField.setEnabled(true);
64 myEditorFontSizeField.setEditable(true);
65 myFontNameField.setEnabled(true);
68 myIsInSchemeChange = false;
72 public Runnable showOption(final String option) {
73 return null;
76 public void applyChangesToScheme() {
80 public void selectOption(final String typeToSelect) {
83 private EditorColorsScheme getCurrentScheme() {
84 return myOptions.getSelectedScheme();
87 private JPanel createFontPanel() {
88 JPanel editorFontPanel = new JPanel();
89 editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("group.editor.font")));
90 editorFontPanel.setLayout(new GridBagLayout());
91 GridBagConstraints gbConstraints = new GridBagConstraints();
92 gbConstraints.fill = GridBagConstraints.HORIZONTAL;
93 gbConstraints.weightx = 0;
94 gbConstraints.weighty = 1;
95 gbConstraints.gridx = 0;
96 gbConstraints.gridy = 0;
97 gbConstraints.gridwidth = 1;
99 gbConstraints.insets = new Insets(0, 0, 0, 0);
100 gbConstraints.gridwidth = 1;
101 editorFontPanel.add(new JLabel(ApplicationBundle.message("label.font.name")), gbConstraints);
103 myFontNameField = new MyTextField(20);
104 myFontNameField.setEditable(false);
105 myFontNameField.setFocusable(false);
107 gbConstraints.gridx = 1;
108 gbConstraints.insets = new Insets(0, 0, 0, 2);
109 editorFontPanel.add(myFontNameField, gbConstraints);
111 JButton myFontNameButton = new FixedSizeButton(myFontNameField);
112 gbConstraints.gridx = 2;
113 gbConstraints.insets = new Insets(0, 0, 0, 8);
114 editorFontPanel.add(myFontNameButton, gbConstraints);
116 gbConstraints.gridx = 3;
117 gbConstraints.insets = new Insets(0, 0, 0, 0);
118 editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.font.size")), gbConstraints);
119 gbConstraints.gridx = 4;
120 gbConstraints.insets = new Insets(0, 0, 0, 8);
121 myEditorFontSizeField = new MyTextField(4);
122 gbConstraints.gridx = 5;
123 editorFontPanel.add(myEditorFontSizeField, gbConstraints);
124 gbConstraints.insets = new Insets(0, 0, 0, 0);
125 gbConstraints.gridx = 6;
126 editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), gbConstraints);
127 gbConstraints.insets = new Insets(0, 0, 0, 0);
128 gbConstraints.gridx = 7;
129 myLineSpacingField = new MyTextField(4);
130 editorFontPanel.add(myLineSpacingField, gbConstraints);
131 gbConstraints.weightx = 1;
132 gbConstraints.gridx = 8;
133 editorFontPanel.add(new TailPanel(), gbConstraints);
135 myFontNameButton.addActionListener(new ActionListener() {
136 public void actionPerformed(ActionEvent e) {
137 EditorColorsScheme current = getCurrentScheme();
138 if (ColorAndFontOptions.isReadOnly(current) || ColorSettingsUtil.isSharedScheme(current)) {
139 ColorAndFontPanel.showReadOnlyMessage(FontOptions.this, ColorSettingsUtil.isSharedScheme(current));
140 return;
143 selectFont();
147 myEditorFontSizeField.getDocument().addDocumentListener(new DocumentAdapter() {
148 public void textChanged(DocumentEvent event) {
149 if (myIsInSchemeChange) return;
150 int fontSize = 12;
151 try {
152 fontSize = Integer.parseInt(myEditorFontSizeField.getText());
154 catch (NumberFormatException e) {
155 // OK, ignore
157 finally {
158 if (fontSize < 1) fontSize = 1;
159 if (fontSize > 30) fontSize = 30;
161 getCurrentScheme().setEditorFontSize(fontSize);
162 updateDescription(true);
167 myLineSpacingField.getDocument().addDocumentListener(new DocumentAdapter() {
168 public void textChanged(DocumentEvent event) {
169 if (myIsInSchemeChange) return;
170 float lineSpacing = 1;
171 try {
172 lineSpacing = Float.parseFloat(myLineSpacingField.getText());
174 catch (NumberFormatException e) {
175 // OK, ignore
177 finally {
178 if (lineSpacing <= 0) lineSpacing = 1;
179 if (lineSpacing > 30) lineSpacing = 30;
180 if (getCurrentScheme().getLineSpacing() != lineSpacing) {
181 getCurrentScheme().setLineSpacing(lineSpacing);
183 updateDescription(true);
188 return editorFontPanel;
191 private void selectFont() {
192 initFontTables();
194 java.util.List<String> fontNamesVector = (java.util.List<String>)myFontNamesVector.clone();
195 HashMap fontNameToIsMonospaced = (HashMap)myFontNameToIsMonospaced.clone();
196 String initialFontName = myFontNameField.getText();
197 if (!fontNamesVector.contains(EditorSettingsExternalizable.DEFAULT_FONT_NAME)) {
198 fontNamesVector.add(0, EditorSettingsExternalizable.DEFAULT_FONT_NAME);
200 if (!fontNamesVector.contains(initialFontName)) {
201 fontNamesVector.add(0, initialFontName);
203 SelectFontDialog selectFontDialog = new SelectFontDialog(this, fontNamesVector, initialFontName, fontNameToIsMonospaced);
204 selectFontDialog.show();
205 if (!selectFontDialog.isOK()) {
206 return;
208 String fontName = selectFontDialog.getFontName();
209 if (fontName != null) {
210 myFontNameField.setText(fontName);
211 getCurrentScheme().setEditorFontName(fontName);
212 updateDescription(true);
216 @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
217 private void initFontTables() {
218 if (myFontNamesVector == null) {
219 myFontNamesVector = new ArrayList<String>();
220 myFontNameToIsMonospaced = new HashMap<String, Boolean>();
222 ProgressManager.getInstance()
223 .runProcessWithProgressSynchronously(new InitFontsRunnable(), ApplicationBundle.message("progress.analyzing.fonts"), false, null);
227 public boolean updateDescription(boolean modified) {
228 EditorColorsScheme scheme = myOptions.getSelectedScheme();
230 if (modified && (ColorAndFontOptions.isReadOnly(scheme) || ColorSettingsUtil.isSharedScheme(scheme))) {
231 ColorAndFontPanel.showReadOnlyMessage(this, ColorSettingsUtil.isSharedScheme(scheme));
232 return false;
235 myDispatcher.getMulticaster().fontChanged();
237 return true;
240 private class InitFontsRunnable implements Runnable {
241 public void run() {
242 ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
244 GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
245 String[] fontNames = graphicsEnvironment.getAvailableFontFamilyNames();
246 for (final String fontName : fontNames) {
247 //noinspection HardCodedStringLiteral
248 if (fontName.endsWith(".bold") || fontName.endsWith(".italic")) {
249 continue;
251 try {
252 Font plainFont = new Font(fontName, Font.PLAIN, 12);
253 if (plainFont.canDisplay('W')) {
254 Font boldFont = plainFont.deriveFont(Font.BOLD);
255 if (progress != null) {
256 progress.setText(ApplicationBundle.message("progress.analysing.font", fontName));
258 FontMetrics plainMetrics = getFontMetrics(plainFont);
259 FontMetrics boldMetrics = getFontMetrics(boldFont);
260 myFontNamesVector.add(fontName);
261 int plainL = plainMetrics.charWidth('l');
262 int boldL = boldMetrics.charWidth('l');
263 int plainW = plainMetrics.charWidth('W');
264 int boldW = boldMetrics.charWidth('W');
265 int plainSpace = plainMetrics.charWidth(' ');
266 int boldSpace = boldMetrics.charWidth(' ');
267 boolean isMonospaced = plainL == plainW && plainL == boldL && plainW == boldW && plainSpace == boldSpace;
268 myFontNameToIsMonospaced.put(fontName, isMonospaced);
271 catch (Throwable e) {
272 // JRE has problems working with the font. Just skip.
278 private static class MyTextField extends JTextField {
279 public MyTextField(int size) {
280 super(size);
283 public Dimension getMinimumSize() {
284 return super.getPreferredSize();
288 public void addListener(ColorAndFontSettingsListener listener) {
289 myDispatcher.addListener(listener);
292 public JPanel getPanel() {
293 return this;
296 public Set<String> processListOptions() {
297 return new HashSet<String>();