| /******************************************************************************* |
| * 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); |
| } |
| } |