blob: 91e43bdc2e5cdd6ec4d13ace27cd86b8206c9b2a [file] [log] [blame]
package org.eclipse.ui.internal.misc;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
/**
* A Label which supports aligned text and/or an image and different border styles.
* If there is not enough space a SmartLabel uses the following strategy to fit the information into the
* available space:
* <pre>
* - ignores the indent in left align mode
* - ignores the image and the gap
* - shortens the text by replacing the center portion of the label with an ellipsis
* - shortens the text by removing the center portion of the label
* </pre>
*/
public class ActivatorItem extends Canvas implements PaintListener,
MouseListener, DisposeListener
{
protected String fText;
protected Image fImage;
static protected Image fCloseImage;
static protected int fInstanceCount;
protected ActivatorBar fParent;
protected boolean fPressed = false;
final static int GAP = 5;
/**
* Create a SmartLabel with the given borderStyle as a child of parent.
*/
public ActivatorItem(ActivatorBar parent) {
super(parent, 0);
addInstance();
fParent = parent;
addPaintListener(this);
addMouseListener(this);
addDisposeListener(this);
fParent.addItem(this);
}
/**
* Add an instance. Create the close image.
*/
static private void addInstance() {
if (fInstanceCount == 0) {
ImageDescriptor desc = WorkbenchImages.getImageDescriptor(
IWorkbenchGraphicConstants.IMG_LCL_CLOSE_VIEW);
if (desc != null)
fCloseImage = desc.createImage();
}
++ fInstanceCount;
}
//---- layout
/**
* Compute the size.
* @private
*/
public Point computeSize(int wHint, int hHint, boolean changed) {
Point e= getMinimumSize();
if (wHint != SWT.DEFAULT)
e.x= wHint;
if (hHint != SWT.DEFAULT)
e.y= hHint;
return e;
}
/**
* Dispose the control.
*/
public void dispose() {
super.dispose();
fParent.removeItem(this);
}
//---- private stuff
/**
* Draw a rectangle in the given colors.
* @private
*/
private static void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) {
gc.setForeground(topleft);
gc.drawLine(x, y, x+w-1, y);
gc.drawLine(x, y, x, y+h-1);
gc.setForeground(bottomright);
gc.drawLine(x+w, y, x+w, y+h);
gc.drawLine(x, y+h, x+w, y+h);
}
/**
* Return the SmartLabel's image or <code>null</code>.
*/
public Image getImage() {
return fImage;
}
/**
* Compute the minimum size.
* @private
*/
public Point getMinimumSize() {
Point size= new Point(0, 22);
// get image extent.
if (fImage != null) {
Rectangle r= fImage.getBounds();
size.x = r.width;
}
// get text extent.
if (fText != null && fText.length() > 0) {
GC gc= new GC(this);
Point e= gc.textExtent(fText);
size.x += e.x + 2 * GAP;
gc.dispose();
}
// get close button extent.
if (fCloseImage != null) {
Rectangle r= fCloseImage.getBounds();
size.x += r.width + 2;
}
return size;
}
//---- setters & getters
/**
* Return the SmartLabel's label text.
*/
public String getText() {
return fText;
}
/**
* mouseDoubleClick method comment.
*/
public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {}
/**
* mouseDown method comment.
*/
public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
if (e.button == 1) {
int textExtent = 100000;
if (fPressed && (fCloseImage != null))
textExtent = getClientArea().width - fCloseImage.getBounds().width - 4;
if (e.x < textExtent)
fParent.itemSelected(this);
else
fParent.itemClosePressed(this);
}
}
/**
* mouseUp method comment.
*/
public void mouseUp(org.eclipse.swt.events.MouseEvent e) {}
/**
* Paint the Label's border.
*/
protected void paintBorder(GC gc, Rectangle r) {
Display disp= getDisplay();
Color c1= null;
Color c2= null;
if (fPressed) {
c1= disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
c2= disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
} else {
c1= disp.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
c2= disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
}
if (c1 != null && c2 != null) {
gc.setLineWidth(1);
drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2);
}
}
/**
* Paint the Label's border.
*/
protected void paintBorder(GC gc, Rectangle r, boolean bPressed) {
Display disp= getDisplay();
Color c1= null;
Color c2= null;
if (bPressed) {
c1= disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
c2= disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
} else {
c1= disp.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
c2= disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
}
if (c1 != null && c2 != null) {
gc.setLineWidth(1);
drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2);
}
}
//---- painting
/**
* Implements PaintListener.
* @private
*/
public void paintControl(PaintEvent event) {
GC gc= event.gc;
Rectangle r= getClientArea();
// Draw background.
if (fPressed) {
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
gc.fillRectangle(r);
} else
ActivatorBar.paintGradient(getDisplay(), gc, r);
// Draw border.
paintBorder(gc, r);
// Get image extent.
int imageWidth = 0;
Image image= fImage;
Rectangle imageBounds = null;
if (image != null) {
imageBounds = image.getBounds();
imageWidth = image.getBounds().width;
}
// Get text extent.
Point textExtent = null;
if (fText != null && fText.length() > 0)
textExtent= gc.textExtent(fText);
// Get close button extent.
Rectangle closeBox = new Rectangle(0, 0, 0, 0);
if (fCloseImage != null) {
int width = fCloseImage.getBounds().width + 2;
closeBox = new Rectangle(r.x + r.width - width, r.y,
width, r.height);
}
// Shorten text as required.
boolean shortenText= false;
if (fText != null) {
int availableWidth= r.width - 2 * GAP - imageWidth - closeBox.width;
if (textExtent.x > availableWidth) {
image = null;
imageWidth = 0;
availableWidth= r.width - 2 * GAP - imageWidth - closeBox.width;
if (textExtent.x > availableWidth) {
shortenText= true;
}
}
}
String t= fText;
if (shortenText) {
int availableWidth= r.width - 2 * GAP - imageWidth - closeBox.width;
t= shortenText(gc, fText, availableWidth);
textExtent.x= gc.textExtent(t).x;
setToolTipText(fText);
} else {
setToolTipText(null);
}
// draw the image
int x= r.x;
if (image != null) {
gc.drawImage(image, 0, 0, imageBounds.width, imageBounds.height,
x, (r.height-imageBounds.height)/2, imageBounds.width, imageBounds.height);
x+= imageBounds.width;
}
// draw the text
if (t != null) {
x+= GAP;
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
gc.drawText(t, x, r.y + (r.height - textExtent.y) / 2, true);
}
// draw the close box.
if (fPressed && (fCloseImage != null)) {
closeBox.x += 1;
closeBox.width -= 2;
closeBox.y += 1;
closeBox.height -= 2;
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
gc.fillRectangle(closeBox);
Rectangle imgBounds = fCloseImage.getBounds();
gc.drawImage(fCloseImage, 0, 0, imgBounds.width, imgBounds.height,
closeBox.x + (closeBox.width-imgBounds.width) / 2,
closeBox.y + (closeBox.height-imgBounds.height) / 2,
imgBounds.width, imgBounds.height);
paintBorder(gc, closeBox, false);
}
}
/**
* Remove an instance. Dispose the close image.
*/
static private void removeInstance() {
-- fInstanceCount;
if (fInstanceCount <= 0) {
if (fCloseImage != null) {
fCloseImage.dispose();
fCloseImage = null;
}
}
}
/**
* Sets the widget's font to the given value and forces
* a redraw of the widget.
*/
public void setFont(Font font) {
super.setFont(font);
redraw();
}
/**
* Set the SmartLabel's Image.
* The value <code>null</code> clears it.
*/
public void setImage(Image image) {
if (image != fImage) {
fImage= image;
redraw();
}
}
/**
* Sets the control state.
*/
public void setPressed(boolean pressed) {
fPressed = pressed;
redraw();
}
/**
* Set the SmartLabel's label text.
* The value <code>null</code> clears it.
*/
public void setText(String text) {
if (text == null)
text= "";//$NON-NLS-1$
if (!text.equals(fText)) {
fText= text;
}
fParent.layout();
redraw();
}
/**
* Shorten the given text <code>t</code> so that its length doesn't exceed
* the given width. The default implementation replaces characters in the
* center of the original string with an ellipsis ("...").
* Override if you need a different strategy.
*/
protected String shortenText(GC gc, String t, int width) {
String ellipsis= "...";//$NON-NLS-1$
int w= gc.textExtent(ellipsis).x;
int l= t.length();
int pivot= l/2;
int s= pivot;
int e= pivot+1;
while (s >= 0 && e < l) {
String s1= t.substring(0, s);
String s2= t.substring(e, l);
int l1= gc.textExtent(s1).x;
int l2= gc.textExtent(s2).x;
if (l1+w+l2 < width) {
t= s1 + ellipsis + s2;
break;
}
s--;
e++;
}
return t;
}
/**
* widgetDisposed method comment.
*/
public void widgetDisposed(org.eclipse.swt.events.DisposeEvent e) {
if (fImage != null)
fImage.dispose();
removeInstance();
}
}