/******************************************************************************* * Copyright (c) 2007 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.internal.ui.viewsupport; import java.util.Iterator; 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.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.graphics.TextStyle; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.TreeItem; /** * Adding owner draw support to a control */ public abstract class OwnerDrawSupport implements Listener { private TextLayout fTextLayout; private final Control fControl; public OwnerDrawSupport(Control control) { fControl= control; fTextLayout= new TextLayout(control.getDisplay()); control.addListener(SWT.PaintItem, this); control.addListener(SWT.EraseItem, this); control.addListener(SWT.Dispose, this); } /** * Return the colored label for the given item. * @param item the item to return the colored label for * @return the colored string */ public abstract ColoredString getColoredLabel(Item item); /** * Return the color for the given style * @param foregroundColorName the name of the color * @param display the current display * @return the color */ public abstract Color getColor(String foregroundColorName, Display display); /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ public void handleEvent(Event event) { if (event.type == SWT.PaintItem) { performPaint(event); } else if (event.type == SWT.EraseItem) { performErase(event); } else if (event.type == SWT.Dispose) { dispose(); } } private void performErase(Event event) { event.detail &= ~SWT.FOREGROUND; } private void performPaint(Event event) { Item item= (Item) event.item; GC gc= event.gc; ColoredString coloredLabel= getColoredLabel(item); boolean isSelected= (event.detail & SWT.SELECTED) != 0 && fControl.isFocusControl(); if (item instanceof TreeItem) { TreeItem treeItem= (TreeItem) item; Image image = treeItem.getImage(event.index); if (image != null) { processImage(image, gc, treeItem.getImageBounds(event.index)); } Rectangle textBounds= treeItem.getTextBounds(event.index); Font font= treeItem.getFont(event.index); processColoredLabel(coloredLabel, gc, textBounds, isSelected, font); Rectangle bounds= treeItem.getBounds(); if ((event.detail & SWT.FOCUSED) != 0) { gc.drawFocus(bounds.x, bounds.y, bounds.width, bounds.height); } } else if (item instanceof TableItem) { TableItem tableItem= (TableItem) item; Image image = tableItem.getImage(event.index); if (image != null) { processImage(image, gc, tableItem.getImageBounds(event.index)); } Rectangle textBounds= tableItem.getTextBounds(event.index); Font font= tableItem.getFont(event.index); processColoredLabel(coloredLabel, gc, textBounds, isSelected, font); Rectangle bounds= tableItem.getBounds(); if ((event.detail & SWT.FOCUSED) != 0) { gc.drawFocus(bounds.x, bounds.y, bounds.width, bounds.height); } } } private void processImage(Image image, GC gc, Rectangle imageBounds) { Rectangle bounds= image.getBounds(); int x= imageBounds.x + Math.max(0, (imageBounds.width - bounds.width) / 2); int y= imageBounds.y + Math.max(0, (imageBounds.height - bounds.height) / 2); gc.drawImage(image, x, y); } private void processColoredLabel(ColoredString richLabel, GC gc, Rectangle textBounds, boolean isSelected, Font font) { String text= richLabel.getString(); fTextLayout.setText(text); fTextLayout.setFont(font); if (!isSelected) { // apply the styled ranges only when element is not selected Display display= (Display) gc.getDevice(); Iterator ranges= richLabel.getRanges(); while (ranges.hasNext()) { ColoredString.StyleRange curr= (ColoredString.StyleRange) ranges.next(); ColoredString.Style style= curr.style; if (style != null) { Color foreground= getColor(style.getForegroundColorName(), display); TextStyle textStyle= new TextStyle(null, foreground, null); fTextLayout.setStyle(textStyle, curr.offset, curr.offset + curr.length - 1); } } } Rectangle bounds= fTextLayout.getBounds(); int x= textBounds.x; int y = textBounds.y + Math.max(0, (textBounds.height - bounds.height) / 2); fTextLayout.draw(gc, x, y); fTextLayout.setText(""); // clear all ranges //$NON-NLS-1$ } public void dispose() { if (fTextLayout != null) { fTextLayout.dispose(); fTextLayout= null; } if (!fControl.isDisposed()) { fControl.removeListener(SWT.PaintItem, this); fControl.removeListener(SWT.EraseItem, this); fControl.removeListener(SWT.Dispose, this); } } }