blob: 92a4a9f49a17c6180a82ca54a84136f2ec0bb73e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package com.google.eclipse.tm.internal.terminal.textcanvas;
import java.util.*;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Display;
import com.google.eclipse.tm.terminal.model.*;
public class StyleMap {
private static final String BLACK = "black";
private static final String WHITE = "white";
private static final String WHITE_FOREGROUND = "white_foreground";
private static final String GRAY = "gray";
private static final String MAGENTA = "magenta";
private static final String CYAN = "cyan";
private static final String YELLOW = "yellow";
private static final String BLUE = "blue";
private static final String GREEN = "green";
private static final String RED = "red";
private static final String PREFIX = "org.eclipse.tm.internal.";
// TODO propagate the name of the font in the FontRegistry
private static final String DEFAULT_FONT_NAME = "terminal.views.view.font.definition";
private String fontName = DEFAULT_FONT_NAME;
private final Map<StyleColor, Color> colorMapForeground = new HashMap<StyleColor, Color>();
private final Map<StyleColor, Color> colorMapBackground = new HashMap<StyleColor, Color>();
private final Map<StyleColor, Color> colorMapIntense = new HashMap<StyleColor, Color>();
private Point charSize;
private final Style defaultStyle;
private boolean invertColors;
private boolean proportional;
private final int[] offsets = new int[256];
private RGB background = new RGB(0, 0, 0);
private RGB foreground = new RGB(229, 229, 229);
private Font font = JFaceResources.getFontRegistry().get(fontName);
StyleMap() {
initColors();
defaultStyle = Style.getStyle(StyleColor.getStyleColor(BLACK), StyleColor.getStyleColor(WHITE));
updateFont();
}
private void initColors() {
initForegroundColors();
initBackgroundColors();
initIntenseColors();
}
private void initForegroundColors() {
if (invertColors) {
setColor(colorMapForeground, WHITE, 0, 0, 0);
setColor(colorMapForeground, WHITE_FOREGROUND, 50, 50, 50);
setColor(colorMapForeground, BLACK, foreground.red, foreground.green, foreground.blue); // set foreground
} else {
setColor(colorMapForeground, WHITE, 255, 255, 255);
setColor(colorMapForeground, WHITE_FOREGROUND, 229, 229, 229);
setColor(colorMapForeground, BLACK, 50, 50, 50);
}
setColor(colorMapForeground, RED, 205, 0, 0);
setColor(colorMapForeground, GREEN, 0, 205, 0);
setColor(colorMapForeground, BLUE, 0, 0, 238);
setColor(colorMapForeground, YELLOW, 205, 205, 0);
setColor(colorMapForeground, CYAN, 0, 205, 205);
setColor(colorMapForeground, MAGENTA, 205, 0, 205);
setColor(colorMapForeground, GRAY, 229, 229, 229);
}
private void initBackgroundColors() {
if (invertColors) {
setColor(colorMapBackground, WHITE, background.red, background.green, background.blue); // set background
setColor(colorMapBackground, WHITE_FOREGROUND, 50, 50, 50); // only used when colors are inverse
setColor(colorMapBackground, BLACK, foreground.red, foreground.green, foreground.blue); // set cursor color
} else {
setColor(colorMapBackground, WHITE, 255, 255, 255);
setColor(colorMapBackground, WHITE_FOREGROUND, 229, 229, 229);
setColor(colorMapBackground, BLACK, 0, 0, 0);
}
setColor(colorMapBackground, RED, 205, 0, 0);
setColor(colorMapBackground, GREEN, 0, 205, 0);
setColor(colorMapBackground, BLUE, 0, 0, 238);
setColor(colorMapBackground, YELLOW, 205, 205, 0);
setColor(colorMapBackground, CYAN, 0, 205, 205);
setColor(colorMapBackground, MAGENTA, 205, 0, 205);
setColor(colorMapBackground, GRAY, 229, 229, 229);
}
private void initIntenseColors() {
if (invertColors) {
setColor(colorMapIntense, WHITE, 127, 127, 127);
setColor(colorMapIntense, WHITE_FOREGROUND, 0, 0, 0); // only used when colors are inverse
setColor(colorMapIntense, BLACK, 255, 255, 255);
} else {
setColor(colorMapIntense, WHITE, 255, 255, 255);
setColor(colorMapIntense, WHITE_FOREGROUND, 255, 255, 255);
setColor(colorMapIntense, BLACK, 0, 0, 0);
}
setColor(colorMapIntense, RED, 255, 0, 0);
setColor(colorMapIntense, GREEN, 0, 255, 0);
setColor(colorMapIntense, BLUE, 92, 92, 255);
setColor(colorMapIntense, YELLOW, 255, 255, 0);
setColor(colorMapIntense, CYAN, 0, 255, 255);
setColor(colorMapIntense, MAGENTA, 255, 0, 255);
setColor(colorMapIntense, GRAY, 255, 255, 255);
}
private void setColor(Map<StyleColor, Color> colorMap, String name, int r, int g, int b) {
String colorName = PREFIX + r + "-" + g + "-" + b;
Color color = JFaceResources.getColorRegistry().get(colorName);
if (color == null) {
JFaceResources.getColorRegistry().put(colorName, new RGB(r, g, b));
color = JFaceResources.getColorRegistry().get(colorName);
}
colorMap.put(StyleColor.getStyleColor(name), color);
colorMap.put(StyleColor.getStyleColor(name.toUpperCase()), color);
}
public Color getForegrondColor(Style style) {
style = defaultIfNull(style);
Map<StyleColor, Color> map = style.isBold() ? colorMapIntense : colorMapForeground;
if (style.isReverse()) {
return getColor(map, style.getBackground());
}
return getColor(map, style.getForground());
}
public Color getBackgroundColor(Style style) {
style = defaultIfNull(style);
if (style.isReverse()) {
return getColor(colorMapBackground, style.getForground());
}
return getColor(colorMapBackground, style.getBackground());
}
Color getColor(Map<StyleColor, Color> map, StyleColor color) {
Color c = map.get(color);
if (c == null) {
c = Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
}
return c;
}
private Style defaultIfNull(Style style) {
if (style == null) {
style = defaultStyle;
}
return style;
}
public void setInvertedColors(boolean invert) {
if (invert == invertColors) {
return;
}
invertColors = invert;
initColors();
}
public Font getFont(Style style) {
style = defaultIfNull(style);
FontData fontDatas[] = font.getFontData();
FontData data = fontDatas[0];
if (style.isBold()) {
return new Font(font.getDevice(), data.getName(), data.getHeight(), data.getStyle() | SWT.BOLD);
}
if (style.isUnderline()) {
return new Font(font.getDevice(), data.getName(), data.getHeight(), data.getStyle() | SWT.ITALIC);
}
return font;
}
public Font getFont() {
return font;
}
public int getFontWidth() {
return charSize.x;
}
public int getFontHeight() {
return charSize.y;
}
public void updateFont() {
Display display = Display.getCurrent();
GC gc = new GC(display);
if (JFaceResources.getFontRegistry().hasValueFor(DEFAULT_FONT_NAME)) {
fontName = DEFAULT_FONT_NAME;
} else if (JFaceResources.getFontRegistry().hasValueFor("REMOTE_COMMANDS_VIEW_FONT")) {
// try RSE Shell View Font
fontName = "REMOTE_COMMANDS_VIEW_FONT";
} else {
// fall back to "basic jface text font"
fontName = "org.eclipse.jface.textfont";
}
gc.setFont(getFont());
charSize = gc.textExtent("W");
proportional = false;
for (char c = ' '; c <= '~'; c++) {
// Consider only the first 128 chars for deciding if a font is proportional.
if (measureChar(gc, c, true)) {
proportional = true;
}
}
// TODO should we also consider the upper 128 chars?
for (char c = ' ' + 128; c <= '~' + 128; c++) {
measureChar(gc, c, false);
}
if (proportional) {
charSize.x -= 2; // Works better on small fonts.
}
for (int i = 0; i < offsets.length; i++) {
offsets[i] = (charSize.x - offsets[i]) / 2;
}
if (!proportional) {
// Measure font in boldface, too, and if wider then treat like proportional.
gc.setFont(getFont(defaultStyle.setBold(true)));
Point charSizeBold = gc.textExtent("W");
if (charSize.x != charSizeBold.x) {
proportional = true;
}
}
gc.dispose();
}
private boolean measureChar(GC gc, char c, boolean updateMax) {
boolean proportional = false;
Point extent = gc.textExtent(String.valueOf(c));
if (extent.x > 0 && extent.y > 0 && (charSize.x != extent.x || charSize.y != extent.y)) {
proportional = true;
if (updateMax) {
charSize.x = Math.max(charSize.x, extent.x);
charSize.y = Math.max(charSize.y, extent.y);
}
}
offsets[c] = extent.x;
return proportional;
}
public boolean isFontProportional() {
return proportional;
}
/**
* Return the offset in pixels required to center a given character.
*
* @param c the character to measure.
* @return the offset in x direction to center this character.
*/
public int getCharOffset(char c) {
if (c >= offsets.length) {
return 0;
}
return offsets[c];
}
public void setColors(RGB background, RGB foreground) {
this.background = background;
this.foreground = foreground;
initColors();
}
public void setFont(Font font) {
this.font = font;
}
}