blob: bde87d14bedfa7cc283e91a141537c2e56f07d91 [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
*
* Contributors:
* Michael Scharf (Wind River) - initial API and implementation
* Michael Scharf (Wind River) - [205260] Terminal does not take the font from the preferences
* Michael Scharf (Wind River) - [209746] There are cases where some colors not displayed correctly
* Michael Scharf (Wind River) - [206328] Terminal does not draw correctly with proportional fonts
* Martin Oberhuber (Wind River) - [247700] Terminal uses ugly fonts in JEE package
* Martin Oberhuber (Wind River) - [335358] Fix Terminal color definition
*******************************************************************************/
package org.eclipse.tm.internal.terminal.textcanvas;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.tm.terminal.model.Style;
import org.eclipse.tm.terminal.model.StyleColor;
import java.util.HashMap;
import java.util.Map;
public class StyleMap {
private static final String BLACK = "black"; //$NON-NLS-1$
private static final String WHITE = "white"; //$NON-NLS-1$
private static final String WHITE_FOREGROUND = "white_foreground"; //$NON-NLS-1$
private static final String GRAY = "gray"; //$NON-NLS-1$
private static final String MAGENTA = "magenta"; //$NON-NLS-1$
private static final String CYAN = "cyan"; //$NON-NLS-1$
private static final String YELLOW = "yellow"; //$NON-NLS-1$
private static final String BLUE = "blue"; //$NON-NLS-1$
private static final String GREEN = "green"; //$NON-NLS-1$
private static final String RED = "red"; //$NON-NLS-1$
private static final String PREFIX = "org.eclipse.tm.internal."; //$NON-NLS-1$
// TODO propagate the name of the font in the FontRegistry
private static final String fDefaultFontName="terminal.views.view.font.definition"; //$NON-NLS-1$
String fFontName=fDefaultFontName;
Map fColorMapForeground=new HashMap();
Map fColorMapBackground=new HashMap();
Map fColorMapIntense=new HashMap();
Map fFontMap=new HashMap();
private Point fCharSize;
private final Style fDefaultStyle;
private boolean fInvertColors;
private boolean fProportional;
private final int[] fOffsets=new int[256];
private RGB background = new RGB(0, 0, 0);
private RGB foreground = new RGB(229, 229, 229);
StyleMap() {
initColors();
fDefaultStyle=Style.getStyle(StyleColor.getStyleColor(BLACK),StyleColor.getStyleColor(WHITE));
updateFont();
}
private void initColors() {
initForegroundColors();
initBackgroundColors();
initIntenseColors();
}
private void initForegroundColors() {
if(fInvertColors) {
setColor(fColorMapForeground, WHITE, 0, 0, 0);
setColor(fColorMapForeground, WHITE_FOREGROUND, 50, 50, 50);
setColor(fColorMapForeground, BLACK, foreground.red, foreground.green, foreground.blue); // set foreground
} else {
setColor(fColorMapForeground, WHITE, 255, 255, 255);
setColor(fColorMapForeground, WHITE_FOREGROUND, 229, 229, 229);
setColor(fColorMapForeground, BLACK, 50, 50, 50);
}
setColor(fColorMapForeground, RED, 205, 0, 0);
setColor(fColorMapForeground, GREEN, 0, 205, 0);
setColor(fColorMapForeground, BLUE, 0, 0, 238);
setColor(fColorMapForeground, YELLOW, 205, 205, 0);
setColor(fColorMapForeground, CYAN, 0, 205, 205);
setColor(fColorMapForeground, MAGENTA, 205, 0, 205);
setColor(fColorMapForeground, GRAY, 229, 229, 229);
}
private void initBackgroundColors() {
if(fInvertColors) {
setColor(fColorMapBackground, WHITE, background.red, background.green, background.blue); // set background
setColor(fColorMapBackground, WHITE_FOREGROUND, 50, 50, 50); // only used when colors are inverse
setColor(fColorMapBackground, BLACK, 255, 255, 255); // set cursor color
} else {
setColor(fColorMapBackground, WHITE, 255, 255, 255);
setColor(fColorMapBackground, WHITE_FOREGROUND, 229, 229, 229);
setColor(fColorMapBackground, BLACK, 0, 0, 0);
}
setColor(fColorMapBackground, RED, 205, 0, 0);
setColor(fColorMapBackground, GREEN, 0, 205, 0);
setColor(fColorMapBackground, BLUE, 0, 0, 238);
setColor(fColorMapBackground, YELLOW, 205, 205, 0);
setColor(fColorMapBackground, CYAN, 0, 205, 205);
setColor(fColorMapBackground, MAGENTA, 205, 0, 205);
setColor(fColorMapBackground, GRAY, 229, 229, 229);
}
private void initIntenseColors() {
if(fInvertColors) {
setColor(fColorMapIntense, WHITE, 127, 127, 127);
setColor(fColorMapIntense, WHITE_FOREGROUND, 0, 0, 0); // only used when colors are inverse
setColor(fColorMapIntense, BLACK, 255, 255, 255);
} else {
setColor(fColorMapIntense, WHITE, 255, 255, 255);
setColor(fColorMapIntense, WHITE_FOREGROUND, 255, 255, 255);
setColor(fColorMapIntense, BLACK, 0, 0, 0);
}
setColor(fColorMapIntense, RED, 255, 0, 0);
setColor(fColorMapIntense, GREEN, 0, 255, 0);
setColor(fColorMapIntense, BLUE, 92, 92, 255);
setColor(fColorMapIntense, YELLOW, 255, 255, 0);
setColor(fColorMapIntense, CYAN, 0, 255, 255);
setColor(fColorMapIntense, MAGENTA, 255, 0, 255);
setColor(fColorMapIntense, GRAY, 255, 255, 255);
}
private void setColor(Map colorMap, String name, int r, int g, int b) {
String colorName=PREFIX+r+"-"+g+"-"+b; //$NON-NLS-1$//$NON-NLS-2$
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 map = style.isBold() ? fColorMapIntense : fColorMapForeground;
//Map map = fColorMapForeground;
if(style.isReverse()) {
return getColor(map ,style.getBackground());
} else {
return getColor(map ,style.getForground());
}
}
public Color getBackgroundColor(Style style) {
style = defaultIfNull(style);
if(style.isReverse()) {
return getColor(fColorMapBackground,style.getForground());
} else {
return getColor(fColorMapBackground,style.getBackground());
}
}
Color getColor(Map map,StyleColor color) {
Color c=(Color) map.get(color);
if(c==null) {
c=Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
}
return c;
}
private Style defaultIfNull(Style style) {
if(style==null) {
style=fDefaultStyle;
}
return style;
}
public void setInvertedColors(boolean invert) {
if(invert==fInvertColors) {
return;
}
fInvertColors=invert;
initColors();
}
// static Font getBoldFont(Font font) {
// FontData fontDatas[] = font.getFontData();
// FontData data = fontDatas[0];
// return new Font(Display.getCurrent(), data.getName(), data.getHeight(), data.getStyle()|SWT.BOLD);
// }
public Font getFont(Style style) {
style = defaultIfNull(style);
if(style.isBold()) {
return JFaceResources.getFontRegistry().getBold(fFontName);
} else if(style.isUnderline()) {
return JFaceResources.getFontRegistry().getItalic(fFontName);
}
return JFaceResources.getFontRegistry().get(fFontName);
}
public Font getFont() {
return JFaceResources.getFontRegistry().get(fFontName);
}
public int getFontWidth() {
return fCharSize.x;
}
public int getFontHeight() {
return fCharSize.y;
}
public void updateFont() {
Display display=Display.getCurrent();
GC gc = new GC (display);
if (JFaceResources.getFontRegistry().hasValueFor(fDefaultFontName)) {
fFontName = fDefaultFontName;
} else if (JFaceResources.getFontRegistry().hasValueFor("REMOTE_COMMANDS_VIEW_FONT")) { //$NON-NLS-1$
//try RSE Shell View Font
fFontName = "REMOTE_COMMANDS_VIEW_FONT"; //$NON-NLS-1$
} else {
//fall back to "basic jface text font"
fFontName = "org.eclipse.jface.textfont"; //$NON-NLS-1$
}
gc.setFont(getFont());
fCharSize = gc.textExtent ("W"); //$NON-NLS-1$
fProportional=false;
for (char c = ' '; c <= '~'; c++) {
// consider only the first 128 chars for deciding if a font
// is proportional
if(measureChar(gc, c, true)) {
fProportional=true;
}
}
// TODO should we also consider the upper 128 chars??
for (char c = ' '+128; c <= '~'+128; c++) {
measureChar(gc, c,false);
}
if(fProportional) {
fCharSize.x-=2; //works better on small fonts
}
for (int i = 0; i < fOffsets.length; i++) {
fOffsets[i]=(fCharSize.x-fOffsets[i])/2;
}
if(!fProportional) {
//measure font in boldface, too, and if wider then treat like proportional
gc.setFont(getFont(fDefaultStyle.setBold(true)));
Point charSizeBold = gc.textExtent("W"); //$NON-NLS-1$
if (fCharSize.x != charSizeBold.x) {
fProportional=true;
}
}
gc.dispose ();
}
/**
* @param gc
* @param c
* @param updateMax
* @return true if the the font is proportional
*/
private boolean measureChar(GC gc, char c, boolean updateMax) {
boolean proportional=false;
Point ext=gc.textExtent(String.valueOf(c));
if(ext.x>0 && ext.y>0 && (fCharSize.x!=ext.x || fCharSize.y!=ext.y)) {
proportional=true;
if(updateMax) {
fCharSize.x=Math.max(fCharSize.x, ext.x);
fCharSize.y=Math.max(fCharSize.y, ext.y);
}
}
fOffsets[c]=ext.x;
return proportional;
}
public boolean isFontProportional() {
return fProportional;
}
/**
* 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>=fOffsets.length) {
return 0;
}
return fOffsets[c];
}
public void resetColors(RGB background, RGB foreground) {
this.background = background;
this.foreground = foreground;
initColors();
}
}