package org.jabref.gui.preftabs; import java.awt.BorderLayout; import java.awt.Font; import java.awt.GridBagLayout; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.UIManager; import org.jabref.gui.GUIGlobals; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; import org.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; class AppearancePrefsTab extends JPanel implements PrefsTab { private static final Log LOGGER = LogFactory.getLog(AppearancePrefsTab.class); private final JabRefPreferences prefs; private final JCheckBox colorCodes; private final JCheckBox resolvedColorCodes; private final JCheckBox overrideFonts; private final JCheckBox showGrid; private final ColorSetupPanel colorPanel; private Font usedFont = GUIGlobals.currentFont; private int oldMenuFontSize; private int oldSmallIconSize; private int oldLargeIconSize; private boolean oldOverrideFontSize; private final JTextField fontSize; private final JTextField largeIconsTextField; private final JTextField smallIconsTextField; private final JTextField rowPadding; // look and feel private final JComboBox<String> classNamesLAF; private String currentLAF = ""; private boolean useDefaultLAF; private final JCheckBox customLAF; static class LookAndFeel { private static final List<String> looks = Arrays.asList( UIManager.getSystemLookAndFeelClassName(), UIManager.getCrossPlatformLookAndFeelClassName(), "com.jgoodies.looks.plastic.Plastic3DLookAndFeel", "com.jgoodies.looks.windows.WindowsLookAndFeel"); public static List<String> getAvailableLookAndFeels() { List<String> lookAndFeels = new ArrayList<>(); for (String l : looks) { try { // Try to find L&F Class.forName(l); lookAndFeels.add(l); } catch (ClassNotFoundException | IllegalAccessError ignored) { // LookAndFeel class does not exist or we don't have rights to access it // Ignore it } } return lookAndFeels; } } /** * Customization of appearance parameters. * * @param prefs a <code>JabRefPreferences</code> value */ public AppearancePrefsTab(JabRefPreferences prefs) { this.prefs = prefs; setLayout(new BorderLayout()); // Font sizes: fontSize = new JTextField(5); // Row padding size: rowPadding = new JTextField(5); // Icon sizes: largeIconsTextField = new JTextField(5); smallIconsTextField = new JTextField(5); colorCodes = new JCheckBox( Localization.lang("Color codes for required and optional fields")); resolvedColorCodes = new JCheckBox(Localization.lang("Color code for resolved fields")); overrideFonts = new JCheckBox(Localization.lang("Override default font settings")); showGrid = new JCheckBox(Localization.lang("Show gridlines")); FormLayout layout = new FormLayout("1dlu, 8dlu, left:pref, 4dlu, fill:pref, 4dlu, fill:60dlu, 4dlu, fill:pref", ""); DefaultFormBuilder builder = new DefaultFormBuilder(layout); customLAF = new JCheckBox(Localization.lang("Use other look and feel")); // Only list L&F which are available List<String> lookAndFeels = LookAndFeel.getAvailableLookAndFeels(); classNamesLAF = new JComboBox<>(lookAndFeels.toArray(new String[lookAndFeels.size()])); classNamesLAF.setEditable(true); final JComboBox<String> clName = classNamesLAF; customLAF.addChangeListener(e -> clName.setEnabled(((JCheckBox) e.getSource()).isSelected())); colorPanel = new ColorSetupPanel(colorCodes, resolvedColorCodes, showGrid); // only the default L&F shows the the OSX specific first dropdownmenu if (!OS.OS_X) { JPanel pan = new JPanel(); builder.appendSeparator(Localization.lang("Look and feel")); JLabel lab = new JLabel( Localization.lang("Default look and feel") + ": " + UIManager.getSystemLookAndFeelClassName()); builder.nextLine(); builder.append(pan); builder.append(lab); builder.nextLine(); builder.append(pan); builder.append(customLAF); builder.nextLine(); builder.append(pan); JPanel pan2 = new JPanel(); lab = new JLabel(Localization.lang("Class name") + ':'); pan2.add(lab); pan2.add(classNamesLAF); builder.append(pan2); builder.nextLine(); builder.append(pan); lab = new JLabel(Localization .lang("Note that you must specify the fully qualified class name for the look and feel,")); builder.append(lab); builder.nextLine(); builder.append(pan); lab = new JLabel( Localization.lang("and the class must be available in your classpath next time you start JabRef.")); builder.append(lab); builder.nextLine(); } builder.leadingColumnOffset(2); // General appearance settings builder.appendSeparator(Localization.lang("General")); FormBuilder generalBuilder = FormBuilder.create(); JPanel generalPanel = generalBuilder.columns("left:pref, left:pref, 3dlu, pref, 7dlu, right:pref, 3dlu, pref") .rows("pref, 3dlu, pref, 3dlu, pref") .columnGroup(2,6) .columnGroup(4,8) .add(overrideFonts).xyw(1,1,5) .add(new JLabel(" ")).xy(1,3) .add(new JLabel(Localization.lang("Menu and label font size") + ":")).xy(2,3) .add(fontSize).xy(4,3) .add(new JLabel(Localization.lang("Size of large icons") + ":")).xy(2, 5) .add(largeIconsTextField).xy(4,5) .add(new JLabel(Localization.lang("Size of small icons") + ":")).xy(6, 5) .add(smallIconsTextField).xy(8,5) .build(); builder.append(generalPanel); builder.nextLine(); builder.appendSeparator(Localization.lang("Table appearance")); JPanel p2 = new JPanel(); p2.add(new JLabel(Localization.lang("Table row height padding") + ":")); p2.add(rowPadding); builder.append(p2); builder.nextLine(); builder.append(colorCodes); builder.nextLine(); builder.append(resolvedColorCodes); builder.nextLine(); builder.append(showGrid); builder.nextLine(); JButton fontButton = new JButton(Localization.lang("Set table font")); builder.append(fontButton); builder.nextLine(); builder.appendSeparator(Localization.lang("Table and entry editor colors")); builder.append(colorPanel); JPanel upper = new JPanel(); JPanel sort = new JPanel(); JPanel namesp = new JPanel(); JPanel iconCol = new JPanel(); GridBagLayout gbl = new GridBagLayout(); upper.setLayout(gbl); sort.setLayout(gbl); namesp.setLayout(gbl); iconCol.setLayout(gbl); overrideFonts.addActionListener(e -> fontSize.setEnabled(overrideFonts.isSelected())); overrideFonts.addActionListener(e -> largeIconsTextField.setEnabled(overrideFonts.isSelected())); overrideFonts.addActionListener(e -> smallIconsTextField.setEnabled(overrideFonts.isSelected())); fontButton.addActionListener( e -> new FontSelectorDialog(null, usedFont).getSelectedFont().ifPresent(x -> usedFont = x)); JPanel pan = builder.getPanel(); pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); add(pan, BorderLayout.CENTER); } @Override public void setValues() { // L&F useDefaultLAF = prefs.getBoolean(JabRefPreferences.USE_DEFAULT_LOOK_AND_FEEL); currentLAF = prefs.get(JabRefPreferences.WIN_LOOK_AND_FEEL); customLAF.setSelected(!useDefaultLAF); classNamesLAF.setSelectedItem(currentLAF); classNamesLAF.setEnabled(!useDefaultLAF); colorCodes.setSelected(prefs.getBoolean(JabRefPreferences.TABLE_COLOR_CODES_ON)); resolvedColorCodes.setSelected(prefs.getBoolean(JabRefPreferences.TABLE_RESOLVED_COLOR_CODES_ON)); rowPadding.setText(String.valueOf(prefs.getInt(JabRefPreferences.TABLE_ROW_PADDING))); oldOverrideFontSize = prefs.getBoolean(JabRefPreferences.OVERRIDE_DEFAULT_FONTS); oldMenuFontSize = prefs.getInt(JabRefPreferences.MENU_FONT_SIZE); oldLargeIconSize = prefs.getInt(JabRefPreferences.ICON_SIZE_LARGE); oldSmallIconSize = prefs.getInt(JabRefPreferences.ICON_SIZE_SMALL); overrideFonts.setSelected(oldOverrideFontSize); fontSize.setText(String.valueOf(oldMenuFontSize)); smallIconsTextField.setText(String.valueOf(oldSmallIconSize)); largeIconsTextField.setText(String.valueOf(oldLargeIconSize)); fontSize.setEnabled(overrideFonts.isSelected()); smallIconsTextField.setEnabled(overrideFonts.isSelected()); largeIconsTextField.setEnabled(overrideFonts.isSelected()); showGrid.setSelected(prefs.getBoolean(JabRefPreferences.TABLE_SHOW_GRID)); colorPanel.setValues(); } @Override public void storeSettings() { // L&F prefs.putBoolean(JabRefPreferences.USE_DEFAULT_LOOK_AND_FEEL, !customLAF.isSelected()); prefs.put(JabRefPreferences.WIN_LOOK_AND_FEEL, classNamesLAF.getSelectedItem().toString()); if ((customLAF.isSelected() == useDefaultLAF) || !currentLAF.equals(classNamesLAF.getSelectedItem().toString())) { JOptionPane.showMessageDialog(null, Localization.lang("You have changed the look and feel setting.").concat(" ") .concat(Localization.lang("You must restart JabRef for this to come into effect.")), Localization.lang("Changed look and feel settings"), JOptionPane.WARNING_MESSAGE); } prefs.putBoolean(JabRefPreferences.TABLE_COLOR_CODES_ON, colorCodes.isSelected()); prefs.putBoolean(JabRefPreferences.TABLE_RESOLVED_COLOR_CODES_ON, resolvedColorCodes.isSelected()); prefs.put(JabRefPreferences.FONT_FAMILY, usedFont.getFamily()); prefs.putInt(JabRefPreferences.FONT_STYLE, usedFont.getStyle()); prefs.putInt(JabRefPreferences.FONT_SIZE, usedFont.getSize()); prefs.putBoolean(JabRefPreferences.OVERRIDE_DEFAULT_FONTS, overrideFonts.isSelected()); GUIGlobals.currentFont = usedFont; colorPanel.storeSettings(); prefs.putBoolean(JabRefPreferences.TABLE_SHOW_GRID, showGrid.isSelected()); try { int size = Integer.parseInt(fontSize.getText()); int smallIconSize = Integer.parseInt(smallIconsTextField.getText()); int largeIconSize = Integer.parseInt(largeIconsTextField.getText()); int padding = Integer.parseInt(rowPadding.getText()); if (overrideFonts.isSelected()) { boolean somethingIsChanged = false; if (size != oldMenuFontSize) { prefs.putInt(JabRefPreferences.MENU_FONT_SIZE, size); somethingIsChanged = true; } if (smallIconSize != oldSmallIconSize) { prefs.putInt(JabRefPreferences.ICON_SIZE_SMALL, smallIconSize); somethingIsChanged = true; } if (largeIconSize != oldLargeIconSize) { prefs.putInt(JabRefPreferences.ICON_SIZE_LARGE, largeIconSize); somethingIsChanged = true; } if (somethingIsChanged) { JOptionPane.showMessageDialog(null, Localization.lang("You have changed the menu and label font size.").concat(" ") .concat(Localization.lang("You must restart JabRef for this to come into effect.")), Localization.lang("Changed font settings"), JOptionPane.WARNING_MESSAGE); } } else if (overrideFonts.isSelected() != oldOverrideFontSize) { prefs.remove(JabRefPreferences.ICON_SIZE_SMALL); prefs.remove(JabRefPreferences.ICON_SIZE_LARGE); prefs.remove(JabRefPreferences.MENU_FONT_SIZE); JOptionPane.showMessageDialog(null, Localization.lang("You have changed the menu and label font size.").concat(" ") .concat(Localization.lang("You must restart JabRef for this to come into effect.")), Localization.lang("Changed font settings"), JOptionPane.WARNING_MESSAGE); } prefs.putInt(JabRefPreferences.TABLE_ROW_PADDING, padding); } catch (NumberFormatException ex) { // should not happen as values are checked beforehand LOGGER.error("Invalid data value, integer expected", ex); } } private boolean validateIntegerField(String fieldName, String fieldValue, String errorTitle) { try { // Test if the field value is a number: Integer.parseInt(fieldValue); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null, Localization.lang("You must enter an integer value in the text field for") + " '" + fieldName + "'", errorTitle, JOptionPane.ERROR_MESSAGE); return false; } return true; } @Override public boolean validateSettings() { // Test if font size is a number: if (!validateIntegerField(Localization.lang("Menu and label font size"), fontSize.getText(), Localization.lang("Invalid setting"))) { return false; } if (!validateIntegerField(Localization.lang("Size of large icons"), largeIconsTextField.getText(), Localization.lang("Invalid setting"))) { return false; } if (!validateIntegerField(Localization.lang("Size of small icons"), smallIconsTextField.getText(), Localization.lang("Invalid setting"))) { return false; } // Test if row padding is a number: return validateIntegerField(Localization.lang("Table row height padding"), rowPadding.getText(), Localization.lang("Invalid setting")); } @Override public String getTabName() { return Localization.lang("Appearance"); } }