Bug 563216 - [E4 UI] Rework About text parsing

Renamed "AboutItem" to "ParsedAbout"
Reduced code duplication in "AboutText"

Change-Id: I2ac679234d20b7b87120ba353b0c8f648d388566
Signed-off-by: Alexander Fedorov <alexander.fedorov@arsysop.ru>
diff --git a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutDialogE4.java b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutDialogE4.java
index 16df925..79eddf4 100644
--- a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutDialogE4.java
+++ b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutDialogE4.java
@@ -82,7 +82,7 @@
 	protected Control createDialogArea(final Composite parent) {

 		// brand the about box if there is product info

 		Optional<Image> aboutImage = Optional.empty();

-		Optional<AboutItem> aboutItem = Optional.empty();

+		Optional<ParsedAbout> aboutItem = Optional.empty();

 

 		// if the about image is small enough, then show the text

 		aboutImage = product.getAboutImage();

@@ -128,7 +128,7 @@
 		return workArea;

 	}

 

-	private void createTextWidget(final Composite parent, AboutItem aboutItem, Color background, Color foreground,

+	private void createTextWidget(final Composite parent, ParsedAbout aboutItem, Color background, Color foreground,

 			final Composite topContainer) {

 		final Composite textComposite = WidgetFactory.composite(SWT.NONE).background(background).create(topContainer);

 

@@ -137,7 +137,7 @@
 

 		textWidget = new StyledText(textComposite, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);

 		textWidget.setFont(parent.getFont());

-		textWidget.setText(aboutItem.getText());

+		textWidget.setText(aboutItem.text());

 		textWidget.setBackground(background);

 		textWidget.setForeground(foreground);

 		textWidget.setAlwaysShowScrollBars(false);

diff --git a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutItem.java b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutItem.java
deleted file mode 100644
index 941e256..0000000
--- a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutItem.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*******************************************************************************

- * Copyright (c) 2000, 2020 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v2.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v20.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *     Ralf Heydenreich - Bug 559694

- *******************************************************************************/

-package org.eclipse.e4.ui.internal.dialogs.about;

-

-import java.util.ArrayList;

-import java.util.List;

-import java.util.Optional;

-

-/**

- * Holds the information for text appearing in the about dialog

- */

-public class AboutItem {

-	private final String text;

-

-	private final List<HyperlinkRange> linkRanges = new ArrayList<>();

-

-	private final List<String> hrefs;

-

-	/**

-	 * Creates a new about item

-	 */

-	public AboutItem(String text, List<HyperlinkRange> linkRanges, List<String> links) {

-		this.text = text;

-		this.linkRanges.addAll(linkRanges);

-		this.hrefs = links;

-	}

-

-	/**

-	 * Returns the link ranges (character locations)

-	 */

-	public List<HyperlinkRange> getLinkRanges() {

-		return linkRanges;

-	}

-

-	/**

-	 * Returns the text to display

-	 */

-	public String getText() {

-		return text;

-	}

-

-	/**

-	 * Returns true if a link is present at the given character location

-	 */

-	public boolean isLinkAt(int offset) {

-		// Check if there is a link at the offset

-		Optional<HyperlinkRange> potentialMatch = linkRanges.stream().filter(r -> r.contains(offset)).findAny();

-		return potentialMatch.isPresent();

-	}

-

-	/**

-	 * Returns the link at the given offset (if there is one), otherwise returns

-	 * <code>null</code>.

-	 */

-	public Optional<String> getLinkAt(int offset) {

-		// Check if there is a link at the offset

-		for (int i = 0; i < linkRanges.size(); i++) {

-			if (linkRanges.get(i).contains(offset)) {

-				return Optional.of(hrefs.get(i));

-			}

-		}

-		return Optional.empty();

-	}

-}

diff --git a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutText.java b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutText.java
index 9957682..2dab0a8 100644
--- a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutText.java
+++ b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/AboutText.java
@@ -49,13 +49,13 @@
 	private boolean mouseDown = false;

 	private boolean dragEvent = false;

 

-	private AboutItem item;

+	private ParsedAbout item;

 

-	public AboutText(final Supplier<AboutItem> item) {

+	public AboutText(final Supplier<ParsedAbout> item) {

 		this.setItem(item.get());

 	}

 

-	public AboutText(StyledText text, final Supplier<AboutItem> item) {

+	public AboutText(StyledText text, final Supplier<ParsedAbout> item) {

 		this.styledText = text;

 		this.setItem(item.get());

 		createCursors();

@@ -77,7 +77,7 @@
 		}

 

 		HyperlinkExtractor hyperlinkExtractor = new HyperlinkExtractor(aboutProperty);

-		setItem(new AboutItem(aboutProperty, hyperlinkExtractor.getLinkRanges(), hyperlinkExtractor.getLinks()));

+		setItem(new ParsedAbout(aboutProperty, hyperlinkExtractor.getLinkRanges(), hyperlinkExtractor.getLinks()));

 	}

 

 	private void createCursors() {

@@ -108,18 +108,15 @@
 			public void mouseUp(MouseEvent e) {

 				mouseDown = false;

 				int offset = styledText.getCaretOffset();

+				Optional<String> link = safeLinkAt(offset);

 				if (dragEvent) {

 					// don't activate a link during a drag/mouse up operation

 					dragEvent = false;

-					if (item != null && item.isLinkAt(offset)) {

+					if (link.isPresent()) {

 						styledText.setCursor(handCursor);

 					}

-				} else if (item != null && item.isLinkAt(offset)) {

-					styledText.setCursor(busyCursor);

-					item.getLinkAt(offset).ifPresent(l -> Program.launch(l));

-					StyleRange selectionRange = getCurrentRange();

-					styledText.setSelectionRange(selectionRange.start, selectionRange.length);

-					styledText.setCursor(null);

+				} else if (link.isPresent()) {

+					launch(styledText, link.get());

 				}

 			}

 		});

@@ -143,7 +140,7 @@
 			}

 			if (offset == -1) {

 				text.setCursor(null);

-			} else if (item != null && item.isLinkAt(offset)) {

+			} else if (safeLinkAt(offset).isPresent()) {

 				text.setCursor(handCursor);

 			} else {

 				text.setCursor(null);

@@ -204,32 +201,34 @@
 		styledText.addKeyListener(new KeyAdapter() {

 			@Override

 			public void keyPressed(KeyEvent event) {

-				StyledText text = (StyledText) event.widget;

 				if (event.character == ' ' || event.character == SWT.CR) {

-					if (item != null) {

-						// Be sure we are in the selection

-						int offset = text.getSelection().x + 1;

-

-						if (item.isLinkAt(offset)) {

-							text.setCursor(busyCursor);

-							item.getLinkAt(offset).ifPresent(l -> Program.launch(l));

-							StyleRange selectionRange = getCurrentRange();

-							text.setSelectionRange(selectionRange.start, selectionRange.length);

-							text.setCursor(null);

-						}

-					}

-					return;

+					StyledText text = (StyledText) event.widget;

+					// Be sure we are in the selection

+					int offset = text.getSelection().x + 1;

+					safeLinkAt(offset).ifPresent(l -> launch(text, l));

 				}

 			}

 		});

 	}

 

+	private Optional<String> safeLinkAt(int offset) {

+		return Optional.ofNullable(item).flatMap(a -> a.linkAt(offset));

+	}

+

+	private void launch(StyledText text, String link) {

+		text.setCursor(busyCursor);

+		Program.launch(link);

+		StyleRange selectionRange = getCurrentRange();

+		text.setSelectionRange(selectionRange.start, selectionRange.length);

+		text.setCursor(null);

+	}

+

 	/**

 	 * Gets the about item.

 	 *

 	 * @return the about item

 	 */

-	public Optional<AboutItem> getAboutItem() {

+	public Optional<ParsedAbout> getAboutItem() {

 		if (item == null) {

 			createAboutItem();

 		}

@@ -241,11 +240,11 @@
 	 *

 	 * @param item about item

 	 */

-	private void setItem(AboutItem item) {

+	private void setItem(ParsedAbout item) {

 		this.item = item;

 		if (item != null && styledText != null) {

-			styledText.setText(item.getText());

-			setLinkRanges(item.getLinkRanges());

+			styledText.setText(item.text());

+			setLinkRanges(item.linkRanges());

 		}

 	}

 

diff --git a/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/ParsedAbout.java b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/ParsedAbout.java
new file mode 100644
index 0000000..be3bc8c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.dialogs/src/org/eclipse/e4/ui/internal/dialogs/about/ParsedAbout.java
@@ -0,0 +1,62 @@
+/*******************************************************************************

+ * Copyright (c) 2000, 2020 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v2.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v20.html

+ *

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *     Ralf Heydenreich - Bug 559694

+ *******************************************************************************/

+package org.eclipse.e4.ui.internal.dialogs.about;

+

+import java.util.ArrayList;

+import java.util.List;

+import java.util.Optional;

+

+/**

+ * Holds the information for text appearing in the about dialog

+ */

+public class ParsedAbout {

+	private final String text;

+	private final List<HyperlinkRange> ranges = new ArrayList<>();

+	private final List<String> links = new ArrayList<>();

+

+	/**

+	 * Creates a new about item

+	 */

+	ParsedAbout(String text, List<HyperlinkRange> linkRanges, List<String> links) {

+		this.text = text;

+		this.ranges.addAll(linkRanges);

+		this.links.addAll(links);

+	}

+

+	/**

+	 * Returns the link ranges (character locations)

+	 */

+	public List<HyperlinkRange> linkRanges() {

+		return ranges;

+	}

+

+	/**

+	 * Returns the text to display

+	 */

+	public String text() {

+		return text;

+	}

+

+	/**

+	 * Returns the {@link Optional} that contains a link at the given offset (if

+	 * there is one), otherwise returns empty {@link Optional}.

+	 */

+	public Optional<String> linkAt(int offset) {

+		// Check if there is a link at the offset

+		for (int i = 0; i < ranges.size(); i++) {

+			if (ranges.get(i).contains(offset)) {

+				return Optional.of(links.get(i));

+			}

+		}

+		return Optional.empty();

+	}

+}