blob: cfbfe219f18ed45f5ba508c5d72b20d2ef3eaa3e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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
* Chriss Gross (schtoo@schtoo.com) - fix for 61670
*******************************************************************************/
package org.eclipse.ui.internal.forms.widgets;
import java.text.BreakIterator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.ColumnLayout;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ILayoutExtension;
public class FormUtil {
public static final String PLUGIN_ID = "org.eclipse.ui.forms"; //$NON-NLS-1$
static final int H_SCROLL_INCREMENT = 5;
static final int V_SCROLL_INCREMENT = 64;
public static final String DEBUG = PLUGIN_ID + "/debug"; //$NON-NLS-1$
public static final String DEBUG_TEXT = DEBUG + "/text"; //$NON-NLS-1$
public static final String DEBUG_TEXTSIZE = DEBUG + "/textsize"; //$NON-NLS-1$
public static final String DEBUG_FOCUS = DEBUG + "/focus"; //$NON-NLS-1$
public static final String FOCUS_SCROLLING = "focusScrolling"; //$NON-NLS-1$
public static Text createText(Composite parent, String label,
FormToolkit factory) {
return createText(parent, label, factory, 1);
}
public static Text createText(Composite parent, String label,
FormToolkit factory, int span) {
factory.createLabel(parent, label);
Text text = factory.createText(parent, ""); //$NON-NLS-1$
int hfill = span == 1 ? GridData.FILL_HORIZONTAL
: GridData.HORIZONTAL_ALIGN_FILL;
GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
gd.horizontalSpan = span;
text.setLayoutData(gd);
return text;
}
public static Text createText(Composite parent, String label,
FormToolkit factory, int span, int style) {
Label l = factory.createLabel(parent, label);
if ((style & SWT.MULTI) != 0) {
GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
l.setLayoutData(gd);
}
Text text = factory.createText(parent, "", style); //$NON-NLS-1$
int hfill = span == 1 ? GridData.FILL_HORIZONTAL
: GridData.HORIZONTAL_ALIGN_FILL;
GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
gd.horizontalSpan = span;
text.setLayoutData(gd);
return text;
}
public static Text createText(Composite parent, FormToolkit factory,
int span) {
Text text = factory.createText(parent, ""); //$NON-NLS-1$
int hfill = span == 1 ? GridData.FILL_HORIZONTAL
: GridData.HORIZONTAL_ALIGN_FILL;
GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
gd.horizontalSpan = span;
text.setLayoutData(gd);
return text;
}
public static int computeMinimumWidth(GC gc, String text) {
BreakIterator wb = BreakIterator.getWordInstance();
wb.setText(text);
int last = 0;
int width = 0;
for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
String word = text.substring(last, loc);
Point extent = gc.textExtent(word);
width = Math.max(width, extent.x);
last = loc;
}
String lastWord = text.substring(last);
Point extent = gc.textExtent(lastWord);
width = Math.max(width, extent.x);
return width;
}
public static Point computeWrapSize(GC gc, String text, int wHint) {
BreakIterator wb = BreakIterator.getWordInstance();
wb.setText(text);
FontMetrics fm = gc.getFontMetrics();
int lineHeight = fm.getHeight();
int saved = 0;
int last = 0;
int height = lineHeight;
int maxWidth = 0;
for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
String word = text.substring(saved, loc);
Point extent = gc.textExtent(word);
if (extent.x > wHint) {
// overflow
saved = last;
height += extent.y;
} else {
maxWidth = Math.max(maxWidth, extent.x);
}
last = loc;
}
return new Point(maxWidth, height);
}
public static void paintWrapText(GC gc, String text, Rectangle bounds) {
paintWrapText(gc, text, bounds, false);
}
public static void paintWrapText(GC gc, String text, Rectangle bounds,
boolean underline) {
BreakIterator wb = BreakIterator.getWordInstance();
wb.setText(text);
FontMetrics fm = gc.getFontMetrics();
int lineHeight = fm.getHeight();
int descent = fm.getDescent();
int saved = 0;
int last = 0;
int y = bounds.y;
int width = bounds.width;
for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
String line = text.substring(saved, loc);
Point extent = gc.textExtent(line);
if (extent.x > width) {
// overflow
String prevLine = text.substring(saved, last);
gc.drawText(prevLine, bounds.x, y, true);
if (underline) {
Point prevExtent = gc.textExtent(prevLine);
int lineY = y + lineHeight - descent + 1;
gc
.drawLine(bounds.x, lineY, bounds.x + prevExtent.x,
lineY);
}
saved = last;
y += lineHeight;
}
last = loc;
}
// paint the last line
String lastLine = text.substring(saved, last);
gc.drawText(lastLine, bounds.x, y, true);
if (underline) {
int lineY = y + lineHeight - descent + 1;
Point lastExtent = gc.textExtent(lastLine);
gc.drawLine(bounds.x, lineY, bounds.x + lastExtent.x, lineY);
}
}
public static ScrolledComposite getScrolledComposite(Control c) {
Composite parent = c.getParent();
while (parent != null) {
if (parent instanceof ScrolledComposite) {
return (ScrolledComposite) parent;
}
parent = parent.getParent();
}
return null;
}
public static void ensureVisible(Control c) {
ScrolledComposite scomp = getScrolledComposite(c);
if (scomp != null) {
Object data = scomp.getData(FOCUS_SCROLLING);
if (data == null || !data.equals(Boolean.FALSE))
FormUtil.ensureVisible(scomp, c);
}
}
public static void ensureVisible(ScrolledComposite scomp, Control control) {
Point controlSize = control.getSize();
Point controlOrigin = getControlLocation(scomp, control);
ensureVisible(scomp, controlOrigin, controlSize);
}
public static void ensureVisible(ScrolledComposite scomp,
Point controlOrigin, Point controlSize) {
Rectangle area = scomp.getClientArea();
Point scompOrigin = scomp.getOrigin();
int x = scompOrigin.x;
int y = scompOrigin.y;
// horizontal right, but only if the control is smaller
// than the client area
if (controlSize.x < area.width
&& (controlOrigin.x + controlSize.x > scompOrigin.x
+ area.width)) {
x = controlOrigin.x + controlSize.x - area.width;
}
// horizontal left - make sure the left edge of
// the control is showing
if (controlOrigin.x < x) {
if (controlSize.x < area.width)
x = controlOrigin.x + controlSize.x - area.width;
else
x = controlOrigin.x;
}
// vertical bottom
if (controlSize.y < area.height
&& (controlOrigin.y + controlSize.y > scompOrigin.y
+ area.height)) {
y = controlOrigin.y + controlSize.y - area.height;
}
// vertical top - make sure the top of
// the control is showing
if (controlOrigin.y < y) {
if (controlSize.y < area.height)
y = controlOrigin.y + controlSize.y - area.height;
else
y = controlOrigin.y;
}
if (scompOrigin.x != x || scompOrigin.y != y) {
// scroll to reveal
scomp.setOrigin(x, y);
}
}
public static void ensureVisible(ScrolledComposite scomp, Control control,
MouseEvent e) {
Point controlOrigin = getControlLocation(scomp, control);
int rX = controlOrigin.x + e.x;
int rY = controlOrigin.y + e.y;
Rectangle area = scomp.getClientArea();
Point scompOrigin = scomp.getOrigin();
int x = scompOrigin.x;
int y = scompOrigin.y;
// System.out.println("Ensure: area="+area+", origin="+scompOrigin+",
// cloc="+controlOrigin+", csize="+controlSize+", x="+x+", y="+y);
// horizontal right
if (rX > scompOrigin.x + area.width) {
x = rX - area.width;
}
// horizontal left
else if (rX < x) {
x = rX;
}
// vertical bottom
if (rY > scompOrigin.y + area.height) {
y = rY - area.height;
}
// vertical top
else if (rY < y) {
y = rY;
}
if (scompOrigin.x != x || scompOrigin.y != y) {
// scroll to reveal
scomp.setOrigin(x, y);
}
}
public static Point getControlLocation(ScrolledComposite scomp,
Control control) {
int x = 0;
int y = 0;
Control content = scomp.getContent();
Control currentControl = control;
for (;;) {
if (currentControl == content)
break;
Point location = currentControl.getLocation();
// if (location.x > 0)
// x += location.x;
// if (location.y > 0)
// y += location.y;
x += location.x;
y += location.y;
currentControl = currentControl.getParent();
}
return new Point(x, y);
}
static void scrollVertical(ScrolledComposite scomp, boolean up) {
scroll(scomp, 0, up ? -V_SCROLL_INCREMENT : V_SCROLL_INCREMENT);
}
static void scrollHorizontal(ScrolledComposite scomp, boolean left) {
scroll(scomp, left ? -H_SCROLL_INCREMENT : H_SCROLL_INCREMENT, 0);
}
static void scrollPage(ScrolledComposite scomp, boolean up) {
Rectangle clientArea = scomp.getClientArea();
int increment = up ? -clientArea.height : clientArea.height;
scroll(scomp, 0, increment);
}
static void scroll(ScrolledComposite scomp, int xoffset, int yoffset) {
Point origin = scomp.getOrigin();
Point contentSize = scomp.getContent().getSize();
int xorigin = origin.x + xoffset;
int yorigin = origin.y + yoffset;
xorigin = Math.max(xorigin, 0);
xorigin = Math.min(xorigin, contentSize.x - 1);
yorigin = Math.max(yorigin, 0);
yorigin = Math.min(yorigin, contentSize.y - 1);
scomp.setOrigin(xorigin, yorigin);
}
public static void updatePageIncrement(ScrolledComposite scomp) {
ScrollBar vbar = scomp.getVerticalBar();
if (vbar != null) {
Rectangle clientArea = scomp.getClientArea();
int increment = clientArea.height - 5;
vbar.setPageIncrement(increment);
}
}
public static void processKey(int keyCode, Control c) {
ScrolledComposite scomp = FormUtil.getScrolledComposite(c);
if (scomp != null) {
if (c instanceof Combo)
return;
switch (keyCode) {
case SWT.ARROW_DOWN:
if (scomp.getData("novarrows") == null) //$NON-NLS-1$
FormUtil.scrollVertical(scomp, false);
break;
case SWT.ARROW_UP:
if (scomp.getData("novarrows") == null) //$NON-NLS-1$
FormUtil.scrollVertical(scomp, true);
break;
case SWT.ARROW_LEFT:
FormUtil.scrollHorizontal(scomp, true);
break;
case SWT.ARROW_RIGHT:
FormUtil.scrollHorizontal(scomp, false);
break;
case SWT.PAGE_UP:
FormUtil.scrollPage(scomp, true);
break;
case SWT.PAGE_DOWN:
FormUtil.scrollPage(scomp, false);
break;
}
}
}
static boolean isWrapControl(Control c) {
if ((c.getStyle() & SWT.WRAP) != 0)
return true;
if (c instanceof Composite) {
return ((Composite) c).getLayout() instanceof ILayoutExtension;
}
return false;
}
public static int getWidthHint(int wHint, Control c) {
boolean wrap = isWrapControl(c);
return wrap ? wHint : SWT.DEFAULT;
}
public static int getHeightHint(int hHint, Control c) {
if (c instanceof Composite) {
Layout layout = ((Composite) c).getLayout();
if (layout instanceof ColumnLayout)
return hHint;
}
return SWT.DEFAULT;
}
public static int computeMinimumWidth(Control c, boolean changed) {
if (c instanceof Composite) {
Layout layout = ((Composite) c).getLayout();
if (layout instanceof ILayoutExtension)
return ((ILayoutExtension) layout).computeMinimumWidth(
(Composite) c, changed);
}
return c.computeSize(FormUtil.getWidthHint(5, c), SWT.DEFAULT, changed).x;
}
public static int computeMaximumWidth(Control c, boolean changed) {
if (c instanceof Composite) {
Layout layout = ((Composite) c).getLayout();
if (layout instanceof ILayoutExtension)
return ((ILayoutExtension) layout).computeMaximumWidth(
(Composite) c, changed);
}
return c.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed).x;
}
public static Form getForm(Control c) {
Composite parent = c.getParent();
while (parent != null) {
if (parent instanceof Form) {
return (Form) parent;
}
parent = parent.getParent();
}
return null;
}
public static Image createAlphaMashImage(Device device, Image srcImage) {
Rectangle bounds = srcImage.getBounds();
int alpha = 0;
int calpha = 0;
ImageData data = srcImage.getImageData();
// Create a new image with alpha values alternating
// between fully transparent (0) and fully opaque (255).
// This image will show the background through the
// transparent pixels.
for (int i = 0; i < bounds.height; i++) {
// scan line
alpha = calpha;
for (int j = 0; j < bounds.width; j++) {
// column
data.setAlpha(j, i, alpha);
alpha = alpha == 255 ? 0 : 255;
}
calpha = calpha == 255 ? 0 : 255;
}
return new Image(device, data);
}
public static Font createBoldFont(Display display, Font regularFont) {
FontData[] fontDatas = regularFont.getFontData();
for (int i = 0; i < fontDatas.length; i++) {
fontDatas[i].setStyle(fontDatas[i].getStyle() | SWT.BOLD);
}
return new Font(display, fontDatas);
}
public static boolean mnemonicMatch(String text, char key) {
char mnemonic = findMnemonic(text);
if (mnemonic == '\0')
return false;
return Character.toUpperCase(key) == Character.toUpperCase(mnemonic);
}
private static char findMnemonic(String string) {
int index = 0;
int length = string.length();
do {
while (index < length && string.charAt(index) != '&')
index++;
if (++index >= length)
return '\0';
if (string.charAt(index) != '&')
return string.charAt(index);
index++;
} while (index < length);
return '\0';
}
public static void setFocusScrollingEnabled(Control c, boolean enabled) {
ScrolledComposite scomp = null;
if (c instanceof ScrolledComposite)
scomp = (ScrolledComposite)c;
else
scomp = getScrolledComposite(c);
if (scomp!=null)
scomp.setData(FormUtil.FOCUS_SCROLLING, enabled?null:Boolean.FALSE);
}
}