/*******************************************************************************
* Copyright (c) 2001, 2015 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
* Mariot Chauvin <mariot.chauvin@obeo.fr> - bug 259553
* Amit Joglekar <joglekar@us.ibm.com> - Support for dynamic images (bug 385795)
* Obeo - Contribution to the EEF project
*******************************************************************************/
package org.eclipse.eef.properties.ui.internal.page.propertylist;
import org.eclipse.eef.properties.ui.api.IEEFTabItem;
import org.eclipse.eef.properties.ui.internal.page.EEFTabbedPropertyComposite;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
/**
* One of the tabs in the tabbed property list.
*
* @author Anthony Hunter
* @author Stephane Begaudeau
*/
public class EEFListElement extends Canvas {
/**
* The tab.
*/
private IEEFTabItem tab;
/**
* The index.
*/
private int index;
/**
* The tabbed property list.
*/
private EEFTabbedPropertyList tabbedPropertyList;
/**
* Indicates if the tab is selected.
*/
private boolean selected;
/**
* Indicates if the tab is hovered.
*/
private boolean hover;
/**
* Array of the dynamic images to use.
*/
private Image[] dynamicImages;
/**
* The color of the text.
*/
private Color textColor;
/**
* The constructor.
*
* @param parent
* The parent composite
* @param tab
* The tab
* @param index
* The index of the tab
* @param tabbedPropertyList
* The tabbed property list
*/
public EEFListElement(Composite parent, IEEFTabItem tab, int index, EEFTabbedPropertyList tabbedPropertyList) {
super(parent, SWT.NO_FOCUS);
this.tab = tab;
this.index = index;
this.tabbedPropertyList = tabbedPropertyList;
this.textColor = this.tabbedPropertyList.getColorHolder().getWidgetForeground();
this.addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent event) {
EEFListElement.this.paint(event);
}
});
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent event) {
EEFListElement.this.mouseUp(event);
}
});
this.addMouseMoveListener(new MouseMoveListener() {
@Override
public void mouseMove(MouseEvent event) {
if (!EEFListElement.this.hover) {
EEFListElement.this.hover = true;
EEFListElement.this.redraw();
}
}
});
this.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseExit(MouseEvent event) {
EEFListElement.this.hover = false;
EEFListElement.this.redraw();
}
});
}
/**
* The constructor.
*
* @param parent
* The parent composite
* @param tab
* The tab
* @param dynamicImageCount
* The number of dynamic images
* @param index
* The index of the tab
* @param tabbedPropertyList
* The tabbed property list
*/
public EEFListElement(Composite parent, IEEFTabItem tab, int dynamicImageCount, int index, EEFTabbedPropertyList tabbedPropertyList) {
this(parent, tab, index, tabbedPropertyList);
this.dynamicImages = new Image[dynamicImageCount];
for (int i = 0; i < dynamicImageCount; i++) {
this.dynamicImages[i] = null;
}
}
/**
* Handle the mouse up event.
*
* @param event
* The mouse up event
*/
protected void mouseUp(MouseEvent event) {
if (!selected) {
this.tabbedPropertyList.select(this.index);
/*
* We set focus to the tabbed property composite so that focus is moved to the appropriate widget in the
* section.
*/
Composite tabbedPropertyComposite = getParent();
while (!(tabbedPropertyComposite instanceof EEFTabbedPropertyComposite)) {
tabbedPropertyComposite = tabbedPropertyComposite.getParent();
}
tabbedPropertyComposite.setFocus();
}
}
/**
* Set selected value for this element.
*
* @param selected
* the selected value.
*/
public void setSelected(boolean selected) {
this.selected = selected;
redraw();
}
/**
* Show the dynamic image at specified index in dynamicImages array. The image width should not be more than 16
* pixels. The caller is responsible for loading the image appropriately and managing it's resources.
*
* @param i
* The index of the image
* @param image
* The image to show
*/
public void showDynamicImage(int i, Image image) {
if (i >= 0 && i < dynamicImages.length) {
if (dynamicImages[i] != image) {
dynamicImages[i] = image;
redraw();
}
}
}
/**
* Hide the dynamic image at specified index in dynamicImages array. The caller is responsible for managing image
* resources and disposing it appropriately.
*
* @param i
* The index of the image to hide
*/
public void hideDynamicImage(int i) {
if (i >= 0 && i < dynamicImages.length) {
if (dynamicImages[i] != null) {
dynamicImages[i] = null;
redraw();
}
}
}
/**
* Sets color to be used for drawing tab label text. The caller is responsible for managing the color's resources
* and disposing it appropriately after setDefaultTextColor() is later invoked.
*
* @param textColor
* The color of the text
*/
public void setTextColor(Color textColor) {
if (textColor != null && !this.textColor.equals(textColor)) {
this.textColor = textColor;
redraw();
}
}
/**
* Sets default color for tab label text.
*/
public void setDefaultTextColor() {
Color widgetForeground = this.tabbedPropertyList.getColorHolder().getWidgetForeground();
if (!this.textColor.equals(widgetForeground)) {
this.textColor = widgetForeground;
redraw();
}
}
/**
* Paint the element.
*
* @param e
* the paint event.
*/
@SuppressWarnings({ "checkstyle:magicnumber" })
private void paint(PaintEvent e) {
/*
* draw the top two lines of the tab, same for selected, hover and default
*/
Rectangle bounds = getBounds();
e.gc.setForeground(this.tabbedPropertyList.getColorHolder().getWidgetNormalShadow());
e.gc.drawLine(0, 0, bounds.width - 1, 0);
e.gc.setForeground(this.tabbedPropertyList.getColorHolder().getListBackground());
e.gc.drawLine(0, 1, bounds.width - 1, 1);
/* draw the fill in the tab */
if (selected) {
e.gc.setBackground(this.tabbedPropertyList.getColorHolder().getListBackground());
e.gc.fillRectangle(0, 2, bounds.width, bounds.height - 1);
} else if (hover && tab.isIndented()) {
e.gc.setBackground(this.tabbedPropertyList.getColorHolder().getIndentedHoverBackground());
e.gc.fillRectangle(0, 2, bounds.width - 1, bounds.height - 1);
} else if (hover) {
e.gc.setForeground(this.tabbedPropertyList.getColorHolder().getHoverGradientStart());
e.gc.setBackground(this.tabbedPropertyList.getColorHolder().getHoverGradientEnd());
e.gc.fillGradientRectangle(0, 2, bounds.width - 1, bounds.height - 1, true);
} else if (tab.isIndented()) {
e.gc.setBackground(this.tabbedPropertyList.getColorHolder().getIndentedDefaultBackground());
e.gc.fillRectangle(0, 2, bounds.width - 1, bounds.height - 1);
} else {
e.gc.setForeground(this.tabbedPropertyList.getColorHolder().getDefaultGradientStart());
e.gc.setBackground(this.tabbedPropertyList.getColorHolder().getDefaultGradientEnd());
e.gc.fillGradientRectangle(0, 2, bounds.width - 1, bounds.height - 1, true);
}
if (!selected) {
e.gc.setForeground(this.tabbedPropertyList.getColorHolder().getWidgetNormalShadow());
e.gc.drawLine(bounds.width - 1, 1, bounds.width - 1, bounds.height + 1);
}
/*
* Add INDENT pixels to the left as a margin.
*/
int textIndent = EEFTabbedPropertyList.INDENT;
FontMetrics fm = e.gc.getFontMetrics();
int height = fm.getHeight();
int textMiddle = (bounds.height - height) / 2;
if (selected && tab.getImage() != null && !tab.getImage().isDisposed()) {
/* draw the icon for the selected tab */
if (tab.isIndented()) {
textIndent = textIndent + EEFTabbedPropertyList.INDENT;
} else {
textIndent = textIndent - 3;
}
e.gc.drawImage(tab.getImage(), textIndent, textMiddle - 1);
textIndent = textIndent + 16 + 4;
} else if (tab.isIndented()) {
textIndent = textIndent + EEFTabbedPropertyList.INDENT;
}
/* draw the text */
e.gc.setForeground(textColor);
if (selected) {
/* selected tab is bold font */
e.gc.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
}
e.gc.drawText(tab.getText(), textIndent, textMiddle, true);
if (((EEFTabbedPropertyList) getParent()).getFocus() && selected) {
/* draw a line if the tab has focus */
Point point = e.gc.textExtent(tab.getText());
e.gc.drawLine(textIndent, bounds.height - 4, textIndent + point.x, bounds.height - 4);
}
/* Draw dynamic images, if any */
boolean hasDynamicImage = false;
for (int i = 0; i < dynamicImages.length; i++) {
Image dynamicImage = dynamicImages[i];
if (dynamicImage != null && !dynamicImage.isDisposed()) {
hasDynamicImage = true;
break;
}
}
if (hasDynamicImage) {
int drawPosition = textIndent + e.gc.textExtent(tab.getText()).x + 4;
boolean addSpace = false;
for (int i = 0; i < dynamicImages.length; i++) {
Image dynamicImage = dynamicImages[i];
if (dynamicImage != null && !dynamicImage.isDisposed()) {
if (addSpace) {
drawPosition = drawPosition + 3;
}
e.gc.drawImage(dynamicImage, drawPosition, textMiddle - 1);
drawPosition = drawPosition + 16;
addSpace = true;
}
}
}
/* draw the bottom line on the tab for selected and default */
if (!hover) {
e.gc.setForeground(this.tabbedPropertyList.getColorHolder().getListBackground());
e.gc.drawLine(0, bounds.height - 1, bounds.width - 2, bounds.height - 1);
}
}
/**
* Get the tab item.
*
* @return the tab item.
*/
public IEEFTabItem getTabItem() {
return tab;
}
@Override
public String toString() {
return tab.getText();
}
}