001: /*******************************************************************************
002: * Copyright (c) 2004, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.forms.widgets;
011:
012: import org.eclipse.swt.SWT;
013: import org.eclipse.swt.accessibility.*;
014: import org.eclipse.swt.graphics.*;
015: import org.eclipse.swt.widgets.Composite;
016: import org.eclipse.ui.internal.forms.widgets.*;
017:
018: /**
019: * Hyperlink is a concrete implementation of the abstract base class that draws
020: * text in the client area. Text can be wrapped and underlined. Hyperlink is
021: * typically added to the hyperlink group so that certain properties are managed
022: * for all the hyperlinks that belong to it.
023: * <p>
024: * Hyperlink can be extended.
025: *
026: * @see org.eclipse.ui.forms.HyperlinkGroup
027: * @since 3.0
028: */
029: public class Hyperlink extends AbstractHyperlink {
030: private String text;
031: private static final String ELLIPSIS = "..."; //$NON-NLS-1$
032: private boolean underlined;
033: // The tooltip is used for two purposes - the application can set
034: // a tooltip or the tooltip can be used to display the full text when the
035: // the text has been truncated due to the label being too short.
036: // The appToolTip stores the tooltip set by the application. Control.tooltiptext
037: // contains whatever tooltip is currently being displayed.
038: private String appToolTipText;
039:
040: /**
041: * Creates a new hyperlink control in the provided parent.
042: *
043: * @param parent
044: * the control parent
045: * @param style
046: * the widget style
047: */
048: public Hyperlink(Composite parent, int style) {
049: super (parent, style);
050: initAccessible();
051: }
052:
053: protected void initAccessible() {
054: Accessible accessible = getAccessible();
055: accessible.addAccessibleListener(new AccessibleAdapter() {
056: public void getName(AccessibleEvent e) {
057: e.result = getText();
058: if (e.result == null)
059: getHelp(e);
060: }
061:
062: public void getHelp(AccessibleEvent e) {
063: e.result = getToolTipText();
064: }
065: });
066: accessible
067: .addAccessibleControlListener(new AccessibleControlAdapter() {
068: public void getChildAtPoint(AccessibleControlEvent e) {
069: Point pt = toControl(new Point(e.x, e.y));
070: e.childID = (getBounds().contains(pt)) ? ACC.CHILDID_SELF
071: : ACC.CHILDID_NONE;
072: }
073:
074: public void getLocation(AccessibleControlEvent e) {
075: Rectangle location = getBounds();
076: Point pt = toDisplay(new Point(location.x,
077: location.y));
078: e.x = pt.x;
079: e.y = pt.y;
080: e.width = location.width;
081: e.height = location.height;
082: }
083:
084: public void getChildCount(AccessibleControlEvent e) {
085: e.detail = 0;
086: }
087:
088: public void getRole(AccessibleControlEvent e) {
089: e.detail = ACC.ROLE_LINK;
090: }
091:
092: public void getDefaultAction(
093: AccessibleControlEvent e) {
094: e.result = SWT.getMessage("SWT_Press"); //$NON-NLS-1$
095: }
096:
097: public void getState(AccessibleControlEvent e) {
098: int state = ACC.STATE_NORMAL;
099: if (Hyperlink.this .getSelection())
100: state = ACC.STATE_SELECTED
101: | ACC.STATE_FOCUSED;
102: e.detail = state;
103: }
104: });
105: }
106:
107: /**
108: * Sets the underlined state. It is not necessary to call this method when
109: * in a hyperlink group.
110: *
111: * @param underlined
112: * if <samp>true </samp>, a line will be drawn below the text for
113: * each wrapped line.
114: */
115: public void setUnderlined(boolean underlined) {
116: this .underlined = underlined;
117: redraw();
118: }
119:
120: /**
121: * Returns the underline state of the hyperlink.
122: *
123: * @return <samp>true </samp> if text is underlined, <samp>false </samp>
124: * otherwise.
125: */
126: public boolean isUnderlined() {
127: return underlined;
128: }
129:
130: /**
131: * Overrides the parent by incorporating the margin.
132: */
133: public Point computeSize(int wHint, int hHint, boolean changed) {
134: checkWidget();
135: int innerWidth = wHint;
136: if (innerWidth != SWT.DEFAULT)
137: innerWidth -= marginWidth * 2;
138: Point textSize = computeTextSize(innerWidth, hHint);
139: int textWidth = textSize.x + 2 * marginWidth;
140: int textHeight = textSize.y + 2 * marginHeight;
141: return new Point(textWidth, textHeight);
142: }
143:
144: /**
145: * Returns the current hyperlink text.
146: *
147: * @return hyperlink text
148: */
149: public String getText() {
150: return text;
151: }
152:
153: /* (non-Javadoc)
154: * @see org.eclipse.swt.widgets.Control#getToolTipText()
155: */
156: public String getToolTipText() {
157: checkWidget();
158: return appToolTipText;
159: }
160:
161: /* (non-Javadoc)
162: * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String)
163: */
164: public void setToolTipText(String string) {
165: super .setToolTipText(string);
166: appToolTipText = super .getToolTipText();
167: }
168:
169: /**
170: * Sets the text of this hyperlink.
171: *
172: * @param text
173: * the hyperlink text
174: */
175: public void setText(String text) {
176: if (text != null)
177: this .text = text;
178: else
179: this .text = ""; //$NON-NLS-1$
180: redraw();
181: }
182:
183: /**
184: * Paints the hyperlink text.
185: *
186: * @param gc
187: * graphic context
188: */
189: protected void paintHyperlink(GC gc) {
190: Rectangle carea = getClientArea();
191: Rectangle bounds = new Rectangle(marginWidth, marginHeight,
192: carea.width - marginWidth - marginWidth, carea.height
193: - marginHeight - marginHeight);
194: paintText(gc, bounds);
195: }
196:
197: /**
198: * Paints the hyperlink text in provided bounding rectangle.
199: *
200: * @param gc
201: * graphic context
202: * @param bounds
203: * the bounding rectangle in which to paint the text
204: */
205: protected void paintText(GC gc, Rectangle bounds) {
206: gc.setFont(getFont());
207: gc.setForeground(getForeground());
208: if ((getStyle() & SWT.WRAP) != 0) {
209: FormUtil.paintWrapText(gc, text, bounds, underlined);
210: } else {
211: Point totalSize = computeTextSize(SWT.DEFAULT, SWT.DEFAULT);
212: boolean shortenText = false;
213: if (bounds.width < totalSize.x) {
214: // shorten
215: shortenText = true;
216: }
217: int textWidth = Math.min(bounds.width, totalSize.x);
218: int textHeight = totalSize.y;
219: String textToDraw = getText();
220: if (shortenText) {
221: textToDraw = shortenText(gc, getText(), bounds.width);
222: if (appToolTipText == null) {
223: super .setToolTipText(getText());
224: }
225: } else {
226: super .setToolTipText(appToolTipText);
227: }
228: gc.drawText(textToDraw, bounds.x, bounds.y, true);
229: if (underlined) {
230: int descent = gc.getFontMetrics().getDescent();
231: int lineY = bounds.y + textHeight - descent + 1;
232: gc.drawLine(bounds.x, lineY, bounds.x + textWidth,
233: lineY);
234: }
235: }
236: }
237:
238: protected String shortenText(GC gc, String t, int width) {
239: if (t == null)
240: return null;
241: int w = gc.textExtent(ELLIPSIS).x;
242: if (width <= w)
243: return t;
244: int l = t.length();
245: int max = l / 2;
246: int min = 0;
247: int mid = (max + min) / 2 - 1;
248: if (mid <= 0)
249: return t;
250: while (min < mid && mid < max) {
251: String s1 = t.substring(0, mid);
252: String s2 = t.substring(l - mid, l);
253: int l1 = gc.textExtent(s1).x;
254: int l2 = gc.textExtent(s2).x;
255: if (l1 + w + l2 > width) {
256: max = mid;
257: mid = (max + min) / 2;
258: } else if (l1 + w + l2 < width) {
259: min = mid;
260: mid = (max + min) / 2;
261: } else {
262: min = max;
263: }
264: }
265: if (mid == 0)
266: return t;
267: return t.substring(0, mid) + ELLIPSIS + t.substring(l - mid, l);
268: }
269:
270: protected Point computeTextSize(int wHint, int hHint) {
271: Point extent;
272: GC gc = new GC(this );
273: gc.setFont(getFont());
274: if ((getStyle() & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) {
275: extent = FormUtil.computeWrapSize(gc, getText(), wHint);
276: } else {
277: extent = gc.textExtent(getText());
278: if ((getStyle() & SWT.WRAP) == 0 && wHint != SWT.DEFAULT)
279: extent.x = wHint;
280: }
281: gc.dispose();
282: return extent;
283: }
284: }
|