| /******************************************************************************* |
| * 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(); |
| } |
| } |