blob: 0281d5b1d55a4b4298b79896e1141403c7fca3c3 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2013, 2019 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.r.ui.graphics;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.ecommons.ui.dialogs.ToolPopup;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.rj.eclient.graphics.RGraphics;
public class RFontFamilyChooser extends ToolPopup {
private static final String GENERIC = "Generic"; //$NON-NLS-1$
public static void drawPreview(final GC gc,
final int x, final int y, final int width, final int height,
final Font font ) {
if (font != null) {
gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
gc.fillRectangle(x, y, width + 1, height + 1);
// gc.setTextAntialias(SWT.ON);
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
gc.setFont(font);
final FontMetrics fontMetrics = gc.getFontMetrics();
gc.setClipping(x, y, width, height);
gc.drawText("Abc 12.0", x + 2, y + 1 - fontMetrics.getLeading() + Math.max(1 + (height - fontMetrics.getHeight()) / 2, 0), //$NON-NLS-1$
SWT.DRAW_TRANSPARENT );
gc.setClipping((Rectangle) null);
}
}
public static String getFontName(final String value) {
if (value != null) {
if (value.equals("serif")) { //$NON-NLS-1$
return Platform.getPreferencesService().getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SERIF_FONTNAME_KEY, "", null); //$NON-NLS-1$
}
else if (value.equals("sansserif")) { //$NON-NLS-1$
return Platform.getPreferencesService().getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SANS_FONTNAME_KEY, "", null); //$NON-NLS-1$
}
else if (value.equals("mono")) { //$NON-NLS-1$
return Platform.getPreferencesService().getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_MONO_FONTNAME_KEY, "", null); //$NON-NLS-1$
}
}
return value;
}
public static Font createFont(final Device device, final String fontName, int height) {
FontData fontData = getFontData(device, fontName);
if (fontData == null) {
return null;
}
if (height < 0) {
height = JFaceResources.getDialogFont().getFontData()[0].getHeight();
}
if (fontData.getHeight() != height) {
fontData = new FontData(fontData.getName(), height, fontData.getStyle());
}
return new Font(device, fontData);
}
private static FontData getFontData(final Device device, final String fontName) {
if (fontName == null || fontName.isEmpty()) {
return null;
}
FontData[] fontDatas = device.getFontList(fontName, true);
if (fontDatas.length == 0) {
fontDatas = device.getFontList(fontName, false);
}
if (fontDatas.length == 0) {
return null;
}
for (int i = 0; i < fontDatas.length; i++) {
if (fontDatas[i].getStyle() == SWT.NORMAL) {
return fontDatas[i];
}
}
for (int i = 0; i < fontDatas.length; i++) {
if (fontDatas[i].getStyle() == SWT.ITALIC) {
return fontDatas[i];
}
}
return fontDatas[0];
}
protected static abstract class GenericTab extends ToolTab {
private static final ImList<String> VALUES= ImCollections.newList(
"serif", //$NON-NLS-1$
"sansserif", //$NON-NLS-1$
"mono" ); //$NON-NLS-1$
private Button[] fButtons;
GenericTab(final ToolPopup parent) {
this(parent, "Standard", "Definition by generic R Standard Names"); //$NON-NLS-1$
}
GenericTab(final ToolPopup parent, final String name, final String tooltip) {
super(GENERIC, parent, name, tooltip);
final Composite composite = create();
composite.setLayout(LayoutUtils.newTabGrid(3));
{ final String[] labels = new String[] { "Serif", "Sans Serif", "Monospace" };
final Listener listener = new Listener() {
@Override
public void handleEvent(final Event event) {
switch (event.type) {
case SWT.Selection:
setValue((String) event.widget.getData());
return;
case SWT.MouseDoubleClick:
event.widget.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
performOK();
}
});
return;
}
}
};
fButtons = new Button[3];
for (int i = 0; i < 3; i++) {
final Button button = new Button(composite, SWT.RADIO);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
button.setText(labels[i] + " ('" + VALUES.get(i) + "')"); //$NON-NLS-1$ //$NON-NLS-2$
button.setData(VALUES.get(i));
button.addListener(SWT.Selection, listener);
button.addListener(SWT.MouseDoubleClick, listener);
fButtons[i] = button;
}
fButtons[0].setSelection(true);
}
LayoutUtils.addGDDummy(composite, true, 3);
{ final Link link = new Link(composite, SWT.NONE);
link.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
link.setText("<a>Preferences for Standard Fonts in StatET...</a>");
link.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final ToolPopup popup = getParent();
popup.beginIgnoreActivation();
try {
final PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(popup.getShell(),
"org.eclipse.statet.r.preferencePages.RGraphicsPage", //$NON-NLS-1$
new String[] { "org.eclipse.statet.r.preferencePages.RGraphicsPage" }, //$NON-NLS-1$
null );
dialog.open();
}
finally {
popup.endIgnoreActivation();
}
}
});
}
}
@Override
protected void activated() {
final String value = getValue();
final int idx = VALUES.indexOf(value);
for (int i = 0; i < 3; i++) {
fButtons[i].setSelection(i == idx);
}
}
protected abstract String getValue();
protected abstract void setValue(String value);
}
private String fInitialValue;
private String fInitialFontName;
private Font fInitialSWTFont;
private String fCurrentFontName;
private String fCurrentValue;
private Font fCurrentSWTFont;
private Composite fStatusControl;
public RFontFamilyChooser() {
}
public void open(final Shell parent, final Rectangle position, final String initialValue) {
fInitialValue = initialValue;
doSetValue((initialValue != null) ? initialValue : "sansserif"); //$NON-NLS-1$
super.open(parent, position);
}
@Override
protected void addTabs(final CTabFolder tabFolder) {
new GenericTab(this) {
@Override
protected String getValue() {
return RFontFamilyChooser.this.getValue();
}
@Override
protected void setValue(final String value) {
RFontFamilyChooser.this.doSetValue(value);
}
};
}
@Override
protected ToolTab getBestTab() {
return getTab(GENERIC);
}
@Override
protected void addStatusControls(final Composite composite) {
fStatusControl = new PreviewCanvas(composite) {
@Override
protected void drawPreview(final GC gc, final int idx,
final int x, final int y, final int width, final int height) {
Font font = null;
switch (idx) {
case 0:
if (fInitialValue != null) {
if (fInitialSWTFont == null && fInitialFontName != "") { //$NON-NLS-1$
if (fInitialFontName == null) {
fInitialFontName = getFontName(fInitialValue);
}
fInitialSWTFont = createFont(gc.getDevice(), fInitialFontName, -1);
if (fInitialSWTFont == null) {
fInitialFontName = ""; //$NON-NLS-1$
}
}
font = fInitialSWTFont;
}
break;
case 1:
if (fCurrentValue != null) {
if (fCurrentSWTFont == null && fCurrentFontName != "") { //$NON-NLS-1$
if (fCurrentFontName == null) {
fCurrentFontName = getFontName(fCurrentValue);
}
fCurrentSWTFont = createFont(gc.getDevice(), fCurrentFontName, -1);
if (fCurrentSWTFont == null) {
fCurrentFontName = ""; //$NON-NLS-1$
}
}
font = fCurrentSWTFont;
}
break;
default:
break;
}
RFontFamilyChooser.drawPreview(gc, x, y, width, height, font);
}
};
updateStatus();
}
protected void doSetValue(final String value) {
if (value == null || value.equals(fCurrentValue)) {
return;
}
final String fontName = getFontName(value);
if (fCurrentSWTFont != null && (fontName == null || !fontName.equals(fCurrentFontName))) {
fCurrentSWTFont.dispose();
fCurrentSWTFont = null;
}
fCurrentValue = value;
fCurrentFontName = fontName;
if (fStatusControl != null) {
updateStatus();
}
}
protected void updateStatus() {
final StringBuilder sb = new StringBuilder();
sb.append("Previous: ");
sb.append((fInitialValue != null) ? fInitialValue : "-"); //$NON-NLS-1$
sb.append("\n");
sb.append("Current: ");
sb.append(fCurrentValue);
// fStatusLabel.setText(info);
fStatusControl.setToolTipText(sb.toString());
fStatusControl.redraw();
}
public String getValue() {
return fCurrentValue;
}
@Override
protected void onDispose() {
fStatusControl = null;
super.onDispose();
if (fInitialSWTFont != null) {
fInitialSWTFont.dispose();
fInitialFontName = null;
fInitialSWTFont = null;
}
if (fCurrentSWTFont != null) {
fCurrentSWTFont.dispose();
fCurrentFontName = null;
fCurrentSWTFont = null;
}
}
}