/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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.google.dart.tools.ui.internal.preferences; import com.google.dart.tools.ui.DartToolsPlugin; import com.google.dart.tools.ui.PreferenceConstants; import com.google.dart.tools.ui.internal.text.editor.DartDocumentSetupParticipant; import com.google.dart.tools.ui.internal.text.functions.DartColorManager; import com.google.dart.tools.ui.internal.util.SWTUtil; import com.google.dart.tools.ui.text.DartPartitions; import com.google.dart.tools.ui.text.DartSourceViewerConfiguration; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.preference.PreferenceStore; import org.eclipse.jface.resource.FontRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FontDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.themes.ThemeElementHelper; import org.eclipse.ui.themes.ITheme; import org.eclipse.ui.themes.IThemeManager; import java.util.HashMap; import java.util.Map; /** * Preference page for fonts in the editor */ @SuppressWarnings("restriction") public class FontPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { private static class FontSelectionComposite extends Composite { private final String baseKey; private final String key; private Button smallFontsButton; private Button mediumFontsButton; private Button largeFontsButton; private Button xlFontsButton; private SourceViewer previewViewer; private Button selectFontButton; private Label codeFontLabel; private Button resetButton; private SourceViewerConfiguration sourceViewerConfiguration; private FontData[] fontData; private FontData[] baseData; public FontSelectionComposite(Composite parent, int style, String baseKey, String key, String msg) { super(parent, style); this.baseKey = baseKey; this.key = key; GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(this); setLayout(new GridLayout(1, false)); Group fontGroup = new Group(this, SWT.NONE); fontGroup.setText(msg); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo( fontGroup); GridLayoutFactory.fillDefaults().numColumns(2).margins(8, 8).applyTo(fontGroup); // code font createPreviewer(fontGroup); Composite buttons = new Composite(fontGroup, SWT.NONE); GridLayoutFactory.fillDefaults().applyTo(buttons); // font scaling { Composite scaleComposite = new Composite(buttons, SWT.NONE); scaleComposite.setLayout(new GridLayout(4, true)); smallFontsButton = new Button(scaleComposite, SWT.TOGGLE | SWT.FLAT | SWT.CENTER); smallFontsButton.setFont(parent.getFont()); // bootstrapping smallFontsButton.setText(PreferencesMessages.DartBasePreferencePage_font_scale_indicator); smallFontsButton.setFont(getSmallFont()); smallFontsButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.END, false, false)); smallFontsButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateFont(smallFontsButton.getFont()); } }); mediumFontsButton = new Button(scaleComposite, SWT.TOGGLE | SWT.FLAT | SWT.CENTER); mediumFontsButton.setText(PreferencesMessages.DartBasePreferencePage_font_scale_indicator); mediumFontsButton.setFont(getMediumFont()); mediumFontsButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.END, false, false)); mediumFontsButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateFont(mediumFontsButton.getFont()); } }); largeFontsButton = new Button(scaleComposite, SWT.TOGGLE | SWT.FLAT | SWT.CENTER); largeFontsButton.setText(PreferencesMessages.DartBasePreferencePage_font_scale_indicator); largeFontsButton.setFont(getLargeFont()); largeFontsButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.END, false, false)); largeFontsButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateFont(largeFontsButton.getFont()); } }); xlFontsButton = new Button(scaleComposite, SWT.TOGGLE | SWT.FLAT | SWT.CENTER); xlFontsButton.setText(PreferencesMessages.DartBasePreferencePage_font_scale_indicator); xlFontsButton.setFont(getXlFont()); xlFontsButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.END, false, false)); xlFontsButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateFont(xlFontsButton.getFont()); } }); } codeFontLabel = new Label(buttons, SWT.NONE); selectFontButton = new Button(buttons, SWT.PUSH); GridDataFactory.fillDefaults().grab(false, true).applyTo(selectFontButton); selectFontButton.setText(PreferencesMessages.DartBasePreferencePage_code_font_select_label); selectFontButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { chooseCodeFont(); } }); resetButton = new Button(buttons, SWT.PUSH); GridDataFactory.fillDefaults().grab(false, true).applyTo(resetButton); resetButton.setText(PreferencesMessages.DartBasePreferencePage_reset_button_label); resetButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { resetFonts(); } }); initFromPrefs(); } boolean isFontOfSize(Font font, int size) { return font.getFontData()[0].getHeight() == size; } private void chooseCodeFont() { final FontDialog fontDialog = new FontDialog(getShell()); fontDialog.setFontList(getFontData()); final FontData data = fontDialog.open(); if (data != null) { fontData = new FontData[] {data}; baseData = fontData; updatePreviewFont(SWTUtil.getFont(getMediumFont().getDevice(), fontData)); } } private void createPreviewer(Composite parent) { Composite previewComp = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = layout.marginWidth = 0; previewComp.setLayout(layout); previewComp.setLayoutData(new GridData(GridData.FILL_BOTH)); previewViewer = new SourceViewer(previewComp, null, SWT.BORDER /* | SWT.V_SCROLL | SWT.H_SCROLL */); sourceViewerConfiguration = getSourceViewerConfiguration(); if (sourceViewerConfiguration != null) { previewViewer.configure(sourceViewerConfiguration); } previewViewer.setEditable(false); previewViewer.setDocument(getDocument()); Control control = previewViewer.getControl(); GridData controlData = new GridData(GridData.FILL_BOTH); controlData.heightHint = 100; control.setLayoutData(controlData); } private int findFontIndex(int size) { // exact match? for (int i = 0; i < FONT_SIZES.length; i++) { if (FONT_SIZES[i] == size) { return i; } } // next largest? for (int i = 0; i < FONT_SIZES.length; i++) { if (FONT_SIZES[i] > size) { return i; } } // first return 0; } private int findScaledCodeFontSize(int oldCodeFontSize, int oldBaseFontSize, int newBaseFontSize) { int oldCodeIndex = findFontIndex(oldCodeFontSize); int oldBaseIndex = findFontIndex(oldBaseFontSize); int newBaseIndex = findFontIndex(newBaseFontSize); int delta = newBaseIndex - oldBaseIndex; int newCodeIndex = oldCodeIndex + delta; newCodeIndex = Math.max(Math.min(newCodeIndex, FONT_SIZES.length - 1), 0); return FONT_SIZES[newCodeIndex]; } private FontData[] getBaseData() { if (baseData == null) { IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); ITheme theme = themeManager.getCurrentTheme(); baseData = theme.getFontRegistry().getFontData(baseKey); } return baseData; } private IDocument getDocument() { IDocument document = new Document(SAMPLE_CODE); new DartDocumentSetupParticipant().setup(document); return document; } private Font getFont(int size) { FontData oldData = getBaseData()[0]; FontData data = new FontData(oldData.getName(), oldData.getHeight(), oldData.getStyle()); data.height = size; Font font = smallFontsButton.getFont(); // bootstrapped font = new Font(font.getDevice(), data); return font; } private FontData[] getFontData() { if (fontData == null) { IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); ITheme theme = themeManager.getCurrentTheme(); fontData = theme.getFontRegistry().getFontData(key); } return fontData; } private Font getLargeFont() { return getFont(SZ_LARGE); } private Font getMediumFont() { return getFont(SZ_MEDIUM); } private Font getSmallFont() { return getFont(SZ_SMALL); } private SourceViewerConfiguration getSourceViewerConfiguration() { return new DartSourceViewerConfiguration( new DartColorManager(), new PreferenceStore(), null, DartPartitions.DART_PARTITIONING); } private Font getXlFont() { return getFont(SZ_XL); } private void initFromPrefs() { getFontData(); getBaseData(); updatePreviewFont(JFaceResources.getFont(key)); selectFontButton(); setCodeFontLabel(); } private void performOk() { persistFont(baseKey, baseData); persistFont(key, fontData); if (key == EDITOR_FONT_KEY) { persistFont(WST_FONT_KEY, baseData); } if (key == VIEW_FONT_KEY) { persistFont( "org.eclipse.debug.ui.VariableTextFont" /*IDebugUIConstants.PREF_VARIABLE_TEXT_FONT*/, baseData); persistFont( "org.eclipse.debug.ui.DetailPaneFont" /*IDebugUIConstants.PREF_DETAIL_PANE_FONT*/, baseData); } /* * The following block of code adjusts fonts in dialogs. There are some issues, like much of the * non-framework section of the page not getting changed. For now, it is commented out. */ // int height = fontData[0].getHeight(); // scaleFontNamed(JFaceResources.HEADER_FONT, height + 3); // scaleFontNamed(JFaceResources.BANNER_FONT, height + 1); // scaleFontNamed(JFaceResources.DIALOG_FONT, height); // scaleFontNamed(JFaceResources.DEFAULT_FONT, height); } private void persistFont(String fontKey, FontData[] fontData) { IPreferenceStore workbenchPrefStore = WorkbenchPlugin.getDefault().getPreferenceStore(); IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); ITheme theme = themeManager.getCurrentTheme(); FontRegistry registry = theme.getFontRegistry(); registry.put(fontKey, fontData); String key = ThemeElementHelper.createPreferenceKey(theme, fontKey); String fdString = PreferenceConverter.getStoredRepresentation(fontData); String storeString = workbenchPrefStore.getString(key); if (!fdString.equals(storeString)) { workbenchPrefStore.setValue(key, fdString); } } private void resetFonts() { IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); ITheme theme = themeManager.getCurrentTheme(); fontData = theme.getFontRegistry().getFontData(EDITOR_DEFAULT_FONT_KEY); baseData = theme.getFontRegistry().getFontData(BASE_DEFAULT_FONT_KEY); selectFontButton(); updatePreviewFont(SWTUtil.getFont(getMediumFont().getDevice(), fontData)); } @SuppressWarnings("unused") private void scaleFontNamed(String name, int size) { IPreferenceStore workbenchPrefStore = WorkbenchPlugin.getDefault().getPreferenceStore(); IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); ITheme theme = themeManager.getCurrentTheme(); FontRegistry registry = theme.getFontRegistry(); FontData[] fds = registry.getFontData(name); FontData data = new FontData(fds[0].getName(), size, fds[0].getStyle()); registry.put(name, new FontData[] {data}); String key = ThemeElementHelper.createPreferenceKey(theme, name); String fdString = PreferenceConverter.getStoredRepresentation(new FontData[] {data}); String storeString = workbenchPrefStore.getString(key); if (!fdString.equals(storeString)) { workbenchPrefStore.setValue(key, fdString); } } private void selectFontButton() { smallFontsButton.setSelection(false); mediumFontsButton.setSelection(false); largeFontsButton.setSelection(false); xlFontsButton.setSelection(false); FontData data = getBaseData()[0]; int size = data.getHeight(); if (isFontOfSize(smallFontsButton.getFont(), size)) { smallFontsButton.setSelection(true); } else if (isFontOfSize(mediumFontsButton.getFont(), size)) { mediumFontsButton.setSelection(true); } else if (isFontOfSize(largeFontsButton.getFont(), size)) { largeFontsButton.setSelection(true); } else if (isFontOfSize(xlFontsButton.getFont(), size)) { xlFontsButton.setSelection(true); } } private void setCodeFontLabel() { StringBuilder label = new StringBuilder(); FontData data = getFontData()[0]; label.append(data.getName()); label.append(" "); label.append(data.getHeight()); codeFontLabel.setText(label.toString()); codeFontLabel.getParent().getParent().layout(true, true); } private void updateFont(Font font) { int oldBaseFontSize = baseData[0].getHeight(); int oldCodeFontSize = fontData[0].getHeight(); FontData[] data = baseData = font.getFontData(); int newBaseFontSize = data[0].getHeight(); int newCodeFontSize = findScaledCodeFontSize( oldCodeFontSize, oldBaseFontSize, newBaseFontSize); baseData = data; fontData = SWTUtil.changeFontSize(fontData, newCodeFontSize); Font newFont = SWTUtil.getFont(font.getDevice(), fontData); selectFontButton(); updatePreviewFont(newFont); } private void updatePreviewFont(Font font) { setCodeFontLabel(); previewViewer.getTextWidget().setFont(font); } } private static final String SAMPLE_CODE = " void run() {\n write('Hello, world!');\n }"; public static final String FONT_PREF_PAGE_ID = "com.google.dart.tools.ui.preferences.FontPreferencePage"; //$NON-NLS-1$ public static final String EDITOR_FONT_KEY = PreferenceConstants.EDITOR_TEXT_FONT; public static final String EDITOR_DEFAULT_FONT_KEY = "com.google.dart.tools.ui.editors.textfont.default"; public static final String EDITOR_BASE_FONT_KEY = "com.google.dart.tools.ui.editors.basefont"; public static final String BASE_DEFAULT_FONT_KEY = "com.google.dart.tools.ui.editors.basefont.default"; public static final String VIEW_FONT_KEY = PreferenceConstants.VIEW_TEXT_FONT; public static final String VIEW_BASE_FONT_KEY = "com.google.dart.tools.ui.views.basefont"; public static final String WST_FONT_KEY = "org.eclipse.wst.sse.ui.textfont"; private static final int SZ_SMALL = 10; private static final int SZ_MEDIUM = 11; private static final int SZ_LARGE = 14; private static final int SZ_XL = 18; // Available font sizes private static final int[] FONT_SIZES = { 8, 9, SZ_SMALL, SZ_MEDIUM, SZ_LARGE, SZ_XL, 24, 36, 48, 64, 72, 96, 144, 288}; public static Map<String, FontData> getAllFontsByName() { // this returns nearly 150 named fonts, so is unsuitable for use directly in the UI FontData[] allFonts = Display.getCurrent().getFontList(null, true); Map<String, FontData> fonts = new HashMap<String, FontData>(); for (FontData data : allFonts) { String name = data.getName(); if (fonts.get(name) == null) { fonts.put(name, data); } } return fonts; } private FontSelectionComposite editorComposite; private FontSelectionComposite viewComposite; public FontPreferencePage() { setPreferenceStore(DartToolsPlugin.getDefault().getPreferenceStore()); // setDescription(PreferencesMessages.DartBasePreferencePage_text_font); noDefaultAndApplyButton(); } @Override public IPreferenceStore getPreferenceStore() { return new PreferenceStore(); } @Override public void init(IWorkbench arg0) { } @Override public boolean performOk() { editorComposite.performOk(); viewComposite.performOk(); return true; } @Override protected Control createContents(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout(1, false)); editorComposite = new FontSelectionComposite( composite, SWT.NONE, EDITOR_BASE_FONT_KEY, EDITOR_FONT_KEY, "Editors"); viewComposite = new FontSelectionComposite( composite, SWT.NONE, VIEW_BASE_FONT_KEY, VIEW_FONT_KEY, "Views"); return composite; } }