*** empty log message ***
diff --git a/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java b/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java
index 7c1406a..ef61956 100644
--- a/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java
+++ b/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/ExpandableComposite.java
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.forms.widgets;
+
import java.util.Vector;
import org.eclipse.jface.util.Assert;
@@ -18,14 +19,16 @@
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.events.*;
import org.eclipse.ui.internal.forms.widgets.*;
+
/**
* This composite is capable of expanding or collapsing a single client that is
* its direct child. The composite renders an expansion toggle affordance
* (according to the chosen style), and a title that also acts as a hyperlink
- * (can be selected and is traversable). The client is layed out below the
- * title when expanded, or hidden when collapsed.
- * <p>The widget can be instantiated as-is, or subclassed to
- * modify some aspects of it.
+ * (can be selected and is traversable). The client is layed out below the title
+ * when expanded, or hidden when collapsed.
+ * <p>
+ * The widget can be instantiated as-is, or subclassed to modify some aspects of
+ * it.
*
* @see Section
* @since 3.0
@@ -36,97 +39,124 @@
* toggle.
*/
public static final int TWISTIE = 1 << 1;
+
/**
* If this style is used, a tree node with either + or - signs will be used
* to render the expansion toggle.
*/
public static final int TREE_NODE = 1 << 2;
+
/**
* If this style is used, the title text will be rendered as a hyperlink
* that can individually accept focus. Otherwise, it will still act like a
* hyperlink, but only the toggle control will accept focus.
*/
public static final int FOCUS_TITLE = 1 << 3;
+
/**
* If this style is used, the client origin will be vertically aligned with
* the title text. Otherwise, it will start at x = 0.
*/
public static final int CLIENT_INDENT = 1 << 4;
+
/**
* If this style is used, computed size of the composite will take the
* client width into consideration only in the expanded state. Otherwise,
* client width will always be taken into acount.
*/
public static final int COMPACT = 1 << 5;
+
/**
- * If this style is used, the control will be created in the expanded
- * state. This state can later be changed programmatically or by the user
- * if TWISTIE or TREE_NODE style is used.
+ * If this style is used, the control will be created in the expanded state.
+ * This state can later be changed programmatically or by the user if
+ * TWISTIE or TREE_NODE style is used.
*/
public static final int EXPANDED = 1 << 6;
+
/**
- * If this style is used, title bar decoration will be painted behind
- * the text.
+ * If this style is used, title bar decoration will be painted behind the
+ * text.
*/
public static final int TITLE_BAR = 1 << 8;
+
/**
* If this style is used, title will not be rendered.
*/
- public static final int NO_TITLE = 1<<12;
+ public static final int NO_TITLE = 1 << 12;
+
/**
- * Width of the margin that will be added around the control (default is
- * 0).
- */
+ * Width of the margin that will be added around the control (default is 0).
+ */
public int marginWidth = 0;
+
/**
* Height of the margin that will be added around the control (default is
* 0).
*/
public int marginHeight = 0;
+
+ /**
+ * Vertical spacing between the title area and the composite client control
+ * (default is 3).
+ */
+ public int clientVerticalSpacing = 3;
+
private int VSPACE = 3;
- public int clientVerticalSpacing = VSPACE;
+
protected int GAP = 4;
private int SEPARATOR_HEIGHT = 2;
+
private int expansionStyle = TWISTIE | FOCUS_TITLE | EXPANDED;
+
private boolean expanded;
+
private Control textClient;
+
private Control client;
+
private Vector listeners;
+
protected ToggleHyperlink toggle;
+
protected Control textLabel;
+
private class ExpandableLayout extends Layout implements ILayoutExtension {
private SizeCache toggleCache = new SizeCache();
+
private SizeCache textClientCache = new SizeCache();
+
private SizeCache textLabelCache = new SizeCache();
+
private SizeCache descriptionCache = new SizeCache();
+
private SizeCache clientCache = new SizeCache();
-
- private void initCache(boolean shouldFlush) {
- toggleCache.setControl(toggle);
- textClientCache.setControl(textClient);
- textLabelCache.setControl(textLabel);
- descriptionCache.setControl(getDescriptionControl());
- clientCache.setControl(client);
-
- if (shouldFlush) {
- toggleCache.flush();
- textClientCache.flush();
- textLabelCache.flush();
- descriptionCache.flush();
- clientCache.flush();
- }
- }
-
+
+ private void initCache(boolean shouldFlush) {
+ toggleCache.setControl(toggle);
+ textClientCache.setControl(textClient);
+ textLabelCache.setControl(textLabel);
+ descriptionCache.setControl(getDescriptionControl());
+ clientCache.setControl(client);
+
+ if (shouldFlush) {
+ toggleCache.flush();
+ textClientCache.flush();
+ textLabelCache.flush();
+ descriptionCache.flush();
+ clientCache.flush();
+ }
+ }
+
protected void layout(Composite parent, boolean changed) {
- initCache(changed);
-
+ initCache(changed);
+
Rectangle clientArea = parent.getClientArea();
int thmargin = 0;
int tvmargin = 0;
-
- if ((expansionStyle & TITLE_BAR)!=0) {
+
+ if ((expansionStyle & TITLE_BAR) != 0) {
thmargin = GAP;
tvmargin = GAP;
}
@@ -136,18 +166,20 @@
Point tcsize = null;
if (toggle != null)
tsize = toggleCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- int twidth = clientArea.width - marginWidth - marginWidth - thmargin - thmargin;
+ int twidth = clientArea.width - marginWidth - marginWidth
+ - thmargin - thmargin;
if (tsize != null)
twidth -= tsize.x + GAP;
- if (textClient !=null)
+ if (textClient != null)
tcsize = textClientCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- if (tcsize!=null)
+ if (tcsize != null)
twidth -= tcsize.x + GAP;
Point size = null;
- if (textLabel!=null)
+ if (textLabel != null)
size = textLabelCache.computeSize(twidth, SWT.DEFAULT);
if (textLabel instanceof Label) {
- Point defSize = textLabelCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ Point defSize = textLabelCache.computeSize(SWT.DEFAULT,
+ SWT.DEFAULT);
if (defSize.y == size.y) {
// One line - pick the smaller of the two widths
size.x = Math.min(defSize.x, size.x);
@@ -166,19 +198,19 @@
toggle.setSize(tsize);
x += tsize.x + GAP;
}
- if (textLabel!=null)
+ if (textLabel != null)
textLabelCache.setBounds(x, y, size.x, size.y);
- if (textClient!=null) {
- int tcx = clientArea.width - tcsize.x-marginWidth-thmargin;
+ if (textClient != null) {
+ int tcx = clientArea.width - tcsize.x - marginWidth - thmargin;
textClientCache.setBounds(tcx, y, tcsize.x, tcsize.y);
}
int tbarHeight = 0;
- if (size!=null)
+ if (size != null)
tbarHeight = size.y;
- if (tcsize!=null)
+ if (tcsize != null)
tbarHeight = Math.max(tbarHeight, tcsize.y);
y += tbarHeight;
- if ((expansionStyle & TITLE_BAR) != 0)
+ if ((expansionStyle & TITLE_BAR) != 0)
y += tvmargin;
if (getSeparatorControl() != null) {
y += VSPACE;
@@ -190,7 +222,8 @@
y += VSPACE;
}
if (expanded) {
- int areaWidth = clientArea.width - marginWidth - marginWidth - thmargin-thmargin;
+ int areaWidth = clientArea.width - marginWidth - marginWidth
+ - thmargin - thmargin;
int cx = marginWidth + thmargin;
if ((expansionStyle & CLIENT_INDENT) != 0) {
cx = x;
@@ -200,14 +233,12 @@
Point dsize = null;
Control desc = getDescriptionControl();
if (desc != null) {
- dsize = descriptionCache.computeSize(areaWidth, SWT.DEFAULT);
+ dsize = descriptionCache.computeSize(areaWidth,
+ SWT.DEFAULT);
descriptionCache.setBounds(cx, y, dsize.x, dsize.y);
y += dsize.y + clientVerticalSpacing;
- }
- else
+ } else
y += clientVerticalSpacing - VSPACE;
- //int cwidth = clientArea.width - marginWidth - marginWidth
- //- cx;
int cwidth = areaWidth;
int cheight = clientArea.height - marginHeight
- marginHeight - y;
@@ -215,11 +246,12 @@
}
}
}
+
protected Point computeSize(Composite parent, int wHint, int hHint,
boolean changed) {
-
- initCache(changed);
-
+
+ initCache(changed);
+
int width = 0, height = 0;
Point tsize = null;
int twidth = 0;
@@ -229,59 +261,61 @@
}
int thmargin = 0;
int tvmargin = 0;
-
- if ((expansionStyle & TITLE_BAR)!=0) {
+
+ if ((expansionStyle & TITLE_BAR) != 0) {
thmargin = GAP;
tvmargin = GAP;
}
int innerwHint = wHint;
if (innerwHint != SWT.DEFAULT)
innerwHint -= twidth;
-
+
int innertHint = innerwHint;
-
+
Point tcsize = null;
- if (textClient!=null) {
+ if (textClient != null) {
tcsize = textClientCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- if (innertHint!=SWT.DEFAULT)
+ if (innertHint != SWT.DEFAULT)
innertHint -= GAP + tcsize.x;
}
Point size = null;
-
- if (textLabel!=null)
+
+ if (textLabel != null)
size = textLabelCache.computeSize(innertHint, SWT.DEFAULT);
if (textLabel instanceof Label) {
- Point defSize = textLabelCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ Point defSize = textLabelCache.computeSize(SWT.DEFAULT,
+ SWT.DEFAULT);
if (defSize.y == size.y) {
// One line - pick the smaller of the two widths
size.x = Math.min(defSize.x, size.x);
}
}
- if (size!=null)
+ if (size != null)
width = size.x;
- int sizey = size!=null?size.y:0;
- height = tcsize!=null?Math.max(tcsize.y, sizey):sizey;
+ int sizey = size != null ? size.y : 0;
+ height = tcsize != null ? Math.max(tcsize.y, sizey) : sizey;
if (getSeparatorControl() != null) {
height += VSPACE + SEPARATOR_HEIGHT;
if (expanded && client != null)
height += VSPACE;
}
- if ((expansionStyle & TITLE_BAR) != 0)
+ if ((expansionStyle & TITLE_BAR) != 0)
height += VSPACE;
if ((expanded || (expansionStyle & COMPACT) == 0) && client != null) {
int cwHint = wHint;
-
- if (cwHint!=SWT.DEFAULT)
- cwHint -= tvmargin + tvmargin;
- if ((expansionStyle & CLIENT_INDENT) != 0)
- cwHint = innerwHint;
+
+ if (cwHint != SWT.DEFAULT) {
+ cwHint -= marginWidth + marginWidth + thmargin + thmargin;
+ if ((expansionStyle & CLIENT_INDENT) != 0)
+ cwHint = innerwHint - marginWidth - marginWidth;
+ }
Point dsize = null;
- Point csize = clientCache.computeSize(FormUtil.getWidthHint(cwHint,
- client), SWT.DEFAULT);
+ Point csize = clientCache.computeSize(FormUtil.getWidthHint(
+ cwHint, client), SWT.DEFAULT);
if (getDescriptionControl() != null) {
int dwHint = cwHint;
if (dwHint == SWT.DEFAULT) {
- dwHint = csize.x - tvmargin - tvmargin;
+ dwHint = csize.x;
if ((expansionStyle & CLIENT_INDENT) != 0)
dwHint -= twidth;
}
@@ -293,8 +327,7 @@
width = Math.max(width, dsize.x);
if (expanded)
height += dsize.y + clientVerticalSpacing;
- }
- else
+ } else
height += clientVerticalSpacing - VSPACE;
if ((expansionStyle & CLIENT_INDENT) != 0)
csize.x -= twidth;
@@ -306,31 +339,33 @@
height = height - sizey + Math.max(sizey, tsize.y);
width += twidth;
}
- return new Point(width + marginWidth + marginWidth+thmargin+thmargin, height
- + marginHeight + marginHeight+tvmargin+tvmargin);
+ return new Point(width + marginWidth + marginWidth + thmargin
+ + thmargin, height + marginHeight + marginHeight + tvmargin
+ + tvmargin);
}
+
public int computeMinimumWidth(Composite parent, boolean changed) {
-
- initCache(changed);
-
+
+ initCache(changed);
+
int width = 0;
Point size = null;
- if (textLabel!=null)
+ if (textLabel != null)
size = textLabelCache.computeSize(5, SWT.DEFAULT);
- Point tcsize=null;
- if (textClient!=null) {
+ Point tcsize = null;
+ if (textClient != null) {
tcsize = textClientCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
}
int thmargin = 0;
- //int tvmargin = 0;
-
- if ((expansionStyle & TITLE_BAR)!=0) {
+ // int tvmargin = 0;
+
+ if ((expansionStyle & TITLE_BAR) != 0) {
thmargin = GAP;
- //tvmargin = GAP;
- }
- if (size!=null)
+ // tvmargin = GAP;
+ }
+ if (size != null)
width = size.x;
- if (tcsize!=null)
+ if (tcsize != null)
width += GAP + tcsize.x;
if ((expanded || (expansionStyle & COMPACT) == 0) && client != null) {
@@ -346,8 +381,9 @@
Point tsize = toggleCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
width += tsize.x + GAP;
}
- return width + marginWidth + marginWidth+thmargin+thmargin;
+ return width + marginWidth + marginWidth + thmargin + thmargin;
}
+
/*
* (non-Javadoc)
*
@@ -355,32 +391,33 @@
* boolean)
*/
public int computeMaximumWidth(Composite parent, boolean changed) {
-
- initCache(changed);
-
+
+ initCache(changed);
+
int width = 0;
Point size = null;
- if (textLabel!=null)
+ if (textLabel != null)
textLabelCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- Point tcsize=null;
+ Point tcsize = null;
int thmargin = 0;
- //int tvmargin = 0;
-
- if ((expansionStyle & TITLE_BAR)!=0) {
+ // int tvmargin = 0;
+
+ if ((expansionStyle & TITLE_BAR) != 0) {
thmargin = GAP;
- //tvmargin = GAP;
- }
- if (textClient!=null) {
+ // tvmargin = GAP;
+ }
+ if (textClient != null) {
tcsize = textClientCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
}
- if (size!=null)
+ if (size != null)
width = size.x;
- if (tcsize!=null)
+ if (tcsize != null)
width += GAP + tcsize.x;
if ((expanded || (expansionStyle & COMPACT) == 0) && client != null) {
Point dsize = null;
if (getDescriptionControl() != null) {
- dsize = descriptionCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ dsize = descriptionCache.computeSize(SWT.DEFAULT,
+ SWT.DEFAULT);
width = Math.max(width, dsize.x);
}
int cwidth = FormUtil.computeMaximumWidth(client, changed);
@@ -390,9 +427,10 @@
Point tsize = toggleCache.computeSize(SWT.DEFAULT, SWT.DEFAULT);
width += tsize.x + GAP;
}
- return width + marginWidth + marginWidth+thmargin+thmargin;
+ return width + marginWidth + marginWidth + thmargin + thmargin;
}
}
+
/**
* Creates an expandable composite using a TWISTIE toggle.
*
@@ -404,6 +442,7 @@
public ExpandableComposite(Composite parent, int style) {
this(parent, style, TWISTIE);
}
+
/**
* Creates the expandable composite in the provided parent.
*
@@ -473,35 +512,39 @@
}
textLabel = label;
}
- if (textLabel!=null)
+ if (textLabel != null)
textLabel.setMenu(getMenu());
}
+
/**
- * Prevents assignment of the layout manager - expandable composite uses
- * its own layout.
+ * Prevents assignment of the layout manager - expandable composite uses its
+ * own layout.
*/
public final void setLayout(Layout layout) {
}
+
/**
* Sets the background of all the custom controls in the expandable.
*/
public void setBackground(Color bg) {
super.setBackground(bg);
- if (textLabel!=null)
+ if (textLabel != null)
textLabel.setBackground(bg);
if (toggle != null)
toggle.setBackground(bg);
}
+
/**
* Sets the foreground of all the custom controls in the expandable.
*/
public void setForeground(Color fg) {
super.setForeground(fg);
- if (textLabel!=null)
+ if (textLabel != null)
textLabel.setForeground(fg);
if (toggle != null)
toggle.setForeground(fg);
}
+
/**
* Sets the color of the toggle control.
*
@@ -512,6 +555,7 @@
if (toggle != null)
toggle.setDecorationColor(c);
}
+
/**
* Sets the active color of the toggle control (when the mouse enters the
* toggle area).
@@ -523,16 +567,18 @@
if (toggle != null)
toggle.setHoverDecorationColor(c);
}
+
/**
* Sets the fonts of all the custom controls in the expandable.
*/
public void setFont(Font font) {
super.setFont(font);
- if (textLabel!=null)
+ if (textLabel != null)
textLabel.setFont(font);
if (toggle != null)
toggle.setFont(font);
}
+
/**
* Sets the client of this expandable composite. The client must not be
* <samp>null </samp> and must be a direct child of this container.
@@ -544,6 +590,7 @@
Assert.isTrue(client != null && client.getParent().equals(this));
this.client = client;
}
+
/**
* Returns the current expandable client.
*
@@ -552,6 +599,7 @@
public Control getClient() {
return client;
}
+
/**
* Sets the title of the expandable composite. The title will act as a
* hyperlink and activating it will toggle the client between expanded and
@@ -567,6 +615,7 @@
else if (textLabel instanceof Hyperlink)
((Hyperlink) textLabel).setText(title);
}
+
/**
* Returns the title string.
*
@@ -581,15 +630,16 @@
else
return "";
}
+
/**
* Tests the expanded state of the composite.
*
- * @return <samp>true </samp> if expanded, <samp>false </samp> if
- * collapsed.
+ * @return <samp>true </samp> if expanded, <samp>false </samp> if collapsed.
*/
public boolean isExpanded() {
return expanded;
}
+
/**
* Returns the bitwise-ORed style bits for the expansion control.
*
@@ -598,6 +648,7 @@
public int getExpansionStyle() {
return expansionStyle;
}
+
/**
* Programmatically changes expanded state.
*
@@ -609,6 +660,7 @@
if (toggle != null)
toggle.setExpanded(expanded);
}
+
/**
* Performs the expansion state change for the expandable control.
*
@@ -625,9 +677,9 @@
layout();
}
}
+
/**
- * Adds the listener that will be notified when the expansion state
- * changes.
+ * Adds the listener that will be notified when the expansion state changes.
*
* @param listener
* the listener to add
@@ -636,6 +688,7 @@
if (!listeners.contains(listener))
listeners.add(listener);
}
+
/**
* Removes the expansion listener.
*
@@ -646,21 +699,25 @@
if (listeners.contains(listener))
listeners.remove(listener);
}
+
private void toggleState() {
boolean newState = !isExpanded();
fireExpanding(newState, true);
internalSetExpanded(!isExpanded());
fireExpanding(newState, false);
}
-/**
- * If TITLE_BAR style is used, title bar decoration will
- * be painted behind the text in this method. The default
- * implementation does nothing - subclasses are responsible
- * for rendering the title area.
- * @param e the paint event
- */
+
+ /**
+ * If TITLE_BAR style is used, title bar decoration will be painted behind
+ * the text in this method. The default implementation does nothing -
+ * subclasses are responsible for rendering the title area.
+ *
+ * @param e
+ * the paint event
+ */
protected void onPaint(PaintEvent e) {
}
+
private void fireExpanding(boolean state, boolean before) {
int size = listeners.size();
if (size == 0)
@@ -674,6 +731,7 @@
listener.expansionStateChanged(e);
}
}
+
/**
* Returns description control that will be placed under the title if
* present.
@@ -683,6 +741,7 @@
protected Control getDescriptionControl() {
return null;
}
+
/**
* Returns the separator control that will be placed between the title and
* the description if present.
@@ -692,6 +751,7 @@
protected Control getSeparatorControl() {
return null;
}
+
/**
* Computes the size of the expandable composite.
*
@@ -709,40 +769,45 @@
Rectangle trim = computeTrim(0, 0, size.x, size.y);
return new Point(trim.width, trim.height);
}
+
/**
* Returns <samp>true </samp> if the composite is fixed i.e. cannot be
* expanded or collapsed. Fixed control will still contain the title,
- * separator and description (if present) as well as the client, but will
- * be in the permanent expanded state and the toggle affordance will not be
+ * separator and description (if present) as well as the client, but will be
+ * in the permanent expanded state and the toggle affordance will not be
* shown.
*
- * @return <samp>true </samp> if the control is fixed in the expanded
- * state, <samp>false </samp> if it can be collapsed.
+ * @return <samp>true </samp> if the control is fixed in the expanded state,
+ * <samp>false </samp> if it can be collapsed.
*/
protected boolean isFixedStyle() {
return (expansionStyle & TWISTIE) == 0
&& (expansionStyle & TREE_NODE) == 0;
}
+
/**
* Returns the text client control.
- * @return Returns the text client control if specified, or <code>null</code> if
- * not.
+ *
+ * @return Returns the text client control if specified, or
+ * <code>null</code> if not.
*/
public Control getTextClient() {
return textClient;
}
+
/**
- * Sets the text client control. Text client is a control that
- * is a child of the expandable composite and is placed to the right
- * of the text. It can be used to place small image hyperlinks. If
- * more than one control is needed, use Composite to hold them. Care should
- * be taken that the height of the control is comparable to the
- * height of the text.
- * @param textClient the textClient to set or <code>null</code> if not
- * needed any more.
+ * Sets the text client control. Text client is a control that is a child of
+ * the expandable composite and is placed to the right of the text. It can
+ * be used to place small image hyperlinks. If more than one control is
+ * needed, use Composite to hold them. Care should be taken that the height
+ * of the control is comparable to the height of the text.
+ *
+ * @param textClient
+ * the textClient to set or <code>null</code> if not needed any
+ * more.
*/
public void setTextClient(Control textClient) {
- if (this.textClient!=null)
+ if (this.textClient != null)
this.textClient.dispose();
this.textClient = textClient;
}
diff --git a/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/FormText.java b/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/FormText.java
index 381b3ea..73e1c05 100644
--- a/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/FormText.java
+++ b/bundles/org.eclipse.ui.forms/src/org/eclipse/ui/forms/widgets/FormText.java
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.forms.widgets;
+
import java.io.InputStream;
import java.util.*;
@@ -22,11 +23,12 @@
import org.eclipse.ui.forms.HyperlinkSettings;
import org.eclipse.ui.forms.events.*;
import org.eclipse.ui.internal.forms.widgets.*;
+
/**
* This class is a read-only text control that is capable of rendering wrapped
* text. Text can be rendered as-is or by parsing the formatting XML tags.
- * Independently, words that start with http:// can be converted into
- * hyperlinks on the fly.
+ * Independently, words that start with http:// can be converted into hyperlinks
+ * on the fly.
* <p>
* When configured to use formatting XML, the control requires the root element
* <code>form</code> to be used. The following tags can be children of the
@@ -48,29 +50,28 @@
* <li><b>value </b>- not used for 'bullet'. For text, it is the value of the
* text to rendered as a bullet. For image, it is the href of the image to be
* rendered as a bullet.</li>
- * <li><b>indent </b>- the number of pixels to indent the text in the list
- * item</li>
- * <li><b>bindent </b>- the number of pixels to indent the bullet itself
+ * <li><b>indent </b>- the number of pixels to indent the text in the list item
* </li>
+ * <li><b>bindent </b>- the number of pixels to indent the bullet itself</li>
* </ul>
* </li>
* </ul>
* <p>
* Text in paragraphs and list items will be wrapped according to the width of
- * the control. The following tags can appear as children of either <b>p </b>
- * or <b>li </b> elements:
+ * the control. The following tags can appear as children of either <b>p </b> or
+ * <b>li </b> elements:
* <ul>
* <li><b>img </b>- to render an image. Element accepts attribute 'href' that
* is a key to the Image set using 'setImage' method.</li>
- * <li><b>a </b>- to render a hyperlink. Element accepts attribute 'href'
- * that will be provided to the hyperlink listeners via HyperlinkEvent object.
- * The element also accepts 'nowrap' attribute (default is false). When set to
+ * <li><b>a </b>- to render a hyperlink. Element accepts attribute 'href' that
+ * will be provided to the hyperlink listeners via HyperlinkEvent object. The
+ * element also accepts 'nowrap' attribute (default is false). When set to
* 'true', the hyperlink will not be wrapped.</li>
* <li><b>b </b>- the enclosed text will use bold font.</li>
* <li><b>br </b>- forced line break (no attributes).</li>
* <li><b>span </b>- the enclosed text will have the color and font specified
- * in the element attributes. Color is provided using 'color' attribute and is
- * a key to the Color object set by 'setColor' method. Font is provided using
+ * in the element attributes. Color is provided using 'color' attribute and is a
+ * key to the Color object set by 'setColor' method. Font is provided using
* 'font' attribute and is a key to the Font object set by 'setFont' method.
* </li>
* </ul>
@@ -92,49 +93,68 @@
* fully each time. Instead, combine the control in a composite with other
* controls and let SWT take care of the dirty regions.
* </p>
- * <p>Although the class is not marked final,
+ * <p>
+ * Although the class is not marked final,
+ *
* @see FormToolkit
* @see TableWrapLayout
* @since 3.0
*/
public final class FormText extends Canvas {
/**
- * The object ID to be used when registering action to handle URL
- * hyperlinks (those that should result in opening the web browser). Value
- * is "urlHandler".
+ * The object ID to be used when registering action to handle URL hyperlinks
+ * (those that should result in opening the web browser). Value is
+ * "urlHandler".
*/
public static final String URL_HANDLER_ID = "urlHandler";
+
/**
* Value of the horizontal margin (default is 0).
*/
public int marginWidth = 0;
+
/**
* Value of hte horizontal margin (default is 1).
*/
public int marginHeight = 1;
- //private fields
+
+ // private fields
private boolean hasFocus;
+
private boolean paragraphsSeparated = true;
+
private FormTextModel model;
+
private Vector listeners;
+
private Hashtable resourceTable = new Hashtable();
+
private HyperlinkSegment entered;
+
private boolean mouseDown = false;
- //private Point dragOrigin;
+
+ // private Point dragOrigin;
private Action openAction;
+
private Action copyShortcutAction;
+
private boolean loading = true;
- //TODO translate this text
+
+ // TODO translate this text
private String loadingText = "Loading...";
+
private class FormTextLayout extends Layout implements ILayoutExtension {
public FormTextLayout() {
}
+
public int computeMaximumWidth(Composite parent, boolean changed) {
return computeSize(parent, SWT.DEFAULT, SWT.DEFAULT, changed).x;
}
+
public int computeMinimumWidth(Composite parent, boolean changed) {
return computeSize(parent, 5, SWT.DEFAULT, true).x;
}
+
/*
* @see Layout#computeSize(Composite, int, int, boolean)
*/
@@ -152,6 +172,7 @@
Point result = new Point(textWidth, textHeight);
return result;
}
+
private Point computeLoading() {
GC gc = new GC(FormText.this);
gc.setFont(getFont());
@@ -162,6 +183,7 @@
size.y += 2 * marginHeight;
return size;
}
+
private Point computeTextSize(int wHint) {
Paragraph[] paragraphs = model.getParagraphs();
GC gc = new GC(FormText.this);
@@ -195,9 +217,11 @@
gc.dispose();
return new Point(width, loc.y);
}
+
protected void layout(Composite composite, boolean flushCache) {
}
}
+
/**
* Contructs a new form text widget in the provided parent and using the
* styles.
@@ -214,8 +238,9 @@
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
model.dispose();
- Font boldFont = (Font)resourceTable.get(FormTextModel.BOLD_FONT_ID);
- if (boldFont!=null) {
+ Font boldFont = (Font) resourceTable
+ .get(FormTextModel.BOLD_FONT_ID);
+ if (boldFont != null) {
boldFont.dispose();
}
}
@@ -236,12 +261,12 @@
addListener(SWT.Traverse, new Listener() {
public void handleEvent(Event e) {
switch (e.detail) {
- case SWT.TRAVERSE_PAGE_NEXT :
- case SWT.TRAVERSE_PAGE_PREVIOUS :
- case SWT.TRAVERSE_ARROW_NEXT :
- case SWT.TRAVERSE_ARROW_PREVIOUS :
- e.doit = false;
- return;
+ case SWT.TRAVERSE_PAGE_NEXT:
+ case SWT.TRAVERSE_PAGE_PREVIOUS:
+ case SWT.TRAVERSE_ARROW_NEXT:
+ case SWT.TRAVERSE_ARROW_PREVIOUS:
+ e.doit = false;
+ return;
}
if (!model.hasFocusSegments()) {
e.doit = true;
@@ -262,6 +287,7 @@
handleFocusChange();
}
}
+
public void focusLost(FocusEvent e) {
if (hasFocus) {
hasFocus = false;
@@ -272,10 +298,12 @@
addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent e) {
}
+
public void mouseDown(MouseEvent e) {
// select a link
handleMouseClick(e, true);
}
+
public void mouseUp(MouseEvent e) {
// activate a link
handleMouseClick(e, false);
@@ -285,6 +313,7 @@
public void mouseEnter(MouseEvent e) {
handleMouseMove(e);
}
+
public void mouseExit(MouseEvent e) {
if (entered != null) {
exitLink(entered, e.stateMask);
@@ -293,6 +322,7 @@
setCursor(null);
}
}
+
public void mouseHover(MouseEvent e) {
handleMouseHover(e);
}
@@ -306,6 +336,7 @@
makeActions();
ensureBoldFontPresent(getFont());
}
+
/**
* Test for focus.
*
@@ -314,6 +345,7 @@
public boolean getFocus() {
return hasFocus;
}
+
/**
* Test if the widget is currently processing the text it is about to
* render.
@@ -324,20 +356,22 @@
public boolean isLoading() {
return loading;
}
+
/**
- * Returns the text that will be shown in the control while the real
- * content is loading.
+ * Returns the text that will be shown in the control while the real content
+ * is loading.
*
* @return loading text message
*/
public String getLoadingText() {
return loadingText;
}
+
/**
- * Sets the text that will be shown in the control while the real content
- * is loading. This is significant when content to render is loaded from
- * the input stream that was created from a remote URL, and the time to
- * load the entire content is nontrivial.
+ * Sets the text that will be shown in the control while the real content is
+ * loading. This is significant when content to render is loaded from the
+ * input stream that was created from a remote URL, and the time to load the
+ * entire content is nontrivial.
*
* @param loadingText
* loading text message
@@ -345,6 +379,7 @@
public void setLoadingText(String loadingText) {
this.loadingText = loadingText;
}
+
/**
* If paragraphs are separated, spacing will be added between them.
* Otherwise, new paragraphs will simply start on a new line with no
@@ -357,6 +392,7 @@
public void setParagraphsSeparated(boolean value) {
paragraphsSeparated = value;
}
+
/**
* Tests if there is some inter-paragraph spacing.
*
@@ -366,6 +402,7 @@
public boolean getParagraphsSeparated() {
return paragraphsSeparated;
}
+
/**
* Registers the image referenced by the provided key.
* <p>
@@ -382,12 +419,13 @@
public void setImage(String key, Image image) {
resourceTable.put("i." + key, image);
}
+
/**
* Registers the color referenced by the provided key.
* <p>
- * For <samp>span </samp> tags, an object of a type <samp>Color </samp>
- * must be registered using the key equivalent to the value of the <samp>
- * color </samp> attribute.
+ * For <samp>span </samp> tags, an object of a type <samp>Color </samp> must
+ * be registered using the key equivalent to the value of the <samp>color
+ * </samp> attribute.
*
* @param key
* unique key that matches the value of the <samp>color </samp>
@@ -398,6 +436,7 @@
public void setColor(String key, Color color) {
resourceTable.put("c." + key, color);
}
+
/**
* Registers the font referenced by the provided key.
* <p>
@@ -414,22 +453,25 @@
public void setFont(String key, Font font) {
resourceTable.put("f." + key, font);
}
+
/**
- * Sets the font to use to render the default
- * text (text that does not have special font property
- * assigned). Bold font will be constructed from
- * this font.
- * @param font the default font to use
+ * Sets the font to use to render the default text (text that does not have
+ * special font property assigned). Bold font will be constructed from this
+ * font.
+ *
+ * @param font
+ * the default font to use
*/
public void setFont(Font font) {
super.setFont(font);
- Font boldFont = (Font)resourceTable.get(FormTextModel.BOLD_FONT_ID);
- if (boldFont!=null) {
+ Font boldFont = (Font) resourceTable.get(FormTextModel.BOLD_FONT_ID);
+ if (boldFont != null) {
boldFont.dispose();
resourceTable.remove(FormTextModel.BOLD_FONT_ID);
}
ensureBoldFontPresent(getFont());
}
+
/**
* Sets the provided text. Text can be rendered as-is, or by parsing the
* formatting tags. Optionally, sections of text starting with http:// will
@@ -441,8 +483,8 @@
* if <samp>true </samp>, formatting tags will be parsed.
* Otherwise, text will be rendered as-is.
* @param expandURLs
- * if <samp>true </samp>, URLs found in the untagged text will
- * be converted into hyperlinks.
+ * if <samp>true </samp>, URLs found in the untagged text will be
+ * converted into hyperlinks.
*/
public void setText(String text, boolean parseTags, boolean expandURLs) {
if (parseTags)
@@ -453,9 +495,10 @@
layout();
redraw();
}
+
/**
- * Sets the contents of the stream. Optionally, URLs in untagged text can
- * be converted into hyperlinks. The caller is responsible for closing the
+ * Sets the contents of the stream. Optionally, URLs in untagged text can be
+ * converted into hyperlinks. The caller is responsible for closing the
* stream.
*
* @param is
@@ -470,33 +513,39 @@
layout();
redraw();
}
+
/**
- * Controls whether whitespace inside paragraph and list
- * items is normalized.
- * <p>If normalized:
+ * Controls whether whitespace inside paragraph and list items is
+ * normalized.
+ * <p>
+ * If normalized:
* <ul>
- * <li>all white space characters will
- * be condensed into at most one when between words.</li>
- * <li>new line characters will be ignored and replaced
- * with one white space character</li>
- * <li>white space characters after the opening
- * tags and before the closing tags will be trimmed</li>
- * @param value <code>true</code> if whitespace is
- * normalized, <code>false</code> otherwise.
+ * <li>all white space characters will be condensed into at most one when
+ * between words.</li>
+ * <li>new line characters will be ignored and replaced with one white
+ * space character</li>
+ * <li>white space characters after the opening tags and before the closing
+ * tags will be trimmed</li>
+ *
+ * @param value
+ * <code>true</code> if whitespace is normalized,
+ * <code>false</code> otherwise.
*/
public void setWhitespaceNormalized(boolean value) {
model.setWhitespaceNormalized(value);
}
+
/**
- * Tests whether whitespace inside paragraph and
- * list item is normalized.
+ * Tests whether whitespace inside paragraph and list item is normalized.
+ *
* @see #setWhitespaceNormalized(boolean)
- * @return <code>true</code> if whitespace is
- * normalized, <code>false</code> otherwise.
+ * @return <code>true</code> if whitespace is normalized,
+ * <code>false</code> otherwise.
*/
public boolean isWhitespaceNormalized() {
return model.isWhitespaceNormalized();
}
+
/**
* Sets the focus to the first hyperlink, or the widget itself if there are
* no hyperlinks.
@@ -510,6 +559,7 @@
*/
return super.setFocus();
}
+
/**
* Returns the hyperlink settings that are in effect for this control.
*
@@ -518,6 +568,7 @@
public HyperlinkSettings getHyperlinkSettings() {
return model.getHyperlinkSettings();
}
+
/**
* Sets the hyperlink settings to be used for this control. Settings will
* affect things like hyperlink color, rendering style, cursor etc.
@@ -528,6 +579,7 @@
public void setHyperlinkSettings(HyperlinkSettings settings) {
model.setHyperlinkSettings(settings);
}
+
/**
* Adds a listener that will handle hyperlink events.
*
@@ -540,6 +592,7 @@
if (!listeners.contains(listener))
listeners.add(listener);
}
+
/**
* Removes the hyperlink listener.
*
@@ -551,6 +604,23 @@
return;
listeners.remove(listener);
}
+
+ /**
+ * Returns the reference of the hyperlink that currently has keyboard focus,
+ * or <code>null</code> if there are no hyperlinks in the receiver or no
+ * hyperlink has focus at the moment.
+ *
+ * @return href of the selected hyperlink or <code>null</code> if none
+ * selected.
+ * @since 3.1
+ */
+ public Object getSelectedLinkHref() {
+ HyperlinkSegment link = model.getSelectedLink();
+ if (link != null)
+ return link.getHref();
+ return null;
+ }
+
/**
* Context menu is about to show - override to add actions to the menu
* manager. Subclasses are required to call 'super' when overriding.
@@ -563,6 +633,7 @@
if (link != null)
contributeLinkActions(manager, link);
}
+
private void makeActions() {
/*
* openAction = new Action() { public void run() {
@@ -574,15 +645,18 @@
* FormsPlugin.getResourceString("FormEgine.linkPopup.copyShortcut"));
*/
}
+
private String getAcessibleText() {
return model.getAccessibleText();
}
+
private void initAccessible() {
Accessible accessible = getAccessible();
accessible.addAccessibleListener(new AccessibleAdapter() {
public void getName(AccessibleEvent e) {
e.result = getAcessibleText();
}
+
public void getHelp(AccessibleEvent e) {
e.result = getToolTipText();
}
@@ -590,10 +664,10 @@
accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
public void getChildAtPoint(AccessibleControlEvent e) {
Point pt = toControl(new Point(e.x, e.y));
- e.childID = (getBounds().contains(pt))
- ? ACC.CHILDID_SELF
+ e.childID = (getBounds().contains(pt)) ? ACC.CHILDID_SELF
: ACC.CHILDID_NONE;
}
+
public void getLocation(AccessibleControlEvent e) {
Rectangle location = getBounds();
Point pt = toDisplay(new Point(location.x, location.y));
@@ -602,17 +676,21 @@
e.width = location.width;
e.height = location.height;
}
+
public void getChildCount(AccessibleControlEvent e) {
e.detail = 0;
}
+
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_TEXT;
}
+
public void getState(AccessibleControlEvent e) {
e.detail = ACC.STATE_READONLY;
}
});
}
+
private void handleMouseClick(MouseEvent e, boolean down) {
if (down) {
// select a hyperlink
@@ -624,7 +702,7 @@
paintFocusTransfer(oldLink, segmentUnder);
}
mouseDown = true;
- //dragOrigin = new Point(e.x, e.y);
+ // dragOrigin = new Point(e.x, e.y);
} else {
if (e.button == 1) {
HyperlinkSegment segmentUnder = model.findHyperlinkAt(e.x, e.y);
@@ -635,8 +713,10 @@
mouseDown = false;
}
}
+
private void handleMouseHover(MouseEvent e) {
}
+
private void handleMouseMove(MouseEvent e) {
if (mouseDown) {
handleDrag(e);
@@ -669,6 +749,7 @@
}
}
}
+
private boolean advance(boolean next) {
HyperlinkSegment current = model.getSelectedLink();
if (current != null)
@@ -682,6 +763,7 @@
ensureVisible(newLink);
return !valid;
}
+
private void handleFocusChange() {
if (hasFocus) {
model.traverseLinks(true);
@@ -693,6 +775,7 @@
model.selectLink(null);
}
}
+
private void enterLink(HyperlinkSegment link, int stateMask) {
if (link == null || listeners == null)
return;
@@ -704,6 +787,7 @@
listener.linkEntered(he);
}
}
+
private void exitLink(HyperlinkSegment link, int stateMask) {
if (link == null || listeners == null)
return;
@@ -715,6 +799,7 @@
listener.linkExited(he);
}
}
+
private void paintLinkHover(HyperlinkSegment link, boolean hover) {
GC gc = new GC(this);
HyperlinkSettings settings = getHyperlinkSettings();
@@ -730,11 +815,13 @@
}
gc.dispose();
}
+
private void activateSelectedLink() {
HyperlinkSegment link = model.getSelectedLink();
if (link != null)
activateLink(link, SWT.NULL);
}
+
private void activateLink(HyperlinkSegment link, int stateMask) {
setCursor(model.getHyperlinkSettings().getBusyCursor());
if (listeners != null) {
@@ -750,9 +837,11 @@
if (!isDisposed())
setCursor(model.getHyperlinkSettings().getHyperlinkCursor());
}
+
private void ensureBoldFontPresent(Font regularFont) {
- Font boldFont = (Font)resourceTable.get(FormTextModel.BOLD_FONT_ID);
- if (boldFont!=null) return;
+ Font boldFont = (Font) resourceTable.get(FormTextModel.BOLD_FONT_ID);
+ if (boldFont != null)
+ return;
FontData[] fontDatas = regularFont.getFontData();
for (int i = 0; i < fontDatas.length; i++) {
fontDatas[i].setStyle(fontDatas[i].getStyle() | SWT.BOLD);
@@ -760,6 +849,7 @@
boldFont = new Font(getDisplay(), fontDatas);
resourceTable.put(FormTextModel.BOLD_FONT_ID, boldFont);
}
+
private void paint(PaintEvent e) {
Rectangle carea = getClientArea();
GC gc = e.gc;
@@ -767,7 +857,7 @@
ensureBoldFontPresent(getFont());
gc.setForeground(getForeground());
gc.setBackground(getBackground());
-
+
Locator loc = new Locator();
loc.marginWidth = marginWidth;
loc.marginHeight = marginHeight;
@@ -783,7 +873,7 @@
textGC.setBackground(getBackground());
textGC.setFont(getFont());
textGC.fillRectangle(0, 0, carea.width, carea.height);
-
+
if (loading) {
int textWidth = gc.textExtent(loadingText).x;
textGC.drawText(loadingText, carea.width / 2 - textWidth / 2,
@@ -806,9 +896,11 @@
textGC.dispose();
textBuffer.dispose();
}
+
private int getParagraphSpacing(int lineHeight) {
return lineHeight / 2;
}
+
private void paintFocusTransfer(HyperlinkSegment oldLink,
HyperlinkSegment newLink) {
GC gc = new GC(this);
@@ -821,27 +913,27 @@
oldLink.paintFocus(gc, bg, fg, false);
}
if (newLink != null) {
- //ensureVisible(newLink);
+ // ensureVisible(newLink);
gc.setBackground(bg);
gc.setForeground(fg);
newLink.paintFocus(gc, bg, fg, true);
}
gc.dispose();
}
+
private void contributeLinkActions(IMenuManager manager,
HyperlinkSegment link) {
manager.add(openAction);
manager.add(copyShortcutAction);
manager.add(new Separator());
}
-/*
- private void copyShortcut(HyperlinkSegment link) {
- String text = link.getText();
- Clipboard clipboard = new Clipboard(getDisplay());
- clipboard.setContents(new Object[]{text}, new Transfer[]{TextTransfer
- .getInstance()});
- }
-*/
+
+ /*
+ * private void copyShortcut(HyperlinkSegment link) { String text =
+ * link.getText(); Clipboard clipboard = new Clipboard(getDisplay());
+ * clipboard.setContents(new Object[]{text}, new Transfer[]{TextTransfer
+ * .getInstance()}); }
+ */
private void ensureVisible(HyperlinkSegment segment) {
if (segment == null)
return;
@@ -858,9 +950,10 @@
private void handleDrag(MouseEvent e) {
}
+
/**
- * Overrides the method by fully trusting the layout manager (computed
- * width or height may be larger than the provider width or height hints).
+ * Overrides the method by fully trusting the layout manager (computed width
+ * or height may be larger than the provider width or height hints).
*/
public Point computeSize(int wHint, int hHint, boolean changed) {
checkWidget();