diff --git a/src/main/java/forge/gui/toolbox/FHyperlink.java b/src/main/java/forge/gui/toolbox/FHyperlink.java
new file mode 100644
index 00000000000..50525855235
--- /dev/null
+++ b/src/main/java/forge/gui/toolbox/FHyperlink.java
@@ -0,0 +1,105 @@
+package forge.gui.toolbox;
+
+import java.awt.Cursor;
+import java.awt.Desktop;
+import java.awt.Toolkit;
+import java.awt.datatransfer.StringSelection;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.swing.JOptionPane;
+import javax.swing.SwingWorker;
+
+import forge.Command;
+
+
+
+@SuppressWarnings("serial")
+public class FHyperlink extends FLabel {
+ public static class Builder extends FLabel.Builder {
+ private String bldUrl;
+
+ public Builder() {
+ bldHoverable = true;
+ bldReactOnMouseDown = true;
+ bldCmd = null;
+ }
+
+ public FHyperlink build() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("");
+ sb.append((null == bldText || bldText.isEmpty()) ? bldUrl : bldText);
+ sb.append("");
+
+ final boolean browsingSupported = _isBrowsingSupported();
+ if (browsingSupported) {
+ tooltip(bldUrl);
+ } else {
+ tooltip(bldUrl + " (click to copy to clipboard)");
+ }
+
+ final URI uri;
+ try {
+ uri = new URI(bldUrl);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+
+ // overwrite whatever command is there -- we could chain them if we wanted to, though
+ cmdClick(new Command() {
+ @Override
+ public void execute() {
+ if (browsingSupported) {
+ // open link in default browser
+ new _LinkRunner(uri).execute();
+ } else {
+ // copy link to clipboard
+ StringSelection ss = new StringSelection(bldUrl);
+ try {
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
+ } catch (IllegalStateException ex) {
+ JOptionPane.showMessageDialog(null,
+ "Sorry, a problem occurred while copying this link to your system clipboard.",
+ "A problem occured", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ });
+
+ return new FHyperlink(this);
+ }
+
+ public Builder url(String url) { bldUrl = url; return this; }
+
+ private static boolean _isBrowsingSupported() {
+ if (!Desktop.isDesktopSupported()) {
+ return false;
+ }
+ return Desktop.getDesktop().isSupported(Desktop.Action.BROWSE);
+ }
+ }
+
+ // Call this using FLabel.Builder()...
+ private FHyperlink(final Builder b) {
+ super(b);
+
+ setCursor(new Cursor(Cursor.HAND_CURSOR));
+ }
+
+ private static class _LinkRunner extends SwingWorker {
+ private final URI uri;
+
+ private _LinkRunner(URI u) {
+ if (u == null) {
+ throw new NullPointerException();
+ }
+ uri = u;
+ }
+
+ @Override
+ protected Void doInBackground() throws Exception {
+ Desktop.getDesktop().browse(uri);
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/forge/gui/toolbox/FLabel.java b/src/main/java/forge/gui/toolbox/FLabel.java
index 6ac46273736..4f05e4679f7 100644
--- a/src/main/java/forge/gui/toolbox/FLabel.java
+++ b/src/main/java/forge/gui/toolbox/FLabel.java
@@ -65,18 +65,18 @@ public class FLabel extends JLabel implements ILocalRepaint {
private int bldIconAlignX = SwingConstants.LEFT;
private Point bldIconInsets = new Point(0, 0);
- private boolean bldSelectable = false;
- private boolean bldSelected = false;
- protected boolean bldHoverable = false;
- protected boolean bldOpaque = false;
- private boolean bldIconInBackground = false;
- private boolean bldIconScaleAuto = true;
- private boolean reactOnMouseDown = false;
+ private boolean bldSelectable = false;
+ private boolean bldSelected = false;
+ protected boolean bldHoverable = false;
+ protected boolean bldOpaque = false;
+ private boolean bldIconInBackground = false;
+ private boolean bldIconScaleAuto = true;
+ protected boolean bldReactOnMouseDown = false;
- private String bldText, bldToolTip;
+ protected String bldText, bldToolTip;
private ImageIcon bldIcon;
private int bldFontAlign;
- private Command bldCmd;
+ protected Command bldCmd;
// Build!
/** @return {@link forge.gui.toolbox.FLabel} */
@@ -121,7 +121,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
/**@param b0 boolean that controls when the label responds to mouse events
* @return {@link forge.gui.toolbox.Builder} */
- public Builder reactOnMouseDown(final boolean b0) { this.reactOnMouseDown = b0; return this; }
+ public Builder reactOnMouseDown(final boolean b0) { this.bldReactOnMouseDown = b0; return this; }
public Builder reactOnMouseDown() { reactOnMouseDown(true); return this; }
/**@param c0 {@link forge.Command} to execute if clicked
@@ -173,11 +173,8 @@ public class FLabel extends JLabel implements ILocalRepaint {
}
//========== Constructors
- /** Must have protected constructor to allow Builder to subclass. */
- protected FLabel() { }
-
// Call this using FLabel.Builder()...
- private FLabel(final Builder b0) {
+ protected FLabel(final Builder b0) {
super(b0.bldText);
// Init fields from builder
@@ -195,7 +192,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.setFontSize(b0.bldFontSize);
this.setUnhoveredAlpha(b0.bldUnhoveredAlpha);
this.setCommand(b0.bldCmd);
- this.setReactOnMouseDown(b0.reactOnMouseDown);
+ this.setReactOnMouseDown(b0.bldReactOnMouseDown);
this.setFontAlign(b0.bldFontAlign);
this.setToolTipText(b0.bldToolTip);
this.setHoverable(b0.bldHoverable);
@@ -293,7 +290,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
private void _doMouseAction() {
if (selectable) { setSelected(!selected); }
- if (cmdClick != null && FLabel.this.isEnabled()) {
+ if (cmdClick != null && isEnabled()) {
hovered = false;
repaintSelf();
cmdClick.execute();
@@ -447,7 +444,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
/** Major performance kicker - won't repaint whole screen! */
@Override
public void repaintSelf() {
- final Dimension d = FLabel.this.getSize();
+ final Dimension d = getSize();
repaint(0, 0, d.width, d.height);
}
@@ -546,7 +543,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
int w = (int) (h * iar);
if (w == 0 || h == 0) { return; }
- FLabel.super.setIcon(new ImageIcon(img.getScaledInstance(w, h, Image.SCALE_SMOOTH)));
+ super.setIcon(new ImageIcon(img.getScaledInstance(w, h, Image.SCALE_SMOOTH)));
}
}
}