IDEA-97665 Provide an option to specify fall back fonts
It's possible to configure list of fonts to use. That instructs the IDE to try them sequentially if current font is unable to display particular symbol (old behavior - try the single configured font, randomly choose a fallback font able to display a symbol that can't be displayed by the configured one)
|
After Width: | Height: | Size: 262 B |
|
After Width: | Height: | Size: 413 B |
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 262 B |
|
After Width: | Height: | Size: 267 B |
|
After Width: | Height: | Size: 416 B |
|
After Width: | Height: | Size: 415 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 201 B |
|
After Width: | Height: | Size: 286 B |
|
After Width: | Height: | Size: 286 B |
|
After Width: | Height: | Size: 202 B |
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 306 B |
|
After Width: | Height: | Size: 306 B |
|
After Width: | Height: | Size: 213 B |
|
After Width: | Height: | Size: 209 B |
|
After Width: | Height: | Size: 306 B |
|
After Width: | Height: | Size: 306 B |
|
After Width: | Height: | Size: 209 B |
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 276 B |
|
After Width: | Height: | Size: 276 B |
|
After Width: | Height: | Size: 203 B |
@@ -64,7 +64,7 @@ public class ColorAndFontDescriptionPanel extends JPanel {
|
||||
private ActionListener myActionListener;
|
||||
private JLabel myLabelFont;
|
||||
|
||||
private JLabel myInheritanceLabel = new JLabel();
|
||||
private JLabel myInheritanceLabel = new JLabel("X");
|
||||
private final static Icon INHERITED_ICON = AllIcons.Ide.Link;
|
||||
|
||||
|
||||
|
||||
@@ -234,11 +234,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
|
||||
|
||||
myColorsManager.removeAllSchemes();
|
||||
for (MyColorScheme scheme : mySchemes.values()) {
|
||||
if (!scheme.isDefault()) {
|
||||
scheme.apply();
|
||||
myColorsManager.addColorsScheme(scheme.getOriginalScheme());
|
||||
}
|
||||
if (!scheme.isDefault()) {
|
||||
scheme.apply();
|
||||
myColorsManager.addColorsScheme(scheme.getOriginalScheme());
|
||||
}
|
||||
}
|
||||
|
||||
EditorColorsScheme originalScheme = mySelectedScheme.getOriginalScheme();
|
||||
myColorsManager.setGlobalScheme(originalScheme);
|
||||
@@ -990,27 +990,18 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
|
||||
}
|
||||
|
||||
private static class MyColorScheme extends EditorColorsSchemeImpl {
|
||||
private int myFontSize;
|
||||
private float myLineSpacing;
|
||||
private String myFontName;
|
||||
|
||||
private int myConsoleFontSize;
|
||||
private float myConsoleLineSpacing;
|
||||
private String myConsoleFontName;
|
||||
|
||||
private EditorSchemeAttributeDescriptor[] myDescriptors;
|
||||
private String myName;
|
||||
private String myName;
|
||||
private boolean myIsNew = false;
|
||||
|
||||
private MyColorScheme(EditorColorsScheme parentScheme) {
|
||||
super(parentScheme, DefaultColorSchemesManager.getInstance());
|
||||
myFontSize = parentScheme.getEditorFontSize();
|
||||
myLineSpacing = parentScheme.getLineSpacing();
|
||||
myFontName = parentScheme.getEditorFontName();
|
||||
parentScheme.getFontPreferences().copyTo(getFontPreferences());
|
||||
setLineSpacing(parentScheme.getLineSpacing());
|
||||
|
||||
myConsoleFontSize = parentScheme.getConsoleFontSize();
|
||||
myConsoleLineSpacing = parentScheme.getConsoleLineSpacing();
|
||||
myConsoleFontName = parentScheme.getConsoleFontName();
|
||||
parentScheme.getConsoleFontPreferences().copyTo(getConsoleFontPreferences());
|
||||
setConsoleLineSpacing(parentScheme.getConsoleLineSpacing());
|
||||
|
||||
setQuickDocFontSize(parentScheme.getQuickDocFontSize());
|
||||
myName = parentScheme.getName();
|
||||
@@ -1059,17 +1050,15 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
|
||||
}
|
||||
|
||||
private boolean isFontModified() {
|
||||
if (myFontSize != myParentScheme.getEditorFontSize()) return true;
|
||||
if (myLineSpacing != myParentScheme.getLineSpacing()) return true;
|
||||
if (!myFontName.equals(myParentScheme.getEditorFontName())) return true;
|
||||
if (myQuickDocFontSize != myParentScheme.getQuickDocFontSize()) return true;
|
||||
if (!getFontPreferences().equals(myParentScheme.getFontPreferences())) return true;
|
||||
if (getLineSpacing() != myParentScheme.getLineSpacing()) return true;
|
||||
if (getQuickDocFontSize() != myParentScheme.getQuickDocFontSize()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isConsoleFontModified() {
|
||||
if (myConsoleFontSize != myParentScheme.getConsoleFontSize()) return true;
|
||||
if (myConsoleLineSpacing != myParentScheme.getConsoleLineSpacing()) return true;
|
||||
if (!myConsoleFontName.equals(myParentScheme.getConsoleFontName())) return true;
|
||||
if (!getConsoleFontPreferences().equals(myParentScheme.getConsoleFontPreferences())) return true;
|
||||
if (getConsoleLineSpacing() != myParentScheme.getConsoleLineSpacing()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1078,85 +1067,17 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
|
||||
}
|
||||
|
||||
public void apply(EditorColorsScheme scheme) {
|
||||
scheme.setEditorFontSize(myFontSize);
|
||||
scheme.setEditorFontName(myFontName);
|
||||
getFontPreferences().copyTo(scheme.getFontPreferences());
|
||||
scheme.setLineSpacing(myLineSpacing);
|
||||
scheme.setQuickDocFontSize(getQuickDocFontSize());
|
||||
scheme.setConsoleFontSize(myConsoleFontSize);
|
||||
scheme.setConsoleFontName(myConsoleFontName);
|
||||
scheme.setConsoleLineSpacing(myConsoleLineSpacing);
|
||||
getConsoleFontPreferences().copyTo(scheme.getConsoleFontPreferences());
|
||||
scheme.setConsoleLineSpacing(getConsoleLineSpacing());
|
||||
|
||||
for (EditorSchemeAttributeDescriptor descriptor : myDescriptors) {
|
||||
descriptor.apply(scheme);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEditorFontName() {
|
||||
return myFontName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEditorFontSize() {
|
||||
return myFontSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLineSpacing() {
|
||||
return myLineSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEditorFontSize(int fontSize) {
|
||||
myFontSize = fontSize;
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLineSpacing(float lineSpacing) {
|
||||
assert lineSpacing >= 0 : lineSpacing;
|
||||
myLineSpacing = lineSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEditorFontName(String fontName) {
|
||||
myFontName = fontName;
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConsoleFontName() {
|
||||
return myConsoleFontName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConsoleFontName(String fontName) {
|
||||
myConsoleFontName = fontName;
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConsoleFontSize() {
|
||||
return myConsoleFontSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConsoleFontSize(int fontSize) {
|
||||
myConsoleFontSize = fontSize;
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getConsoleLineSpacing() {
|
||||
return myConsoleLineSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConsoleLineSpacing(float lineSpacing) {
|
||||
assert lineSpacing >= 0 : lineSpacing;
|
||||
myConsoleLineSpacing = lineSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.intellij.application.options.colors;
|
||||
|
||||
import com.intellij.openapi.editor.colors.FontPreferences;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
*/
|
||||
@@ -23,24 +26,10 @@ public class ConsoleFontOptions extends FontOptions {
|
||||
super(options, "Console Font");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getCurrentFontName() {
|
||||
return getCurrentScheme().getConsoleFontName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCurrentFontName(String fontName) {
|
||||
getCurrentScheme().setConsoleFontName(fontName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getCurrentFontSize() {
|
||||
return getCurrentScheme().getConsoleFontSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCurrentFontSize(int fontSize) {
|
||||
getCurrentScheme().setConsoleFontSize(fontSize);
|
||||
protected FontPreferences getFontPreferences() {
|
||||
return getCurrentScheme().getConsoleFontPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,7 +56,12 @@ public class FontEditorPreview implements PreviewPanel{
|
||||
"advanced code editing and refactoring support.\n" +
|
||||
"\n" +
|
||||
"abcdefghijklmnopqrstuvwxyz 0123456789 (){}[]\n" +
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ +-*/= .,;:!? #&$%@|^";
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ +-*/= .,;:!? #&$%@|^\n" +
|
||||
// Create empty lines in order to make the gutter wide enough to display two-digits line numbers (other previews use long text
|
||||
// and we don't want different gutter widths on color pages switching).
|
||||
"\n" +
|
||||
"\n" +
|
||||
"\n";
|
||||
}
|
||||
|
||||
static void installTrafficLights(@NotNull EditorEx editor) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,196 +17,198 @@
|
||||
package com.intellij.application.options.colors;
|
||||
|
||||
import com.intellij.application.options.OptionsConstants;
|
||||
import com.intellij.application.options.SelectFontDialog;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
|
||||
import com.intellij.openapi.editor.colors.FontPreferences;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.ui.FixedSizeButton;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.ListSpeedSearch;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.components.JBMovePanel;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class FontOptions extends JPanel implements OptionsPanel{
|
||||
private final ColorAndFontOptions myOptions;
|
||||
|
||||
private JTextField myEditorFontSizeField;
|
||||
private static List<String> myFontNames;
|
||||
private static List<String> myMonospacedFontNames;
|
||||
|
||||
private JTextField myLineSpacingField;
|
||||
private JTextField myFontNameField;
|
||||
|
||||
private static ArrayList<String> myFontNames;
|
||||
private static ArrayList<String> myMonospacedFontNames;
|
||||
private final EventDispatcher<ColorAndFontSettingsListener> myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class);
|
||||
private boolean myIsInSchemeChange = false;
|
||||
private String myTitle;
|
||||
|
||||
@NotNull private final ColorAndFontOptions myOptions;
|
||||
|
||||
@NotNull private final DefaultListModel myAllFontsModel = new DefaultListModel();
|
||||
@NotNull private final JBList myAllFontsList = new JBList(myAllFontsModel);
|
||||
@NotNull private final DefaultListModel mySelectedFontsModel = new DefaultListModel();
|
||||
@NotNull private final JBList mySelectedFontsList = new JBList(mySelectedFontsModel);
|
||||
@NotNull private final JBMovePanel myFontsControl = new JBMovePanel(myAllFontsList, mySelectedFontsList) {
|
||||
@SuppressWarnings("SSBasedInspection")
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
if (myFontNames == null) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initFontTables();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull private final JTextField myEditorFontSizeField = new MyTextField(4);
|
||||
@NotNull private final JTextField myLineSpacingField = new MyTextField(4);
|
||||
|
||||
@NotNull private final JBCheckBox myOnlyMonospacedCheckBox =
|
||||
new JBCheckBox(ApplicationBundle.message("checkbox.show.only.monospaced.fonts"));
|
||||
@Nullable private final Dimension myPreferredSize;
|
||||
|
||||
private boolean myIsInSchemeChange;
|
||||
private String myTitle;
|
||||
|
||||
public FontOptions(ColorAndFontOptions options) {
|
||||
this(options, ApplicationBundle.message("group.editor.font"));
|
||||
}
|
||||
|
||||
protected FontOptions(ColorAndFontOptions options, final String title) {
|
||||
super(new BorderLayout());
|
||||
protected FontOptions(@NotNull ColorAndFontOptions options, final String title) {
|
||||
super(new GridBagLayout());
|
||||
myOptions = options;
|
||||
myTitle = title;
|
||||
add(createEditorFontPanel(), new GridBag().weightx(1).weighty(1).fillCell().coverLine());
|
||||
add(new JLabel(ApplicationBundle.message("label.fallback.fonts.list.description"),
|
||||
MessageType.INFO.getDefaultIcon(),
|
||||
SwingConstants.LEFT),
|
||||
new GridBag().anchor(GridBagConstraints.WEST));
|
||||
myFontsControl.setShowButtons(JBMovePanel.ButtonType.LEFT, JBMovePanel.ButtonType.RIGHT);
|
||||
myFontsControl.setListLabels(ApplicationBundle.message("title.font.available"), ApplicationBundle.message("title.font.selected"));
|
||||
myFontsControl.setEnabled(false); // Disable the controls until fonts are loaded.
|
||||
myFontsControl.setLeftInsertionStrategy(JBMovePanel.NATURAL_ORDER);
|
||||
myOnlyMonospacedCheckBox.setSelected(EditorColorsManager.getInstance().isUseOnlyMonospacedFonts());
|
||||
new ListSpeedSearch(myAllFontsList);
|
||||
new ListSpeedSearch(mySelectedFontsList);
|
||||
|
||||
JPanel schemesGroup = new JPanel(new BorderLayout());
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(createEditorFontPanel(), BorderLayout.NORTH);
|
||||
schemesGroup.add(panel, BorderLayout.CENTER);
|
||||
add(schemesGroup, BorderLayout.CENTER);
|
||||
// Almost all other color scheme pages use the following pattern:
|
||||
//
|
||||
// __________________________________________
|
||||
// | color keys | color and font settings |
|
||||
//
|
||||
// Here page's height is calculated on the 'color and font settings' preferred height (debugged a lot to ensure that).
|
||||
// The idea is to configure current page to use the same height as other pages. That's why we set it up to use the same preferred
|
||||
// size as 'color and font settings' control.
|
||||
myPreferredSize = new ColorAndFontDescriptionPanel().getPreferredSize();
|
||||
if (myFontNames != null) {
|
||||
onFontsInit();
|
||||
}
|
||||
initListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOptionsList() {
|
||||
myIsInSchemeChange = true;
|
||||
|
||||
myLineSpacingField.setText(Float.toString(getLineSpacing()));
|
||||
myEditorFontSizeField.setText(Integer.toString(getCurrentFontSize()));
|
||||
myFontNameField.setText(getCurrentFontName());
|
||||
|
||||
boolean enabled = !ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme());
|
||||
myLineSpacingField.setEnabled(enabled);
|
||||
myEditorFontSizeField.setEditable(enabled);
|
||||
myFontNameField.setEnabled(enabled);
|
||||
|
||||
myIsInSchemeChange = false;
|
||||
|
||||
}
|
||||
|
||||
protected String getCurrentFontName() {
|
||||
return getCurrentScheme().getEditorFontName();
|
||||
}
|
||||
|
||||
protected void setCurrentFontName(String fontName) {
|
||||
getCurrentScheme().setEditorFontName(fontName);
|
||||
}
|
||||
|
||||
|
||||
protected int getCurrentFontSize() {
|
||||
return getCurrentScheme().getEditorFontSize();
|
||||
}
|
||||
|
||||
protected void setCurrentFontSize(int fontSize) {
|
||||
getCurrentScheme().setEditorFontSize(fontSize);
|
||||
}
|
||||
|
||||
protected float getLineSpacing() {
|
||||
return getCurrentScheme().getLineSpacing();
|
||||
}
|
||||
|
||||
protected void setCurrentLineSpacing(float lineSpacing) {
|
||||
getCurrentScheme().setLineSpacing(lineSpacing);
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Runnable showOption(final String option) {
|
||||
return null;
|
||||
public Dimension getPreferredSize() {
|
||||
return myPreferredSize == null ? super.getPreferredSize() : myPreferredSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyChangesToScheme() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectOption(final String typeToSelect) {
|
||||
}
|
||||
|
||||
protected EditorColorsScheme getCurrentScheme() {
|
||||
return myOptions.getSelectedScheme();
|
||||
}
|
||||
|
||||
private JPanel createEditorFontPanel() {
|
||||
JPanel editorFontPanel = new JPanel();
|
||||
editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(myTitle, false));
|
||||
editorFontPanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints gbConstraints = new GridBagConstraints();
|
||||
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbConstraints.weightx = 0;
|
||||
gbConstraints.weighty = 1;
|
||||
gbConstraints.gridx = 0;
|
||||
gbConstraints.gridy = 0;
|
||||
gbConstraints.gridwidth = 1;
|
||||
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 0);
|
||||
gbConstraints.gridwidth = 1;
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("label.font.name")), gbConstraints);
|
||||
|
||||
myFontNameField = new MyTextField(20);
|
||||
myFontNameField.setEditable(false);
|
||||
myFontNameField.setFocusable(false);
|
||||
|
||||
gbConstraints.gridx = 1;
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 2);
|
||||
editorFontPanel.add(myFontNameField, gbConstraints);
|
||||
|
||||
JButton myFontNameButton = new FixedSizeButton(myFontNameField);
|
||||
gbConstraints.gridx = 2;
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 8);
|
||||
editorFontPanel.add(myFontNameButton, gbConstraints);
|
||||
|
||||
gbConstraints.gridx = 3;
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 0);
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.font.size")), gbConstraints);
|
||||
gbConstraints.gridx = 4;
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 8);
|
||||
myEditorFontSizeField = new MyTextField(4);
|
||||
gbConstraints.gridx = 5;
|
||||
editorFontPanel.add(myEditorFontSizeField, gbConstraints);
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 0);
|
||||
gbConstraints.gridx = 6;
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), gbConstraints);
|
||||
gbConstraints.insets = new Insets(0, 0, 0, 0);
|
||||
gbConstraints.gridx = 7;
|
||||
myLineSpacingField = new MyTextField(4);
|
||||
editorFontPanel.add(myLineSpacingField, gbConstraints);
|
||||
gbConstraints.weightx = 1;
|
||||
gbConstraints.gridx = 8;
|
||||
editorFontPanel.add(new TailPanel(), gbConstraints);
|
||||
|
||||
myFontNameButton.addActionListener(new ActionListener() {
|
||||
private void initListeners() {
|
||||
myOnlyMonospacedCheckBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
EditorColorsScheme current = getCurrentScheme();
|
||||
if (ColorAndFontOptions.isReadOnly(current) || ColorSettingsUtil.isSharedScheme(current)) {
|
||||
showReadOnlyMessage(FontOptions.this, ColorSettingsUtil.isSharedScheme(current));
|
||||
return;
|
||||
}
|
||||
|
||||
selectFont();
|
||||
boolean onlyMonospaced = myOnlyMonospacedCheckBox.isSelected();
|
||||
EditorColorsManager.getInstance().setUseOnlyMonospacedFonts(onlyMonospaced);
|
||||
onFontsInit();
|
||||
}
|
||||
});
|
||||
|
||||
mySelectedFontsModel.addListDataListener(new ListDataListener() {
|
||||
@Override
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
syncFontFamilies();
|
||||
}
|
||||
|
||||
private void syncFontFamilies() {
|
||||
if (myIsInSchemeChange) {
|
||||
return;
|
||||
}
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
fontPreferences.clearFonts();
|
||||
Enumeration elements = mySelectedFontsModel.elements();
|
||||
while (elements.hasMoreElements()) {
|
||||
String fontFamily = (String)elements.nextElement();
|
||||
// Don't save a single 'default' font family at the font preferences.
|
||||
if (mySelectedFontsModel.getSize() > 1 || !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily)) {
|
||||
fontPreferences.addFontFamily(fontFamily);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mySelectedFontsList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
Object value = mySelectedFontsList.getSelectedValue();
|
||||
if (value != null) {
|
||||
boolean toRestore = myIsInSchemeChange;
|
||||
myIsInSchemeChange = true;
|
||||
try {
|
||||
myEditorFontSizeField.setText(String.valueOf(getFontPreferences().getSize((String)value)));
|
||||
}
|
||||
finally {
|
||||
myIsInSchemeChange = toRestore;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myEditorFontSizeField.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void textChanged(DocumentEvent event) {
|
||||
if (myIsInSchemeChange) return;
|
||||
int fontSize = OptionsConstants.DEFAULT_EDITOR_FONT_SIZE;
|
||||
if (myIsInSchemeChange || !SwingUtilities.isEventDispatchThread()) return;
|
||||
try {
|
||||
fontSize = Integer.parseInt(myEditorFontSizeField.getText());
|
||||
int fontSize = Integer.parseInt(myEditorFontSizeField.getText());
|
||||
if (fontSize < 1) fontSize = 1;
|
||||
if (fontSize > OptionsConstants.MAX_EDITOR_FONT_SIZE) fontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
|
||||
Object selectedFont = mySelectedFontsList.getSelectedValue();
|
||||
if (selectedFont != null) {
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
fontPreferences.register((String)selectedFont, fontSize);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// OK, ignore
|
||||
}
|
||||
finally {
|
||||
if (fontSize < 1) fontSize = 1;
|
||||
if (fontSize > OptionsConstants.MAX_EDITOR_FONT_SIZE) fontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
|
||||
|
||||
setCurrentFontSize(fontSize);
|
||||
updateDescription(true);
|
||||
}
|
||||
}
|
||||
@@ -234,32 +236,151 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
}
|
||||
});
|
||||
|
||||
return editorFontPanel;
|
||||
}
|
||||
|
||||
public static void showReadOnlyMessage(JComponent parent, final boolean sharedScheme) {
|
||||
if (!sharedScheme) {
|
||||
Messages.showMessageDialog(
|
||||
parent,
|
||||
ApplicationBundle.message("error.readonly.scheme.cannot.be.modified"),
|
||||
ApplicationBundle.message("title.cannot.modify.readonly.scheme"),
|
||||
Messages.getInformationIcon()
|
||||
);
|
||||
}
|
||||
else {
|
||||
Messages.showMessageDialog(
|
||||
parent,
|
||||
ApplicationBundle.message("error.shared.scheme.cannot.be.modified"),
|
||||
ApplicationBundle.message("title.cannot.modify.readonly.scheme"),
|
||||
Messages.getInformationIcon()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectFont() {
|
||||
initFontTables();
|
||||
@Override
|
||||
public void updateOptionsList() {
|
||||
myIsInSchemeChange = true;
|
||||
|
||||
ArrayList<String> fontNames = new ArrayList<String>(myFontNames);
|
||||
ArrayList<String> monospacedFontNames = new ArrayList<String>(myMonospacedFontNames);
|
||||
String initialFontName = myFontNameField.getText();
|
||||
if (!fontNames.contains(EditorSettingsExternalizable.DEFAULT_FONT_NAME)) {
|
||||
fontNames.add(0, EditorSettingsExternalizable.DEFAULT_FONT_NAME);
|
||||
myLineSpacingField.setText(Float.toString(getLineSpacing()));
|
||||
mySelectedFontsModel.clear();
|
||||
FontPreferences fontPreferences = getFontPreferences();
|
||||
List<String> fontFamilies = fontPreferences.getFontFamilies();
|
||||
Set<String> selectedFonts = ContainerUtilRt.newHashSet();
|
||||
Object selectedValue = mySelectedFontsList.getSelectedValue();
|
||||
mySelectedFontsModel.clear();
|
||||
if (fontFamilies.isEmpty()) {
|
||||
// Add default font.
|
||||
mySelectedFontsModel.addElement(fontPreferences.getFontFamily());
|
||||
selectedFonts.add(fontPreferences.getFontFamily());
|
||||
}
|
||||
if (!fontNames.contains(initialFontName)) {
|
||||
fontNames.add(0, initialFontName);
|
||||
else {
|
||||
for (String fontFamily : fontFamilies) {
|
||||
mySelectedFontsModel.addElement(fontFamily);
|
||||
selectedFonts.add(fontFamily);
|
||||
}
|
||||
}
|
||||
SelectFontDialog selectFontDialog = new SelectFontDialog(this, fontNames, initialFontName, monospacedFontNames);
|
||||
selectFontDialog.show();
|
||||
if (!selectFontDialog.isOK()) {
|
||||
return;
|
||||
|
||||
int newSelectionIndex = 0;
|
||||
if (selectedValue != null) {
|
||||
newSelectionIndex = Math.max(0, mySelectedFontsModel.indexOf(selectedValue));
|
||||
}
|
||||
String fontName = selectFontDialog.getFontName();
|
||||
if (fontName != null) {
|
||||
myFontNameField.setText(fontName);
|
||||
setCurrentFontName(fontName);
|
||||
updateDescription(true);
|
||||
mySelectedFontsList.setSelectedIndex(newSelectionIndex);
|
||||
|
||||
for (int i = myAllFontsModel.size() - 1; i >= 0; i--) {
|
||||
if (selectedFonts.contains(myAllFontsModel.getElementAt(i))) {
|
||||
myAllFontsModel.remove(i);
|
||||
}
|
||||
}
|
||||
myEditorFontSizeField.setText(String.valueOf(fontPreferences.getSize(fontPreferences.getFontFamily())));
|
||||
|
||||
boolean enabled = !ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme());
|
||||
myOnlyMonospacedCheckBox.setEnabled(enabled);
|
||||
myLineSpacingField.setEnabled(enabled);
|
||||
myEditorFontSizeField.setEditable(enabled);
|
||||
myFontsControl.setEnabled(enabled);
|
||||
|
||||
myIsInSchemeChange = false;
|
||||
}
|
||||
|
||||
private void onFontsInit() {
|
||||
assert myFontNames != null;
|
||||
Object selectedValue = myAllFontsList.getSelectedValue();
|
||||
myAllFontsModel.clear();
|
||||
List<String> availableFonts = myOnlyMonospacedCheckBox.isSelected() ? myMonospacedFontNames : myFontNames;
|
||||
int newSelectionIndex = 0;
|
||||
int i = 0;
|
||||
for (String name : availableFonts) {
|
||||
if (!mySelectedFontsModel.contains(name)) { // Don't bother with performance here in assumption that fallback fonts sequence is short
|
||||
myAllFontsModel.addElement(name);
|
||||
if (name.equals(selectedValue)) {
|
||||
newSelectionIndex = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
myAllFontsList.setSelectedIndex(newSelectionIndex);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected FontPreferences getFontPreferences() {
|
||||
return getCurrentScheme().getFontPreferences();
|
||||
}
|
||||
|
||||
protected float getLineSpacing() {
|
||||
return getCurrentScheme().getLineSpacing();
|
||||
}
|
||||
|
||||
protected void setCurrentLineSpacing(float lineSpacing) {
|
||||
getCurrentScheme().setLineSpacing(lineSpacing);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Runnable showOption(final String option) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyChangesToScheme() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectOption(final String typeToSelect) {
|
||||
}
|
||||
|
||||
protected EditorColorsScheme getCurrentScheme() {
|
||||
return myOptions.getSelectedScheme();
|
||||
}
|
||||
|
||||
private JPanel createEditorFontPanel() {
|
||||
JPanel editorFontPanel = new JPanel(new GridBagLayout());
|
||||
Insets borderInsets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET,
|
||||
IdeBorderFactory.TITLED_BORDER_LEFT_INSET,
|
||||
0,
|
||||
IdeBorderFactory.TITLED_BORDER_RIGHT_INSET);
|
||||
editorFontPanel.setBorder(IdeBorderFactory.createTitledBorder(myTitle, false, borderInsets));
|
||||
|
||||
Insets insets = new Insets(0, 0, 5, 0);
|
||||
GridBag constraints = new GridBag().insets(insets);
|
||||
editorFontPanel.add(myOnlyMonospacedCheckBox, constraints);
|
||||
|
||||
insets.left = 8;
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.font.size")), constraints);
|
||||
|
||||
insets.left = 2;
|
||||
editorFontPanel.add(myEditorFontSizeField, constraints);
|
||||
|
||||
insets.left = 8;
|
||||
editorFontPanel.add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), constraints);
|
||||
|
||||
insets.left = 2;
|
||||
editorFontPanel.add(myLineSpacingField, constraints);
|
||||
|
||||
editorFontPanel.add(new JLabel(""), new GridBag().insets(insets).weightx(1).fillCellHorizontally().coverLine());
|
||||
|
||||
editorFontPanel.add(myFontsControl, new GridBag().weightx(1).weighty(1).fillCell().coverLine().insets(insets));
|
||||
|
||||
return editorFontPanel;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
|
||||
@@ -285,22 +406,29 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void showReadOnlyMessage(JComponent parent, final boolean sharedScheme) {
|
||||
if (!sharedScheme) {
|
||||
Messages.showMessageDialog(
|
||||
parent,
|
||||
ApplicationBundle.message("error.readonly.scheme.cannot.be.modified"),
|
||||
ApplicationBundle.message("title.cannot.modify.readonly.scheme"),
|
||||
Messages.getInformationIcon()
|
||||
);
|
||||
@Override
|
||||
public void addListener(ColorAndFontSettingsListener listener) {
|
||||
myDispatcher.addListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> processListOptions() {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
|
||||
private static class MyTextField extends JTextField {
|
||||
private MyTextField(int size) {
|
||||
super(size);
|
||||
}
|
||||
else {
|
||||
Messages.showMessageDialog(
|
||||
parent,
|
||||
ApplicationBundle.message("error.shared.scheme.cannot.be.modified"),
|
||||
ApplicationBundle.message("title.cannot.modify.readonly.scheme"),
|
||||
Messages.getInformationIcon()
|
||||
);
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,32 +478,13 @@ public class FontOptions extends JPanel implements OptionsPanel{
|
||||
// JRE has problems working with the font. Just skip.
|
||||
}
|
||||
}
|
||||
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onFontsInit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyTextField extends JTextField {
|
||||
private MyTextField(int size) {
|
||||
super(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(ColorAndFontSettingsListener listener) {
|
||||
myDispatcher.addListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> processListOptions() {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,15 +40,30 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, Schem
|
||||
Color getColor(ColorKey key);
|
||||
void setColor(ColorKey key, Color color);
|
||||
|
||||
int getEditorFontSize();
|
||||
void setEditorFontSize(int fontSize);
|
||||
|
||||
FontSize getQuickDocFontSize();
|
||||
void setQuickDocFontSize(@NotNull FontSize fontSize);
|
||||
/**
|
||||
* The IDE has allowed to configure only a single font family for a while. However, that doesn't handle a situation when
|
||||
* that font family is unable to display particular char - fallback font family was chosen randomly from the whole collection
|
||||
* of all registered fonts.
|
||||
* <p/>
|
||||
* Now it's possible to specify more than one font, i.e. directly indicated 'fallback fonts sequence' (see {@link FontPreferences}).
|
||||
* However, old single font-based API is still here in order to preserve backward compatibility ({@link #getEditorFontName()} and
|
||||
* {@link #getEditorFontSize()}). I.e. those methods are just re-written in order to use {@link FontPreferences} object exposed
|
||||
* by this method.
|
||||
*
|
||||
* @return font preferences to use
|
||||
*/
|
||||
@NotNull
|
||||
FontPreferences getFontPreferences();
|
||||
|
||||
String getEditorFontName();
|
||||
void setEditorFontName(String fontName);
|
||||
|
||||
|
||||
int getEditorFontSize();
|
||||
void setEditorFontSize(int fontSize);
|
||||
|
||||
FontSize getQuickDocFontSize();
|
||||
void setQuickDocFontSize(@NotNull FontSize fontSize);
|
||||
|
||||
Font getFont(EditorFontType key);
|
||||
void setFont(EditorFontType key, Font font);
|
||||
|
||||
@@ -57,6 +72,13 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, Schem
|
||||
|
||||
Object clone();
|
||||
|
||||
/**
|
||||
* @return console font preferences to use
|
||||
* @see #getFontPreferences()
|
||||
*/
|
||||
@NotNull
|
||||
FontPreferences getConsoleFontPreferences();
|
||||
|
||||
String getConsoleFontName();
|
||||
void setConsoleFontName(String fontName);
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.colors;
|
||||
|
||||
import com.intellij.openapi.options.FontSize;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility class which holds collection of font families and theirs sizes.
|
||||
* <p/>
|
||||
* The basic idea is to allow end-user to configure not a single font but fonts list instead - every time particular font is unable
|
||||
* to display particular char, next font is tried. This is an improvement over an old approach when it was possible to configure
|
||||
* only a single font family. Fallback fonts were chosen randomly when that font family was unable to display particular char then.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 12/20/12 9:37 PM
|
||||
*/
|
||||
public class FontPreferences {
|
||||
|
||||
@NonNls @NotNull public static final String DEFAULT_FONT_NAME = getDefaultFontName();
|
||||
public static final int DEFAULT_FONT_SIZE = FontSize.SMALL.getSize();
|
||||
|
||||
@NotNull private final TObjectIntHashMap<String> myFontSizes = new TObjectIntHashMap<String>();
|
||||
@NotNull private final List<String> myFontFamilies = ContainerUtilRt.newArrayList();
|
||||
|
||||
/**
|
||||
* Font size to use by default. Default value is {@link #DEFAULT_FONT_SIZE}.
|
||||
*/
|
||||
private int myTemplateFontSize = DEFAULT_FONT_SIZE;
|
||||
|
||||
public void clear() {
|
||||
myFontFamilies.clear();
|
||||
myFontSizes.clear();
|
||||
}
|
||||
|
||||
public void clearFonts() {
|
||||
myFontFamilies.clear();
|
||||
}
|
||||
|
||||
public boolean hasSize(@NotNull String fontName) {
|
||||
return myFontSizes.containsKey(fontName);
|
||||
}
|
||||
|
||||
public int getSize(@NotNull String fontFamily) {
|
||||
int result = myFontSizes.get(fontFamily);
|
||||
if (result <= 0) {
|
||||
result = myTemplateFontSize;
|
||||
}
|
||||
return result > 0 ? result : DEFAULT_FONT_SIZE;
|
||||
}
|
||||
|
||||
public void setSize(@NotNull String fontFamily, int size) {
|
||||
myFontSizes.put(fontFamily, size);
|
||||
myTemplateFontSize = size;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getFontFamilies() {
|
||||
return myFontFamilies;
|
||||
}
|
||||
|
||||
public void register(@NotNull String fontFamily, int size) {
|
||||
if (!myFontFamilies.contains(fontFamily)) {
|
||||
myFontFamilies.add(fontFamily);
|
||||
}
|
||||
setSize(fontFamily, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return first element of the {@link #getFontFamilies() registered font families} (if any);
|
||||
* {@link #DEFAULT_FONT_NAME} otherwise
|
||||
*/
|
||||
@NotNull
|
||||
public String getFontFamily() {
|
||||
return myFontFamilies.isEmpty() ? DEFAULT_FONT_NAME : myFontFamilies.get(0);
|
||||
}
|
||||
|
||||
public void addFontFamily(@NotNull String fontFamily) {
|
||||
if (!myFontFamilies.contains(fontFamily)) {
|
||||
myFontFamilies.add(fontFamily);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyTo(@NotNull final FontPreferences preferences) {
|
||||
preferences.myFontFamilies.clear();
|
||||
preferences.myFontFamilies.addAll(myFontFamilies);
|
||||
preferences.myFontSizes.clear();
|
||||
for (String fontFamily : myFontFamilies) {
|
||||
if (myFontSizes.containsKey(fontFamily)) {
|
||||
preferences.myFontSizes.put(fontFamily, myFontSizes.get(fontFamily));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myFontFamilies.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FontPreferences that = (FontPreferences)o;
|
||||
|
||||
if (!myFontFamilies.equals(that.myFontFamilies)) return false;
|
||||
for (String fontFamily : myFontFamilies) {
|
||||
if (myFontSizes.get(fontFamily) != that.myFontSizes.get(fontFamily)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDefaultFontName() {
|
||||
if (SystemInfo.isMacOSSnowLeopard) return "Menlo";
|
||||
if (SystemInfo.isXWindow) {
|
||||
for (Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) {
|
||||
if ("DejaVu Sans Mono".equals(font.getName())) {
|
||||
return font.getFontName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return "Monospaced";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class JBMovePanel extends JBPanel {
|
||||
protected final JButton myMoveLeftButton;
|
||||
protected final JButton myMoveAllLeftButton;
|
||||
protected final JButton myMoveRightButton;
|
||||
protected final JButton myMoveAllRightButton;
|
||||
@NotNull protected final JList myLeft;
|
||||
@NotNull protected final JList myRight;
|
||||
|
||||
protected enum ButtonType {MOVE_LEFT, MOVE_RIGHT, MOVE_ALL_LEFT, MOVE_ALL_RIGHT}
|
||||
|
||||
public JBMovePanel(@NotNull JList left, @NotNull JList right) {
|
||||
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||
assertModelIsEditable(left);
|
||||
assertModelIsEditable(right);
|
||||
myLeft = left;
|
||||
myRight = right;
|
||||
final JPanel buttonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE));
|
||||
buttonsPanel.add(myMoveLeftButton = createButton(ButtonType.MOVE_RIGHT));
|
||||
buttonsPanel.add(myMoveRightButton = createButton(ButtonType.MOVE_LEFT));
|
||||
buttonsPanel.add(myMoveAllLeftButton = createButton(ButtonType.MOVE_ALL_RIGHT));
|
||||
buttonsPanel.add(myMoveAllRightButton = createButton(ButtonType.MOVE_ALL_LEFT));
|
||||
final Dimension size = new Dimension(getButtonsWidth(), buttonsPanel.getPreferredSize().height);
|
||||
buttonsPanel.setPreferredSize(size);
|
||||
buttonsPanel.setMaximumSize(size);
|
||||
|
||||
add(new JBScrollPane(left));
|
||||
add(buttonsPanel);
|
||||
add(new JBScrollPane(right));
|
||||
}
|
||||
|
||||
private static void assertModelIsEditable(JList list) {
|
||||
assert list.getModel() instanceof DefaultListModel: String.format("List model should extends %s interface", DefaultListModel.class.getName());
|
||||
}
|
||||
|
||||
protected JButton createButton(@NotNull final ButtonType type) {
|
||||
final int size = 20;
|
||||
final JButton button = new JButton(getButtonText(type)) {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(getButtonsWidth(), size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMaximumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
};
|
||||
|
||||
button.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (type) {
|
||||
case MOVE_LEFT:
|
||||
doMoveLeft();
|
||||
break;
|
||||
case MOVE_RIGHT:
|
||||
doMoveRight();
|
||||
break;
|
||||
case MOVE_ALL_LEFT:
|
||||
doMoveAllLeft();
|
||||
break;
|
||||
case MOVE_ALL_RIGHT:
|
||||
doMoveAllRight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
protected int getButtonsWidth() {
|
||||
return 150;
|
||||
}
|
||||
|
||||
protected void doMoveRight() {
|
||||
move(myRight, myLeft);
|
||||
}
|
||||
|
||||
protected void doMoveLeft() {
|
||||
move(myLeft, myRight);
|
||||
}
|
||||
|
||||
protected void doMoveAllLeft() {
|
||||
moveAll(myLeft, myRight);
|
||||
}
|
||||
|
||||
protected void doMoveAllRight() {
|
||||
moveAll(myRight, myLeft);
|
||||
}
|
||||
|
||||
private static void move(JList to, JList from) {
|
||||
final Object[] values = from.getSelectedValues();
|
||||
final int[] indices = from.getSelectedIndices();
|
||||
for (int i = indices.length - 1; i >=0; i--) {
|
||||
((DefaultListModel)from.getModel()).remove(i);
|
||||
}
|
||||
for (Object value : values) {
|
||||
((DefaultListModel)to.getModel()).addElement(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void moveAll(JList to, JList from) {
|
||||
final DefaultListModel fromModel = (DefaultListModel)from.getModel();
|
||||
final DefaultListModel toModel = (DefaultListModel)to.getModel();
|
||||
while (fromModel.getSize() > 0) {
|
||||
toModel.addElement(fromModel.remove(0));
|
||||
}
|
||||
}
|
||||
|
||||
protected String getButtonText(@NotNull ButtonType type) {
|
||||
switch (type) {
|
||||
case MOVE_LEFT: return "Move <<";
|
||||
case MOVE_RIGHT: return "Move >>";
|
||||
case MOVE_ALL_LEFT: return "Move All <<";
|
||||
case MOVE_ALL_RIGHT: return "Move All >>";
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown button type: " + type);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
final JBMovePanel panel = new JBMovePanel(new JBList("asdas", "weqrwe", "ads12312", "aZSD23"),
|
||||
new JBList("123412", "as2341", "aaaaaaaaaaa", "ZZZZZZZZZZ", "12"));
|
||||
final JFrame test = new JFrame("Test");
|
||||
test.setContentPane(panel);
|
||||
test.setSize(500, 500);
|
||||
test.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
test.setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.application.options;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.DoubleClickListener;
|
||||
import com.intellij.ui.ListScrollingUtil;
|
||||
import com.intellij.ui.ListSpeedSearch;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.components.JBList;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
|
||||
public class SelectFontDialog extends DialogWrapper {
|
||||
private JList myFontList;
|
||||
private JCheckBox myShowMonospacedCheckbox;
|
||||
private final List<String> myFontNames;
|
||||
private final String myInitialFontName;
|
||||
private final List<String> myMonospacedFontNames;
|
||||
|
||||
public SelectFontDialog(Component parent, List<String> fontNames, String initialFontName, List<String> monospacedFontNames) {
|
||||
super(parent, true);
|
||||
myMonospacedFontNames = monospacedFontNames;
|
||||
setTitle(ApplicationBundle.message("title.select.font"));
|
||||
myFontNames = fontNames;
|
||||
myInitialFontName = initialFontName;
|
||||
init();
|
||||
}
|
||||
|
||||
protected JComponent createCenterPanel() {
|
||||
myShowMonospacedCheckbox = new JCheckBox(ApplicationBundle.message("checkbox.show.only.monospaced.fonts"));
|
||||
final boolean useOnlyMonospacedFonts = EditorColorsManager.getInstance().isUseOnlyMonospacedFonts();
|
||||
myFontList = new JBList();
|
||||
new ListSpeedSearch(myFontList);
|
||||
myFontList.setModel(new DefaultListModel());
|
||||
fillList(useOnlyMonospacedFonts);
|
||||
|
||||
new DoubleClickListener() {
|
||||
@Override
|
||||
protected boolean onDoubleClick(MouseEvent e) {
|
||||
doOKAction();
|
||||
return true;
|
||||
}
|
||||
}.installOn(myFontList);
|
||||
|
||||
myFontList.setCellRenderer(new MyListCellRenderer());
|
||||
|
||||
myShowMonospacedCheckbox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
boolean onlyMonospaced = myShowMonospacedCheckbox.isSelected();
|
||||
EditorColorsManager.getInstance().setUseOnlyMonospacedFonts(onlyMonospaced);
|
||||
String selection = (String) myFontList.getSelectedValue();
|
||||
fillList(onlyMonospaced);
|
||||
if (selection != null) {
|
||||
myFontList.setSelectedValue(selection, true);
|
||||
myFontList.ensureIndexIsVisible(myFontList.getSelectedIndex());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
panel.add(myShowMonospacedCheckbox, BorderLayout.NORTH);
|
||||
panel.add(ScrollPaneFactory.createScrollPane(myFontList), BorderLayout.CENTER);
|
||||
myShowMonospacedCheckbox.setSelected(useOnlyMonospacedFonts);
|
||||
myFontList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
setOKActionEnabled(myFontList.getSelectedValue() != null);
|
||||
}
|
||||
});
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void fillList(boolean onlyMonospaced) {
|
||||
DefaultListModel model = (DefaultListModel) myFontList.getModel();
|
||||
model.removeAllElements();
|
||||
for (String fontName : myFontNames) {
|
||||
if (!onlyMonospaced || myMonospacedFontNames.contains(fontName)) {
|
||||
model.addElement(fontName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
ListScrollingUtil.selectItem(myFontList, myInitialFontName);
|
||||
super.show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myFontList;
|
||||
}
|
||||
|
||||
public String getFontName() {
|
||||
return (String)myFontList.getSelectedValue();
|
||||
}
|
||||
|
||||
private static class MyListCellRenderer extends DefaultListCellRenderer {
|
||||
public Component getListCellRendererComponent(
|
||||
JList list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean isSelected,
|
||||
boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
String fontName = (String) value;
|
||||
c.setFont(new Font(fontName, Font.PLAIN, 14));
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.EditorSettings;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.EditorFontType;
|
||||
import com.intellij.openapi.editor.colors.FontPreferences;
|
||||
import com.intellij.openapi.editor.colors.impl.DelegateColorScheme;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.impl.EditorFactoryImpl;
|
||||
@@ -81,6 +82,12 @@ public class ConsoleViewUtil {
|
||||
return color == null ? super.getDefaultBackground() : color;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getFontPreferences() {
|
||||
return getConsoleFontPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEditorFontSize() {
|
||||
return getConsoleFontSize();
|
||||
|
||||
@@ -27,8 +27,8 @@ import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.options.FontSize;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
@@ -42,50 +42,49 @@ import java.util.List;
|
||||
public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
|
||||
private static final int CURR_VERSION = 124;
|
||||
|
||||
private static final FontSize DEFAULT_FONT_SIZE = FontSize.SMALL;
|
||||
|
||||
protected EditorColorsScheme myParentScheme;
|
||||
|
||||
protected int myEditorFontSize;
|
||||
private static final FontSize DEFAULT_FONT_SIZE = FontSize.SMALL;
|
||||
|
||||
protected EditorColorsScheme myParentScheme;
|
||||
|
||||
protected FontSize myQuickDocFontSize = DEFAULT_FONT_SIZE;
|
||||
protected float myLineSpacing;
|
||||
|
||||
private final Map<EditorFontType, Font> myFonts = new EnumMap<EditorFontType, Font>(EditorFontType.class);
|
||||
private String myEditorFontName;
|
||||
@NotNull private final Map<EditorFontType, Font> myFonts = new EnumMap<EditorFontType, Font>(EditorFontType.class);
|
||||
@NotNull private final FontPreferences myFontPreferences = new FontPreferences();
|
||||
@NotNull private final FontPreferences myConsoleFontPreferences = new FontPreferences();
|
||||
|
||||
private String myFallbackFontName;
|
||||
private String mySchemeName;
|
||||
|
||||
private String myConsoleFontName;
|
||||
private int myConsoleFontSize = -1;
|
||||
private float myConsoleLineSpacing = -1;
|
||||
|
||||
// version influences XML format and triggers migration
|
||||
private int myVersion = CURR_VERSION;
|
||||
|
||||
protected Map<ColorKey, Color> myColorsMap = new HashMap<ColorKey, Color>();
|
||||
protected Map<TextAttributesKey, TextAttributes> myAttributesMap = new HashMap<TextAttributesKey, TextAttributes>();
|
||||
protected Map<ColorKey, Color> myColorsMap = ContainerUtilRt.newHashMap();
|
||||
protected Map<TextAttributesKey, TextAttributes> myAttributesMap = ContainerUtilRt.newHashMap();
|
||||
|
||||
@NonNls private static final String DEFAULT_FONT_NAME = getDefaultFontName();
|
||||
@NonNls private static final String EDITOR_FONT_NAME = "EDITOR_FONT_NAME";
|
||||
@NonNls private static final String EDITOR_FONT = "font";
|
||||
@NonNls private static final String CONSOLE_FONT = "console-font";
|
||||
@NonNls private static final String EDITOR_FONT_NAME = "EDITOR_FONT_NAME";
|
||||
@NonNls private static final String CONSOLE_FONT_NAME = "CONSOLE_FONT_NAME";
|
||||
@NonNls protected static final String SCHEME_NAME = "SCHEME_NAME";
|
||||
protected DefaultColorSchemesManager myDefaultColorSchemesManager;
|
||||
private Color myDeprecatedBackgroundColor = null;
|
||||
@NonNls private static final String SCHEME_ELEMENT = "scheme";
|
||||
@NonNls public static final String NAME_ATTR = "name";
|
||||
@NonNls private static final String VERSION_ATTR = "version";
|
||||
@NonNls private static final String DEFAULT_SCHEME_ATTR = "default_scheme";
|
||||
@NonNls private static final String PARENT_SCHEME_ATTR = "parent_scheme";
|
||||
@NonNls private static final String OPTION_ELEMENT = "option";
|
||||
@NonNls private static final String COLORS_ELEMENT = "colors";
|
||||
@NonNls private static final String ATTRIBUTES_ELEMENT = "attributes";
|
||||
@NonNls private static final String VALUE_ELEMENT = "value";
|
||||
@NonNls private static final String BACKGROUND_COLOR_NAME = "BACKGROUND";
|
||||
@NonNls private static final String LINE_SPACING = "LINE_SPACING";
|
||||
@NonNls private static final String CONSOLE_LINE_SPACING = "CONSOLE_LINE_SPACING";
|
||||
@NonNls private static final String EDITOR_FONT_SIZE = "EDITOR_FONT_SIZE";
|
||||
@NonNls private static final String CONSOLE_FONT_SIZE = "CONSOLE_FONT_SIZE";
|
||||
private Color myDeprecatedBackgroundColor = null;
|
||||
@NonNls private static final String SCHEME_ELEMENT = "scheme";
|
||||
@NonNls public static final String NAME_ATTR = "name";
|
||||
@NonNls private static final String VERSION_ATTR = "version";
|
||||
@NonNls private static final String DEFAULT_SCHEME_ATTR = "default_scheme";
|
||||
@NonNls private static final String PARENT_SCHEME_ATTR = "parent_scheme";
|
||||
@NonNls private static final String OPTION_ELEMENT = "option";
|
||||
@NonNls private static final String COLORS_ELEMENT = "colors";
|
||||
@NonNls private static final String ATTRIBUTES_ELEMENT = "attributes";
|
||||
@NonNls private static final String VALUE_ELEMENT = "value";
|
||||
@NonNls private static final String BACKGROUND_COLOR_NAME = "BACKGROUND";
|
||||
@NonNls private static final String LINE_SPACING = "LINE_SPACING";
|
||||
@NonNls private static final String CONSOLE_LINE_SPACING = "CONSOLE_LINE_SPACING";
|
||||
@NonNls private static final String EDITOR_FONT_SIZE = "EDITOR_FONT_SIZE";
|
||||
@NonNls private static final String CONSOLE_FONT_SIZE = "CONSOLE_FONT_SIZE";
|
||||
@NonNls private static final String EDITOR_QUICK_JAVADOC_FONT_SIZE = "EDITOR_QUICK_DOC_FONT_SIZE";
|
||||
|
||||
protected AbstractColorsScheme(EditorColorsScheme parentScheme, DefaultColorSchemesManager defaultColorSchemesManager) {
|
||||
@@ -125,12 +124,10 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
public abstract Object clone();
|
||||
|
||||
public void copyTo(AbstractColorsScheme newScheme) {
|
||||
newScheme.myEditorFontSize = myEditorFontSize;
|
||||
myFontPreferences.copyTo(newScheme.myFontPreferences);
|
||||
newScheme.myLineSpacing = myLineSpacing;
|
||||
newScheme.setEditorFontName(getEditorFontName());
|
||||
newScheme.myQuickDocFontSize = myQuickDocFontSize;
|
||||
newScheme.myConsoleFontName = myConsoleFontName;
|
||||
newScheme.myConsoleFontSize = myConsoleFontSize;
|
||||
myConsoleFontPreferences.copyTo(newScheme.myConsoleFontPreferences);
|
||||
newScheme.myConsoleLineSpacing = myConsoleLineSpacing;
|
||||
|
||||
final Set<EditorFontType> types = myFonts.keySet();
|
||||
@@ -146,13 +143,14 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
|
||||
@Override
|
||||
public void setEditorFontName(String fontName) {
|
||||
myEditorFontName = fontName;
|
||||
myFontPreferences.clear();
|
||||
myFontPreferences.register(fontName, getEditorFontSize());
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEditorFontSize(int fontSize) {
|
||||
myEditorFontSize = fontSize;
|
||||
myFontPreferences.setSize(getEditorFontName(), fontSize);
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@@ -176,17 +174,23 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
mySchemeName = name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getFontPreferences() {
|
||||
return myFontPreferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEditorFontName() {
|
||||
if (myFallbackFontName != null) {
|
||||
return myFallbackFontName;
|
||||
}
|
||||
return myEditorFontName == null ? DEFAULT_FONT_NAME : myEditorFontName;
|
||||
return myFontPreferences.getFontFamily();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEditorFontSize() {
|
||||
return myEditorFontSize;
|
||||
return myFontPreferences.getSize(getEditorFontName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -207,7 +211,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
|
||||
Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize);
|
||||
if (plainFont.getFamily().equals("Dialog") && !editorFontName.equals("Dialog")) {
|
||||
editorFontName = myParentScheme != null ? myParentScheme.getEditorFontName() : DEFAULT_FONT_NAME;
|
||||
editorFontName = myParentScheme != null ? myParentScheme.getEditorFontName() : FontPreferences.DEFAULT_FONT_NAME;
|
||||
myFallbackFontName = editorFontName;
|
||||
plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize);
|
||||
}
|
||||
@@ -272,13 +276,20 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
|
||||
for (final Object o : node.getChildren()) {
|
||||
Element childNode = (Element)o;
|
||||
if (OPTION_ELEMENT.equals(childNode.getName())) {
|
||||
String childName = childNode.getName();
|
||||
if (OPTION_ELEMENT.equals(childName)) {
|
||||
readSettings(childNode);
|
||||
}
|
||||
else if (COLORS_ELEMENT.equals(childNode.getName())) {
|
||||
else if (EDITOR_FONT.equals(childName)) {
|
||||
readFontSettings(childNode, myFontPreferences);
|
||||
}
|
||||
else if (CONSOLE_FONT.equals(childName)) {
|
||||
readFontSettings(childNode, myConsoleFontPreferences);
|
||||
}
|
||||
else if (COLORS_ELEMENT.equals(childName)) {
|
||||
readColors(childNode);
|
||||
}
|
||||
else if (ATTRIBUTES_ELEMENT.equals(childNode.getName())) {
|
||||
else if (ATTRIBUTES_ELEMENT.equals(childName)) {
|
||||
readAttributes(childNode);
|
||||
}
|
||||
}
|
||||
@@ -365,7 +376,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
myLineSpacing = Float.parseFloat(value);
|
||||
}
|
||||
else if (EDITOR_FONT_SIZE.equals(name)) {
|
||||
myEditorFontSize = Integer.parseInt(value);
|
||||
setEditorFontSize(Integer.parseInt(value));
|
||||
}
|
||||
else if (EDITOR_FONT_NAME.equals(name)) {
|
||||
setEditorFontName(value);
|
||||
@@ -384,6 +395,32 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
}
|
||||
}
|
||||
|
||||
private static void readFontSettings(@NotNull Element element, @NotNull FontPreferences preferences) {
|
||||
List children = element.getChildren(OPTION_ELEMENT);
|
||||
String fontFamily = null;
|
||||
int size = -1;
|
||||
for (Object child : children) {
|
||||
Element e = (Element)child;
|
||||
if (EDITOR_FONT_NAME.equals(e.getAttributeValue(NAME_ATTR))) {
|
||||
fontFamily = e.getAttributeValue(VALUE_ELEMENT);
|
||||
}
|
||||
else if (EDITOR_FONT_SIZE.equals(e.getAttributeValue(NAME_ATTR))) {
|
||||
try {
|
||||
size = Integer.parseInt(e.getAttributeValue(VALUE_ELEMENT));
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fontFamily != null && size > 1) {
|
||||
preferences.register(fontFamily, size);
|
||||
}
|
||||
else if (fontFamily != null) {
|
||||
preferences.addFontFamily(fontFamily);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element parentNode) throws WriteExternalException {
|
||||
parentNode.setAttribute(NAME_ATTR, getName());
|
||||
@@ -398,23 +435,37 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
element.setAttribute(VALUE_ELEMENT, String.valueOf(getLineSpacing()));
|
||||
parentNode.addContent(element);
|
||||
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE);
|
||||
element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize()));
|
||||
parentNode.addContent(element);
|
||||
|
||||
if (!Comparing.strEqual(getConsoleFontName(), getEditorFontName())) {
|
||||
// IJ has used a 'single customizable font' mode for ages. That's why we want to support that format now, when it's possible
|
||||
// to specify fonts sequence (see getFontPreferences()), there are big chances that many clients still will use a single font.
|
||||
// That's why we want to use old format when zero or one font is selected and 'extended' format otherwise.
|
||||
boolean useOldFontFormat = myFontPreferences.getFontFamilies().size() <= 1;
|
||||
if (useOldFontFormat) {
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, CONSOLE_FONT_NAME);
|
||||
element.setAttribute(VALUE_ELEMENT, getConsoleFontName());
|
||||
element.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE);
|
||||
element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize()));
|
||||
parentNode.addContent(element);
|
||||
}
|
||||
else {
|
||||
writeFontPreferences(EDITOR_FONT, parentNode, myFontPreferences);
|
||||
}
|
||||
|
||||
if (getConsoleFontSize() != getEditorFontSize()) {
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, CONSOLE_FONT_SIZE);
|
||||
element.setAttribute(VALUE_ELEMENT, Integer.toString(getConsoleFontSize()));
|
||||
parentNode.addContent(element);
|
||||
if (!myFontPreferences.equals(myConsoleFontPreferences)) {
|
||||
if (myConsoleFontPreferences.getFontFamilies().size() <= 1) {
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, CONSOLE_FONT_NAME);
|
||||
element.setAttribute(VALUE_ELEMENT, getConsoleFontName());
|
||||
parentNode.addContent(element);
|
||||
|
||||
if (getConsoleFontSize() != getEditorFontSize()) {
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, CONSOLE_FONT_SIZE);
|
||||
element.setAttribute(VALUE_ELEMENT, Integer.toString(getConsoleFontSize()));
|
||||
parentNode.addContent(element);
|
||||
}
|
||||
}
|
||||
else {
|
||||
writeFontPreferences(CONSOLE_FONT, parentNode, myConsoleFontPreferences);
|
||||
}
|
||||
}
|
||||
|
||||
if (getConsoleLineSpacing() != getLineSpacing()) {
|
||||
@@ -431,10 +482,12 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
parentNode.addContent(element);
|
||||
}
|
||||
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
|
||||
element.setAttribute(VALUE_ELEMENT, getEditorFontName());
|
||||
parentNode.addContent(element);
|
||||
if (useOldFontFormat) {
|
||||
element = new Element(OPTION_ELEMENT);
|
||||
element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
|
||||
element.setAttribute(VALUE_ELEMENT, getEditorFontName());
|
||||
parentNode.addContent(element);
|
||||
}
|
||||
|
||||
Element colorElements = new Element(COLORS_ELEMENT);
|
||||
Element attrElements = new Element(ATTRIBUTES_ELEMENT);
|
||||
@@ -446,6 +499,23 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
parentNode.addContent(attrElements);
|
||||
}
|
||||
|
||||
private static void writeFontPreferences(@NotNull String key, @NotNull Element parent, @NotNull FontPreferences preferences) {
|
||||
for (String fontFamily : preferences.getFontFamilies()) {
|
||||
Element element = new Element(key);
|
||||
Element e = new Element(OPTION_ELEMENT);
|
||||
e.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
|
||||
e.setAttribute(VALUE_ELEMENT, fontFamily);
|
||||
element.addContent(e);
|
||||
|
||||
e = new Element(OPTION_ELEMENT);
|
||||
e.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE);
|
||||
e.setAttribute(VALUE_ELEMENT, String.valueOf(preferences.getSize(fontFamily)));
|
||||
element.addContent(e);
|
||||
|
||||
parent.addContent(element);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean haveToWrite(final TextAttributesKey key, final TextAttributes value, final TextAttributes defaultAttribute) {
|
||||
if (key.getFallbackAttributeKey() != null && value.isFallbackEnabled()) return false;
|
||||
boolean hasDefaultValue = value.equals(defaultAttribute);
|
||||
@@ -507,30 +577,37 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getConsoleFontPreferences() {
|
||||
return myConsoleFontPreferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConsoleFontName() {
|
||||
if (myConsoleFontName == null) {
|
||||
return getEditorFontName();
|
||||
}
|
||||
return myConsoleFontName;
|
||||
return myConsoleFontPreferences.getFontFamily();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConsoleFontName(String fontName) {
|
||||
myConsoleFontName = fontName;
|
||||
myConsoleFontPreferences.clear();
|
||||
myConsoleFontPreferences.register(fontName, getConsoleFontSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConsoleFontSize() {
|
||||
if (myConsoleFontSize == -1) {
|
||||
String font = getConsoleFontName();
|
||||
if (myConsoleFontPreferences.hasSize(font)) {
|
||||
return myConsoleFontPreferences.getSize(font);
|
||||
}
|
||||
else {
|
||||
return getEditorFontSize();
|
||||
}
|
||||
return myConsoleFontSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConsoleFontSize(int fontSize) {
|
||||
myConsoleFontSize = fontSize;
|
||||
myConsoleFontPreferences.setSize(getConsoleFontName(), fontSize);
|
||||
initFonts();
|
||||
}
|
||||
|
||||
@@ -548,18 +625,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme {
|
||||
myConsoleLineSpacing = lineSpacing;
|
||||
}
|
||||
|
||||
private static String getDefaultFontName() {
|
||||
if (SystemInfo.isMacOSSnowLeopard) return "Menlo";
|
||||
if (SystemInfo.isXWindow) {
|
||||
for (Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) {
|
||||
if ("DejaVu Sans Mono".equals(font.getName())) {
|
||||
return font.getFontName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return "Monospaced";
|
||||
}
|
||||
|
||||
protected TextAttributes getFallbackAttributes(TextAttributesKey fallbackKey) {
|
||||
if (fallbackKey == null) return null;
|
||||
if (myAttributesMap.containsKey(fallbackKey)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.colors.impl;
|
||||
|
||||
import com.intellij.openapi.editor.colors.ColorKey;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.EditorFontType;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.colors.*;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.options.FontSize;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
@@ -81,6 +78,12 @@ public abstract class DelegateColorScheme implements EditorColorsScheme {
|
||||
myDelegate.setColor(key, color);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getFontPreferences() {
|
||||
return myDelegate.getFontPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEditorFontSize() {
|
||||
return myDelegate.getEditorFontSize();
|
||||
@@ -149,6 +152,12 @@ public abstract class DelegateColorScheme implements EditorColorsScheme {
|
||||
return myDelegate.clone();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getConsoleFontPreferences() {
|
||||
return myDelegate.getConsoleFontPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConsoleFontName() {
|
||||
return myDelegate.getConsoleFontName();
|
||||
|
||||
@@ -509,7 +509,7 @@ public class EditorUtil {
|
||||
|
||||
public static FontInfo fontForChar(final char c, @JdkConstants.FontStyle int style, @NotNull Editor editor) {
|
||||
EditorColorsScheme colorsScheme = editor.getColorsScheme();
|
||||
return ComplementaryFontsRegistry.getFontAbleToDisplay(c, colorsScheme.getEditorFontSize(), style, colorsScheme.getEditorFontName());
|
||||
return ComplementaryFontsRegistry.getFontAbleToDisplay(c, style, colorsScheme.getFontPreferences());
|
||||
}
|
||||
|
||||
public static int charWidth(char c, @JdkConstants.FontStyle int fontType, @NotNull Editor editor) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,12 +18,14 @@ package com.intellij.openapi.editor.impl;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ide.ui.UISettingsListener;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.colors.FontPreferences;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
@@ -140,8 +142,43 @@ public class ComplementaryFontsRegistry {
|
||||
boolean found = ourStyledFontNames.contains(styledFamilyName);
|
||||
return Pair.create(found ? styledFamilyName : familyName, found ? Font.PLAIN : style);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FontInfo getFontAbleToDisplay(char c, @JdkConstants.FontStyle int style, @NotNull FontPreferences preferences) {
|
||||
boolean tryDefaultFont = true;
|
||||
List<String> fontFamilies = preferences.getFontFamilies();
|
||||
FontInfo result;
|
||||
for (String fontFamily : fontFamilies) {
|
||||
result = doGetFontAbleToDisplay(c, preferences.getSize(fontFamily), style, fontFamily);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
tryDefaultFont &= !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily);
|
||||
}
|
||||
int size = FontPreferences.DEFAULT_FONT_SIZE;
|
||||
if (!fontFamilies.isEmpty()) {
|
||||
size = preferences.getSize(fontFamilies.get(0));
|
||||
}
|
||||
if (tryDefaultFont) {
|
||||
result = doGetFontAbleToDisplay(c, size, style, FontPreferences.DEFAULT_FONT_NAME);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return doGetFontAbleToDisplay(c, size, style);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FontInfo getFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) {
|
||||
FontInfo result = doGetFontAbleToDisplay(c, size, style, defaultFontFamily);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return doGetFontAbleToDisplay(c, size, style);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FontInfo doGetFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) {
|
||||
synchronized (lock) {
|
||||
Pair<String, Integer> p = fontFamily(defaultFontFamily, style);
|
||||
if (ourSharedKeyInstance.mySize == size &&
|
||||
@@ -152,7 +189,7 @@ public class ComplementaryFontsRegistry {
|
||||
( c < 128 ||
|
||||
ourSharedDefaultFont.canDisplay(c)
|
||||
)
|
||||
) {
|
||||
) {
|
||||
return ourSharedDefaultFont;
|
||||
}
|
||||
|
||||
@@ -171,8 +208,16 @@ public class ComplementaryFontsRegistry {
|
||||
if (c < 128 || defaultFont.canDisplay(c)) {
|
||||
return defaultFont;
|
||||
}
|
||||
|
||||
if (ourUndisplayableChars.contains(c)) return defaultFont;
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FontInfo doGetFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style) {
|
||||
synchronized (lock) {
|
||||
if (ourUndisplayableChars.contains(c)) return ourSharedDefaultFont;
|
||||
|
||||
final Collection<FontInfo> descriptors = ourUsedFonts.values();
|
||||
for (FontInfo font : descriptors) {
|
||||
@@ -193,7 +238,7 @@ public class ComplementaryFontsRegistry {
|
||||
|
||||
ourUndisplayableChars.add(c);
|
||||
|
||||
return defaultFont;
|
||||
return ourSharedDefaultFont;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.Producer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
@@ -5683,13 +5684,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
private class MyColorSchemeDelegate implements EditorColorsScheme {
|
||||
private final HashMap<TextAttributesKey, TextAttributes> myOwnAttributes = new HashMap<TextAttributesKey, TextAttributes>();
|
||||
private final HashMap<ColorKey, Color> myOwnColors = new HashMap<ColorKey, Color>();
|
||||
|
||||
private final FontPreferences myFontPreferences = new FontPreferences();
|
||||
private final Map<TextAttributesKey, TextAttributes> myOwnAttributes = ContainerUtilRt.newHashMap();
|
||||
private final Map<ColorKey, Color> myOwnColors = ContainerUtilRt.newHashMap();
|
||||
private final EditorColorsScheme myCustomGlobalScheme;
|
||||
private Map<EditorFontType, Font> myFontsMap = null;
|
||||
private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
|
||||
private int myFontSize = -1;
|
||||
private String myFaceName = null;
|
||||
private Map<EditorFontType, Font> myFontsMap = null;
|
||||
private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
|
||||
private int myFontSize = -1;
|
||||
private String myFaceName = null;
|
||||
private EditorColorsScheme myGlobalScheme;
|
||||
|
||||
private MyColorSchemeDelegate(@Nullable final EditorColorsScheme globalScheme) {
|
||||
@@ -5711,6 +5714,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
String editorFontName = getEditorFontName();
|
||||
int editorFontSize = getEditorFontSize();
|
||||
|
||||
myFontPreferences.clear();
|
||||
myFontPreferences.register(editorFontName, editorFontSize);
|
||||
|
||||
myFontsMap = new EnumMap<EditorFontType, Font>(EditorFontType.class);
|
||||
|
||||
Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize);
|
||||
@@ -5796,6 +5802,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myGlobalScheme.setQuickDocFontSize(fontSize);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getFontPreferences() {
|
||||
return myFontPreferences.getFontFamilies().isEmpty() ? getGlobal().getFontPreferences() : myFontPreferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEditorFontName() {
|
||||
if (myFaceName == null) {
|
||||
@@ -5858,6 +5870,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myMaxFontSize = Math.max(OptionsConstants.MAX_EDITOR_FONT_SIZE, globalFontSize);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FontPreferences getConsoleFontPreferences() {
|
||||
return getGlobal().getConsoleFontPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConsoleFontName() {
|
||||
return getGlobal().getConsoleFontName();
|
||||
@@ -6282,7 +6300,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
for (
|
||||
FoldRegion region = myFoldingModel.getCollapsedRegionAtOffset(endOffset);
|
||||
region != null && endOffset < myDocument.getTextLength();
|
||||
region = myFoldingModel.getCollapsedRegionAtOffset(endOffset)) {
|
||||
region = myFoldingModel.getCollapsedRegionAtOffset(endOffset))
|
||||
{
|
||||
final int lineNumber = myDocument.getLineNumber(region.getEndOffset());
|
||||
endOffset = myDocument.getLineEndOffset(lineNumber);
|
||||
}
|
||||
@@ -6583,7 +6602,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int x,
|
||||
int y,
|
||||
Color color,
|
||||
@NotNull FontInfo fontInfo) {
|
||||
@NotNull FontInfo fontInfo)
|
||||
{
|
||||
drawCharsCached(g, data, start, end, x, y, fontInfo, color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionButton;
|
||||
import com.intellij.openapi.actionSystem.impl.PresentationFactory;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.ListUtil;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A UI control which consists of two lists with ability to move elements between them.
|
||||
* <p/>
|
||||
* It looks as <a href="http://openfaces.org/documentation/developersGuide/twolistselection.html">here</a>.
|
||||
*
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class JBMovePanel extends JBPanel {
|
||||
|
||||
public static final String MOVE_PANEL_PLACE = "MOVE_PANEL";
|
||||
|
||||
public static final InsertPositionStrategy ANCHORING_SELECTION = new InsertPositionStrategy() {
|
||||
@Override
|
||||
public int getInsertionIndex(@NotNull Object data, @NotNull JList list) {
|
||||
int index = list.getSelectedIndex();
|
||||
DefaultListModel model = (DefaultListModel)list.getModel();
|
||||
return index < 0 ? model.getSize() : index + 1;
|
||||
}
|
||||
};
|
||||
|
||||
public static final InsertPositionStrategy NATURAL_ORDER = new InsertPositionStrategy() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int getInsertionIndex(@NotNull Object data, @NotNull JList list) {
|
||||
Enumeration elements = ((DefaultListModel)list.getModel()).elements();
|
||||
int index = 0;
|
||||
while (elements.hasMoreElements()) {
|
||||
Object e = elements.nextElement();
|
||||
// DefaultListModel is type-aware only since java7, so, use raw types until we're on java6.
|
||||
if (((Comparable)e).compareTo(data) >= 0) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull private final Map<ButtonType, ActionButton> myButtons = new EnumMap<ButtonType, ActionButton>(ButtonType.class);
|
||||
|
||||
@NotNull private final ListPanel myLeftPanel = new ListPanel();
|
||||
@NotNull private final ListPanel myRightPanel = new ListPanel();
|
||||
|
||||
@NotNull protected final JList myLeftList;
|
||||
@NotNull protected final JList myRightList;
|
||||
@NotNull protected final ActionButton myLeftButton;
|
||||
@NotNull protected final ActionButton myAllLeftButton;
|
||||
@NotNull protected final ActionButton myRightButton;
|
||||
@NotNull protected final ActionButton myAllRightButton;
|
||||
@NotNull protected final ActionButton myUpButton;
|
||||
@NotNull protected final ActionButton myDownButton;
|
||||
|
||||
@NotNull private InsertPositionStrategy myLeftInsertionStrategy = ANCHORING_SELECTION;
|
||||
@NotNull private InsertPositionStrategy myRightInsertionStrategy = ANCHORING_SELECTION;
|
||||
|
||||
private boolean myActivePreferredSizeProcessing;
|
||||
|
||||
public enum ButtonType {LEFT, RIGHT, ALL_LEFT, ALL_RIGHT}
|
||||
|
||||
public JBMovePanel(@NotNull JList left, @NotNull JList right) {
|
||||
super(new GridBagLayout());
|
||||
assertModelIsEditable(left);
|
||||
assertModelIsEditable(right);
|
||||
myLeftList = left;
|
||||
myRightList = right;
|
||||
|
||||
final JPanel leftRightButtonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE));
|
||||
leftRightButtonsPanel.add(myRightButton = createButton(ButtonType.RIGHT));
|
||||
leftRightButtonsPanel.add(myAllRightButton = createButton(ButtonType.ALL_RIGHT));
|
||||
leftRightButtonsPanel.add(myLeftButton = createButton(ButtonType.LEFT));
|
||||
leftRightButtonsPanel.add(myAllLeftButton = createButton(ButtonType.ALL_LEFT));
|
||||
|
||||
myUpButton = createButton(new UpAction());
|
||||
myDownButton = createButton(new DownAction());
|
||||
final JPanel upDownButtonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE));
|
||||
upDownButtonsPanel.add(myUpButton);
|
||||
upDownButtonsPanel.add(myDownButton);
|
||||
|
||||
MouseListener mouseListener = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() != 2 || e.getButton() != MouseEvent.BUTTON1) {
|
||||
return;
|
||||
}
|
||||
if (e.getSource() == myLeftList) {
|
||||
doRight();
|
||||
}
|
||||
else if (e.getSource() == myRightList) {
|
||||
doLeft();
|
||||
}
|
||||
}
|
||||
};
|
||||
myLeftList.addMouseListener(mouseListener);
|
||||
myRightList.addMouseListener(mouseListener);
|
||||
|
||||
GridBag listConstraints = new GridBag().weightx(1).weighty(1).fillCell();
|
||||
GridBag buttonConstraints = new GridBag().anchor(GridBagConstraints.CENTER);
|
||||
myLeftPanel.add(ScrollPaneFactory.createScrollPane(left), listConstraints);
|
||||
add(myLeftPanel, listConstraints);
|
||||
add(leftRightButtonsPanel, buttonConstraints);
|
||||
myRightPanel.add(ScrollPaneFactory.createScrollPane(right), listConstraints);
|
||||
add(myRightPanel, listConstraints);
|
||||
add(upDownButtonsPanel, buttonConstraints);
|
||||
}
|
||||
|
||||
private static void assertModelIsEditable(@NotNull JList list) {
|
||||
assert list.getModel() instanceof DefaultListModel : String
|
||||
.format("List model should extends %s interface", DefaultListModel.class.getName());
|
||||
}
|
||||
|
||||
public void setShowButtons(@NotNull ButtonType... types) {
|
||||
for (ActionButton button : myButtons.values()) {
|
||||
button.setVisible(false);
|
||||
}
|
||||
for (ButtonType type : types) {
|
||||
myButtons.get(type).setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListLabels(@NotNull String left, @NotNull String right) {
|
||||
// Border insets are used as a component insets (see JComponent.getInsets()). That's why an ugly bottom inset is used when
|
||||
// we create a border with default insets. That is the reason why we explicitly specify bottom inset as zero.
|
||||
Insets insets = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET,
|
||||
IdeBorderFactory.TITLED_BORDER_LEFT_INSET,
|
||||
0,
|
||||
IdeBorderFactory.TITLED_BORDER_RIGHT_INSET);
|
||||
myLeftPanel.setBorder(IdeBorderFactory.createTitledBorder(left, false, insets));
|
||||
myRightPanel.setBorder(IdeBorderFactory.createTitledBorder(right, false, insets));
|
||||
}
|
||||
|
||||
public void setLeftInsertionStrategy(@NotNull InsertPositionStrategy leftInsertionStrategy) {
|
||||
myLeftInsertionStrategy = leftInsertionStrategy;
|
||||
}
|
||||
|
||||
// Commented to preserve green code policy until this method is not used. Uncomment when necessary.
|
||||
//public void setRightInsertionStrategy(@NotNull InsertPositionStrategy rightInsertionStrategy) {
|
||||
// myRightInsertionStrategy = rightInsertionStrategy;
|
||||
//}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
myLeftList.setEnabled(enabled);
|
||||
myRightList.setEnabled(enabled);
|
||||
for (ActionButton button : myButtons.values()) {
|
||||
button.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ActionButton createButton(@NotNull final ButtonType type) {
|
||||
final AnAction action;
|
||||
switch (type) {
|
||||
case LEFT:
|
||||
action = new LeftAction();
|
||||
break;
|
||||
case RIGHT:
|
||||
action = new RightAction();
|
||||
break;
|
||||
case ALL_LEFT:
|
||||
action = new AllLeftAction();
|
||||
break;
|
||||
case ALL_RIGHT:
|
||||
action = new AllRightAction();
|
||||
break;
|
||||
default: throw new IllegalArgumentException("Unsupported button type: " + type);
|
||||
}
|
||||
|
||||
|
||||
ActionButton button = createButton(action);
|
||||
myButtons.put(type, button);
|
||||
return button;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ActionButton createButton(@NotNull final AnAction action) {
|
||||
PresentationFactory presentationFactory = new PresentationFactory();
|
||||
Icon icon = AllIcons.Actions.AllLeft;
|
||||
Dimension size = new Dimension(icon.getIconWidth(), icon.getIconHeight());
|
||||
return new ActionButton(action, presentationFactory.getPresentation(action), MOVE_PANEL_PLACE, size);
|
||||
}
|
||||
|
||||
protected void doRight() {
|
||||
moveBetween(myRightList, myRightInsertionStrategy, myLeftList);
|
||||
}
|
||||
|
||||
protected void doLeft() {
|
||||
moveBetween(myLeftList, myLeftInsertionStrategy, myRightList);
|
||||
}
|
||||
|
||||
protected void doAllLeft() {
|
||||
moveAllBetween(myLeftList, myRightList);
|
||||
}
|
||||
|
||||
protected void doAllRight() {
|
||||
moveAllBetween(myRightList, myLeftList);
|
||||
}
|
||||
|
||||
private static void moveBetween(@NotNull JList to, @NotNull InsertPositionStrategy strategy, @NotNull JList from) {
|
||||
final int[] indices = from.getSelectedIndices();
|
||||
if (indices.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Object[] values = from.getSelectedValues();
|
||||
for (int i = indices.length - 1; i >= 0; i--) {
|
||||
((DefaultListModel)from.getModel()).remove(indices[i]);
|
||||
}
|
||||
if (from.getModel().getSize() > 0) {
|
||||
int newSelectionIndex = indices[0];
|
||||
newSelectionIndex = Math.min(from.getModel().getSize() - 1, newSelectionIndex);
|
||||
from.setSelectedIndex(newSelectionIndex);
|
||||
}
|
||||
|
||||
to.clearSelection();
|
||||
DefaultListModel toModel = (DefaultListModel)to.getModel();
|
||||
int newSelectionIndex = -1;
|
||||
for (Object value : values) {
|
||||
if (!toModel.contains(value)) {
|
||||
int i = strategy.getInsertionIndex(value, to);
|
||||
if (newSelectionIndex < 0) {
|
||||
newSelectionIndex = i;
|
||||
}
|
||||
toModel.add(i, value);
|
||||
to.addSelectionInterval(i, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void moveAllBetween(@NotNull JList to, @NotNull JList from) {
|
||||
final DefaultListModel fromModel = (DefaultListModel)from.getModel();
|
||||
final DefaultListModel toModel = (DefaultListModel)to.getModel();
|
||||
while (fromModel.getSize() > 0) {
|
||||
Object element = fromModel.remove(0);
|
||||
if (!toModel.contains(element)) {
|
||||
toModel.addElement(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
final JBMovePanel panel = new JBMovePanel(new JBList("asdas", "weqrwe", "ads12312", "aZSD23"),
|
||||
new JBList("123412", "as2341", "aaaaaaaaaaa", "ZZZZZZZZZZ", "12"));
|
||||
final JFrame test = new JFrame("Test");
|
||||
test.setContentPane(panel);
|
||||
test.setSize(500, 500);
|
||||
test.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
test.setVisible(true);
|
||||
}
|
||||
|
||||
public interface InsertPositionStrategy {
|
||||
int getInsertionIndex(@NotNull Object data, @NotNull JList list);
|
||||
}
|
||||
|
||||
/**
|
||||
* The general idea is to layout target lists to use the same width. This wrapper panel controls that.
|
||||
*/
|
||||
private class ListPanel extends JPanel {
|
||||
|
||||
ListPanel() {
|
||||
super(new GridBagLayout());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension d1 = super.getPreferredSize();
|
||||
if (myActivePreferredSizeProcessing) {
|
||||
return d1;
|
||||
}
|
||||
myActivePreferredSizeProcessing = true;
|
||||
try {
|
||||
final Dimension d2;
|
||||
if (myLeftPanel == this) {
|
||||
d2 = myRightPanel.getPreferredSize();
|
||||
}
|
||||
else {
|
||||
d2 = myLeftPanel.getPreferredSize();
|
||||
}
|
||||
return new Dimension(Math.max(d1.width, d2.width), Math.max(d1.height, d2.height));
|
||||
}
|
||||
finally {
|
||||
myActivePreferredSizeProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LeftAction extends AnAction {
|
||||
|
||||
LeftAction() {
|
||||
getTemplatePresentation().setIcon(AllIcons.Actions.Left);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
doLeft();
|
||||
}
|
||||
}
|
||||
|
||||
private class RightAction extends AnAction {
|
||||
|
||||
RightAction() {
|
||||
getTemplatePresentation().setIcon(AllIcons.Actions.Right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
doRight();
|
||||
}
|
||||
}
|
||||
|
||||
private class AllLeftAction extends AnAction {
|
||||
|
||||
AllLeftAction() {
|
||||
getTemplatePresentation().setIcon(AllIcons.Actions.AllLeft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
doAllLeft();
|
||||
}
|
||||
}
|
||||
|
||||
private class AllRightAction extends AnAction {
|
||||
|
||||
AllRightAction() {
|
||||
getTemplatePresentation().setIcon(AllIcons.Actions.AllRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
doAllRight();
|
||||
}
|
||||
}
|
||||
|
||||
private class UpAction extends AnAction {
|
||||
|
||||
UpAction() {
|
||||
getTemplatePresentation().setIcon(AllIcons.Actions.Up);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
ListUtil.moveSelectedItemsUp(myRightList);
|
||||
}
|
||||
}
|
||||
|
||||
private class DownAction extends AnAction {
|
||||
|
||||
DownAction() {
|
||||
getTemplatePresentation().setIcon(AllIcons.Actions.Down);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
ListUtil.moveSelectedItemsDown(myRightList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,6 +492,9 @@ title.colors.and.fonts=Colors \\& Fonts
|
||||
progress.analysing.font=Analysing font: {0}
|
||||
button.edit.scopes=Edit Scopes...
|
||||
group.editor.font=Editor Font
|
||||
title.font.available=Available fonts:
|
||||
title.font.selected=Selected fonts:
|
||||
label.fallback.fonts.list.description=The ide tries to use the next font from 'Selected fonts' list for displaying a symbol if the current font fails to do that
|
||||
quickdoc.tooltip.font.size.by.wheel=Slider or Ctrl+Wheel change font size
|
||||
label.font.size=Font size:
|
||||
label.font.name=Name:
|
||||
|
||||
@@ -27,6 +27,8 @@ public class AllIcons {
|
||||
|
||||
public static class Actions {
|
||||
public static final Icon AddFacesSupport = IconLoader.getIcon("/actions/addFacesSupport.png"); // 16x16
|
||||
public static final Icon AllLeft = IconLoader.getIcon("/actions/allLeft.png"); // 16x16
|
||||
public static final Icon AllRight = IconLoader.getIcon("/actions/allRight.png"); // 16x16
|
||||
public static final Icon Annotate = IconLoader.getIcon("/actions/annotate.png"); // 16x16
|
||||
public static final Icon Back = IconLoader.getIcon("/actions/back.png"); // 16x16
|
||||
public static final Icon Browser_externalJavaDoc = IconLoader.getIcon("/actions/browser-externalJavaDoc.png"); // 16x16
|
||||
@@ -53,6 +55,7 @@ public class AllIcons {
|
||||
public static final Icon Delete = IconLoader.getIcon("/actions/delete.png"); // 16x16
|
||||
public static final Icon Diff = IconLoader.getIcon("/actions/diff.png"); // 16x16
|
||||
public static final Icon DiffWithCurrent = IconLoader.getIcon("/actions/diffWithCurrent.png"); // 16x16
|
||||
public static final Icon Down = IconLoader.getIcon("/actions/down.png"); // 16x16
|
||||
public static final Icon Download = IconLoader.getIcon("/actions/download.png"); // 16x16
|
||||
public static final Icon Dump = IconLoader.getIcon("/actions/dump.png"); // 16x16
|
||||
public static final Icon Edit = IconLoader.getIcon("/actions/edit.png"); // 14x14
|
||||
@@ -78,6 +81,7 @@ public class AllIcons {
|
||||
public static final Icon Help = IconLoader.getIcon("/actions/help.png"); // 16x16
|
||||
public static final Icon Install = IconLoader.getIcon("/actions/install.png"); // 16x16
|
||||
public static final Icon IntentionBulb = IconLoader.getIcon("/actions/intentionBulb.png"); // 16x16
|
||||
public static final Icon Left = IconLoader.getIcon("/actions/left.png"); // 16x16
|
||||
public static final Icon Lightning = IconLoader.getIcon("/actions/lightning.png"); // 16x16
|
||||
public static final Icon Menu_cut = IconLoader.getIcon("/actions/menu-cut.png"); // 16x16
|
||||
public static final Icon Menu_find = IconLoader.getIcon("/actions/menu-find.png"); // 16x16
|
||||
@@ -120,6 +124,7 @@ public class AllIcons {
|
||||
public static final Icon Reset = IconLoader.getIcon("/actions/reset.png"); // 16x16
|
||||
public static final Icon Restart = IconLoader.getIcon("/actions/restart.png"); // 16x16
|
||||
public static final Icon Resume = IconLoader.getIcon("/actions/resume.png"); // 16x16
|
||||
public static final Icon Right = IconLoader.getIcon("/actions/right.png"); // 16x16
|
||||
public static final Icon Rollback = IconLoader.getIcon("/actions/rollback.png"); // 16x16
|
||||
public static final Icon RunToCursor = IconLoader.getIcon("/actions/runToCursor.png"); // 16x16
|
||||
public static final Icon Search = IconLoader.getIcon("/actions/search.png"); // 16x16
|
||||
@@ -150,7 +155,8 @@ public class AllIcons {
|
||||
public static final Icon Uninstall = IconLoader.getIcon("/actions/uninstall.png"); // 16x16
|
||||
public static final Icon Unselectall = IconLoader.getIcon("/actions/unselectall.png"); // 16x16
|
||||
public static final Icon Unshare = IconLoader.getIcon("/actions/unshare.png"); // 14x14
|
||||
|
||||
public static final Icon Up = IconLoader.getIcon("/actions/up.png"); // 16x16
|
||||
|
||||
}
|
||||
|
||||
public static class Ant {
|
||||
|
||||