📄 decoratedfield.java
字号:
/******************************************************************************* * Copyright (c) 2005, 2006 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 *******************************************************************************/package org.eclipse.jface.fieldassist;import org.eclipse.core.runtime.Assert;import org.eclipse.swt.SWT;import org.eclipse.swt.events.DisposeEvent;import org.eclipse.swt.events.DisposeListener;import org.eclipse.swt.events.FocusEvent;import org.eclipse.swt.events.FocusListener;import org.eclipse.swt.events.MouseAdapter;import org.eclipse.swt.events.MouseEvent;import org.eclipse.swt.events.MouseTrackListener;import org.eclipse.swt.events.PaintEvent;import org.eclipse.swt.events.PaintListener;import org.eclipse.swt.graphics.GC;import org.eclipse.swt.graphics.Image;import org.eclipse.swt.graphics.Point;import org.eclipse.swt.graphics.Region;import org.eclipse.swt.layout.FormAttachment;import org.eclipse.swt.layout.FormData;import org.eclipse.swt.layout.FormLayout;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.Shell;/** * DecoratedField manages image decorations around a control. It allows clients * to specify an image decoration and a position for the decoration relative to * the field. Decorations may be assigned descriptions, which are shown when the * user hovers over the decoration. Clients can decorate any kind of control by * supplying a {@link IControlCreator} to create the control that is decorated. * <p> * Decorations always appear on either horizontal side of the field, never above * or below it. Decorations can be positioned at the top or bottom of either * side. Future implementations may provide additional positioning options for * decorations. * <p> * By default, DecoratedField will consult the {@link FieldDecorationRegistry} * to determine how much space should be reserved for each decoration. This * allows fields with decorations from different sources to align properly on * the same dialog, since the registry tracks the size of all decorations * registered. Therefore, it is recommended, but not required, that clients of * DecoratedField register the decorations used. In cases where alignment * between different fields is not a concern, clients can use * <code>setUseMaximumDecorationWidth(false)</code> and need not register * their decorations. * <p> * This class is not intended to be subclassed. * * @since 3.2 * * @see FieldDecorationRegistry */public class DecoratedField { /** * Cached platform flags for dealing with platform-specific issues. */ private static boolean CARBON = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$ /** * Constants describing the array indices used to hold the decorations in * array slots. */ private static final int LEFT_TOP = 0; private static final int LEFT_BOTTOM = 1; private static final int RIGHT_TOP = 2; private static final int RIGHT_BOTTOM = 3; private static final int DECORATION_SLOTS = 4; /** * Simple data structure class for specifying the internals for a field * decoration. This class contains data specific to the implementation of * field decorations as labels attached to the field. Clients should use * <code>FieldDecoration</code> for specifying a decoration. */ private class FieldDecorationData { /* Package */FieldDecoration decoration; /* Package */Label label; /* Package */FormData data; /* Package */boolean showOnFocus; /* Package */boolean visible = true; /** * Create a decoration data representing the specified decoration, using * the specified label and form data for its representation. * * @param decoration * the decoration whose data is kept. * @param label * the label used to represent the decoration. * @param formData * the form data used to attach the decoration to its field. * @param showOnFocus * a boolean specifying whether the decoration should only be * shown when the field has focus. */ FieldDecorationData(FieldDecoration decoration, Label label, FormData formData, boolean showOnFocus) { this.decoration = decoration; this.label = label; this.data = formData; this.showOnFocus = showOnFocus; } } /** * Decorations keyed by position. */ private FieldDecorationData[] decDatas = new FieldDecorationData[DECORATION_SLOTS]; /** * The associated control */ private Control control; /** * The composite with form layout used to manage decorations. */ private Composite form; /** * The boolean that indicates whether the maximum decoration width is used * when allocating space for decorations. */ private boolean useMaxDecorationWidth = true; /** * The hover used for showing description text */ private Hover hover; /** * The hover used to show a decoration image's description. */ class Hover { private static final String EMPTY = ""; //$NON-NLS-1$ /** * Offset of info hover arrow from the left or right side. */ private int hao = 10; /** * Width of info hover arrow. */ private int haw = 8; /** * Height of info hover arrow. */ private int hah = 10; /** * Margin around info hover text. */ private int hm = 2; /** * This info hover's shell. */ Shell hoverShell; /** * The info hover text. */ String text = EMPTY; /** * The region used to manage the shell shape */ Region region; /** * Boolean indicating whether the last computed polygon location had an * arrow on left. (true if left, false if right). */ boolean arrowOnLeft = true; /* * Create a hover parented by the specified shell. */ Hover(Shell parent) { final Display display = parent.getDisplay(); hoverShell = new Shell(parent, SWT.NO_TRIM | SWT.ON_TOP | SWT.NO_FOCUS); hoverShell.setBackground(display .getSystemColor(SWT.COLOR_INFO_BACKGROUND)); hoverShell.setForeground(display .getSystemColor(SWT.COLOR_INFO_FOREGROUND)); hoverShell.addPaintListener(new PaintListener() { public void paintControl(PaintEvent pe) { pe.gc.drawString(text, hm, hm); if (!CARBON) { pe.gc.drawPolygon(getPolygon(true)); } } }); hoverShell.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { hideHover(); } }); } /* * Compute a polygon that represents a hover with an arrow pointer. If * border is true, compute the polygon inset by 1-pixel border. Consult * the arrowOnLeft flag to determine which side the arrow is on. */ int[] getPolygon(boolean border) { Point e = getExtent(); int b = border ? 1 : 0; if (arrowOnLeft) { return new int[] { 0, 0, e.x - b, 0, e.x - b, e.y - b, hao + haw, e.y - b, hao + haw / 2, e.y + hah - b, hao, e.y - b, 0, e.y - b, 0, 0 }; } return new int[] { 0, 0, e.x - b, 0, e.x - b, e.y - b, e.x - hao - b, e.y - b, e.x - hao - haw / 2, e.y + hah - b, e.x - hao - haw, e.y - b, 0, e.y - b, 0, 0 }; } /* * Dispose the hover, it is no longer needed. Dispose any resources * allocated by the hover. */ void dispose() { if (!hoverShell.isDisposed()) { hoverShell.dispose(); } if (region != null) { region.dispose(); } } /* * Set the visibility of the hover. */ void setVisible(boolean visible) { if (visible) { if (!hoverShell.isVisible()) { hoverShell.setVisible(true); } } else { if (hoverShell.isVisible()) { hoverShell.setVisible(false); } } } /* * Set the text of the hover to the specified text. Recompute the size * and location of the hover to hover near the specified control, * pointing the arrow toward the target control. */ void setText(String t, Control hoverNear, Control targetControl) { if (t == null) { t = EMPTY; } if (!t.equals(text)) { Point oldSize = getExtent(); text = t; hoverShell.redraw(); Point newSize = getExtent(); if (!oldSize.equals(newSize)) { // set a flag that indicates the direction of arrow arrowOnLeft = hoverNear.getLocation().x <= targetControl .getLocation().x; setNewShape(); } } if (hoverNear != null) { Point extent = getExtent(); int y = -extent.y - hah + 1; int x = arrowOnLeft ? -hao + haw / 2 : -extent.x + hao + haw / 2; hoverShell.setLocation(hoverNear.toDisplay(x, y)); } } /* * Return whether or not the hover (shell) is visible. */ boolean isVisible() { return hoverShell.isVisible(); } /* * Compute the extent of the hover for the current text. */ Point getExtent() { GC gc = new GC(hoverShell); Point e = gc.textExtent(text); gc.dispose(); e.x += hm * 2; e.y += hm * 2; return e; } /* * Compute a new shape for the hover shell. */ void setNewShape() { Region oldRegion = region; region = new Region(); region.add(getPolygon(false)); hoverShell.setRegion(region); if (oldRegion != null) { oldRegion.dispose(); } } } /** * Construct a decorated field which is parented by the specified composite * and has the given style bits. Use the controlCreator to create the * specific kind of control that is decorated inside the field. * * @param parent * the parent of the decorated field. * @param style * the desired style bits for the field. * @param controlCreator * the IControlCreator used to specify the specific kind of * control that is to be decorated. * * @see IControlCreator */ public DecoratedField(Composite parent, int style, IControlCreator controlCreator) { this.form = createForm(parent); this.control = controlCreator.createControl(form, style); addControlListeners(); form.setTabList(new Control[] { control }); // Set up the initial layout data. FormData data = new FormData(); data.left = new FormAttachment(0, 0); data.top = new FormAttachment(0, 0); data.right = new FormAttachment(100, 0); control.setLayoutData(data); } /** * Adds an image decoration to the field. * * @param decoration * A FieldDecoration describing the image and description for the * decoration * * @param position * The SWT constant indicating the position of the decoration * relative to the field's control. The position should include * style bits describing both the vertical and horizontal * orientation. <code>SWT.LEFT</code> and * <code>SWT.RIGHT</code> describe the horizontal placement of * the decoration relative to the field, and the constants * <code>SWT.TOP</code> and <code>SWT.BOTTOM</code> describe * the vertical alignment of the decoration relative to the * field. Decorations always appear on either horizontal side of * the field, never above or below it. For example, a decoration * appearing on the left side of the field, at the top, is * specified as SWT.LEFT | SWT.TOP. If an image decoration * already exists in the specified position, it will be replaced * by the one specified. * @param showOnFocus * <code>true</code> if the decoration should only be shown * when the associated control has focus, <code>false</code> if * it should always be shown. * */ public void addFieldDecoration(FieldDecoration decoration, int position, boolean showOnFocus) { final Label label; FormData formData; int i = indexForPosition(position); if (decDatas[i] == null) { formData = createFormDataForIndex(i, decoration.getImage()); label = new Label(form, SWT.HORIZONTAL | SWT.VERTICAL | SWT.CENTER); label.addMouseTrackListener(new MouseTrackListener() { public void mouseHover(MouseEvent event) { FieldDecorationData decData = (FieldDecorationData) event.widget .getData(); String desc = decData.decoration.getDescription(); if (desc != null) { showHoverText(desc, label); } } public void mouseEnter(MouseEvent event) { } public void mouseExit(MouseEvent event) { hideHover(); } }); decDatas[i] = new FieldDecorationData(decoration, label, formData, showOnFocus); } else { label = decDatas[i].label; formData = decDatas[i].data; decDatas[i].decoration = decoration; decDatas[i].showOnFocus = showOnFocus; } label.setImage(decDatas[i].decoration.getImage()); label.setData(decDatas[i]); label.setLayoutData(formData); label.setVisible(!showOnFocus);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -