/* * Copyright (c) 2011, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.tools.ui.internal.viewsupport; import com.google.dart.tools.ui.internal.viewsupport.ColoredString.StyleRange; 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; import java.util.Iterator; /** * 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); } 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); } } /** * 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); /** * 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); /* * (non-Javadoc) * * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ @Override 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 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<StyleRange> ranges = richLabel.getRanges(); while (ranges.hasNext()) { ColoredString.StyleRange curr = 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$ } 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); } }