Skip to content
Snippets Groups Projects
Commit 5f089216 authored by Andre Brait's avatar Andre Brait
Browse files

New help mechanism and web pages being parameterized

parent 27fc130e
No related branches found
No related tags found
No related merge requests found
BSD 3-Clause License BSD 3-Clause License
Copyright (c) 2007, Distributed Computing Group (DCG), ETH Zurich, Switzerland, http://dcg.ethz.ch Copyright (c) 2007, Distributed Computing Group (DCG), ETH Zurich, Switzerland, https://dcg.ethz.ch
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
......
...@@ -52,7 +52,7 @@ message whether it should arrive or not. E.g. drop one percent of all messages. ...@@ -52,7 +52,7 @@ message whether it should arrive or not. E.g. drop one percent of all messages.
arrives at its destination. arrives at its destination.
DISCLAIMER: DISCLAIMER:
Sinalgo was originally developed by the [DCG (Distributed Computing Group)](https://disco.ethz.ch/) at [ETHzürich](http://www.ethz.ch/). Sinalgo was originally developed by the [DCG (Distributed Computing Group)](https://disco.ethz.ch/) at [ETHzürich](https://www.ethz.ch/).
## Installation and usage ## Installation and usage
......
1.0.0-beta4 1.0.0-beta5
\ No newline at end of file \ No newline at end of file
https://sinalgo.github.io
\ No newline at end of file
https://github.com/Sinalgo/sinalgo
\ No newline at end of file
...@@ -89,6 +89,8 @@ task wrapper(type: Wrapper) { ...@@ -89,6 +89,8 @@ task wrapper(type: Wrapper) {
processResources { processResources {
with copySpec { with copySpec {
from 'VERSION' from 'VERSION'
from 'WEB_PAGE_URL'
from 'WEB_REPOSITORY_URL'
} }
with copySpec { with copySpec {
......
...@@ -69,14 +69,7 @@ import java.util.List; ...@@ -69,14 +69,7 @@ import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Scanner; import java.util.Scanner;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.MODELS_CONNECTIVITY; import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.*;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.MODELS_DISTRIBUTION;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.MODELS_INTERFERENCE;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.MODELS_MESSAGE_TRANSMISSION;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.MODELS_MOBILITY;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.MODELS_RELIABILITY;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.NODES_EDGES;
import static sinalgo.configuration.Configuration.ImplementationChoiceInConfigFile.ImplementationType.NODES_IMPLEMENTATIONS;
/** /**
* This class provides globally visible constants and access to the custom * This class provides globally visible constants and access to the custom
...@@ -111,6 +104,34 @@ public class Configuration { ...@@ -111,6 +104,34 @@ public class Configuration {
} }
} }
/**
* The repository which contains the latest code changes for Sinalgo
*/
public static final String SINALGO_REPO = getRepoString();
private static String getRepoString() {
try {
return new Scanner(Thread.currentThread().getContextClassLoader().getResourceAsStream("WEB_REPOSITORY_URL"),
StandardCharsets.UTF_8.displayName()).useDelimiter("\\A").next().trim();
} catch (Exception e) {
throw new SinalgoFatalException("Could not read version information from the WEB_REPOSITORY_URL file.\n\n" + e);
}
}
/**
* The webpage that contains Sinalgo's tutorial and help files
*/
public static final String SINALGO_WEB_PAGE = getWebPageString();
private static String getWebPageString() {
try {
return new Scanner(Thread.currentThread().getContextClassLoader().getResourceAsStream("WEB_PAGE_URL"),
StandardCharsets.UTF_8.displayName()).useDelimiter("\\A").next().trim();
} catch (Exception e) {
throw new SinalgoFatalException("Could not read version information from the WEB_PAGE_URL file.\n\n" + e);
}
}
/** /**
* The annotation to be used for fields that are included by default in the * The annotation to be used for fields that are included by default in the
* configuration file. The description contains a brief description of this * configuration file. The description contains a brief description of this
......
...@@ -49,6 +49,9 @@ import java.awt.datatransfer.StringSelection; ...@@ -49,6 +49,9 @@ import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
public class AboutDialog extends JDialog implements ActionListener { public class AboutDialog extends JDialog implements ActionListener {
...@@ -75,11 +78,11 @@ public class AboutDialog extends JDialog implements ActionListener { ...@@ -75,11 +78,11 @@ public class AboutDialog extends JDialog implements ActionListener {
+ "<center><h1><span class='red'>Si</span>mulator for <span class='red'>N</span>etwork <span class='red'>Algo</span>rithms</h1></center>" + "<center><h1><span class='red'>Si</span>mulator for <span class='red'>N</span>etwork <span class='red'>Algo</span>rithms</h1></center>"
+ "" + "<center>Version " + Configuration.VERSION_STRING + "" + "<center>Version " + Configuration.VERSION_STRING
+ "</center><center><small><a href='TestVersion'>Test for newer version</a></small></center>" + "</center><center><small><a href='TestVersion'>Test for newer version</a></small></center>"
+ "<p>Visit <a href='https://github.com/Sinalgo/sinalgo'>https://github.com/Sinalgo/sinalgo</a> to obtain the latest version, report bugs or problems, " + "<p>Visit <a href='" + Configuration.SINALGO_REPO + "'>" + Configuration.SINALGO_REPO + "</a> to obtain the latest version, report bugs or problems, "
+ "and visit <a href='https://github.com/Sinalgo/sinalgo'>https://github.com/Sinalgo/sinalgo</a> for a documentation of Sinalgo" + "and visit <a href='" + Configuration.SINALGO_WEB_PAGE + "'>" + Configuration.SINALGO_WEB_PAGE + "</a> for a documentation of Sinalgo"
+ "<p>" + "<p>"
+ "Sinalgo is brought to you by the Distributed Computing Group of ETH Zurich <a href='http://dcg.ethz.ch'>http://dcg.ethz.ch</a>" + "Sinalgo is brought to you by the Distributed Computing Group of ETH Zurich <a href='https://dcg.ethz.ch'>https://dcg.ethz.ch</a>"
+ "<p>" + "<small>Hint: Click on a link to copy it to the clip board.</small>" + "</body>" + "</html>"); + "<p>" + "</body>" + "</html>");
html.setEditable(false); html.setEditable(false);
html.setBackground(this.getBackground()); html.setBackground(this.getBackground());
this.add(html); this.add(html);
...@@ -90,19 +93,14 @@ public class AboutDialog extends JDialog implements ActionListener { ...@@ -90,19 +93,14 @@ public class AboutDialog extends JDialog implements ActionListener {
VersionTester.testVersion(false, true); VersionTester.testVersion(false, true);
return; return;
} }
Desktop dt = Desktop.getDesktop();
try {
dt.browse(new URL(e.getDescription()).toURI());
} catch (IOException | URISyntaxException ex) {
Clipboard cp = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard cp = Toolkit.getDefaultToolkit().getSystemClipboard();
cp.setContents(new StringSelection(e.getDescription()), null); cp.setContents(new StringSelection(e.getDescription()), null);
// With Java 1.6, we could open the 'default' browser JOptionPane.showMessageDialog(this, "The link was copied to the clipboard!");
// Desktop dt = Desktop.getDesktop(); }
// try {
// dt.browse(url.toURI());
// } catch (IOException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// } catch (URISyntaxException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
} }
}); });
......
...@@ -37,25 +37,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -37,25 +37,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sinalgo.gui.dialogs; package sinalgo.gui.dialogs;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.web.WebHistory;
import javafx.scene.web.WebView;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import sinalgo.configuration.AppConfig; import sinalgo.configuration.AppConfig;
import sinalgo.gui.GuiHelper; import sinalgo.configuration.Configuration;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.*;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.net.URL;
@Getter(AccessLevel.PRIVATE) @Getter(AccessLevel.PRIVATE)
@Setter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE)
...@@ -63,188 +59,50 @@ public class HelpDialog extends JFrame implements ActionListener, WindowListener ...@@ -63,188 +59,50 @@ public class HelpDialog extends JFrame implements ActionListener, WindowListener
private static final long serialVersionUID = 5648555963120786571L; private static final long serialVersionUID = 5648555963120786571L;
private JEditorPane html; private JFXPanel fxPanel;
private JButton menuButton = new JButton("Menu");
private URL currentURL;
private URL defaultURL;
private HelpDialog(JFrame parent) { // is private, use showHelp() to create it in a new thread private HelpDialog(JFrame parent) { // is private, use showHelp() to create it in a new thread
this.setTitle("Sinalgo Help (source: https://github.com/Sinalgo/sinalgo)"); super("Sinalgo Help (source: " + Configuration.SINALGO_WEB_PAGE + ")");
GuiHelper.setWindowIcon(this); fxPanel = new JFXPanel();
this.addWindowListener(this); Platform.runLater(() -> {
this.restoreWindowState(); WebView wv = new WebView();
wv.getEngine().load(Configuration.SINALGO_WEB_PAGE);
this.setLayout(new BorderLayout()); wv.setContextMenuEnabled(false);
this.setResizable(true); getFxPanel().setScene(new Scene(wv, 500, 500));
HelpDialog.this.setMinimumSize(new Dimension(500, 500));
JPanel topPanel = new JPanel(); HelpDialog.this.setIconImage(parent.getIconImage());
this.add(topPanel, BorderLayout.NORTH); HelpDialog.this.add(new JScrollPane(fxPanel));
topPanel.setLayout(new BorderLayout()); HelpDialog.this.addWindowListener(this);
topPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); HelpDialog.this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
topPanel.add(this.getMenuButton(), BorderLayout.WEST); HelpDialog.this.restoreWindowState();
this.getMenuButton().addActionListener(this); wv.setOnKeyPressed(e -> {
if (!e.isConsumed()) {
this.setHtml(new JEditorPane()); if (e.getCode() == KeyCode.LEFT && e.isAltDown()) {
JScrollPane scroller = new JScrollPane(); WebHistory h = wv.getEngine().getHistory();
JViewport vp = scroller.getViewport(); if (h.getCurrentIndex() > 0) {
vp.add(this.getHtml()); h.go(-1);
this.add(scroller, BorderLayout.CENTER); }
} else if (e.getCode() == KeyCode.RIGHT && e.isAltDown()) {
try { WebHistory h = wv.getEngine().getHistory();
this.setDefaultURL(new URL("https://sinalgo.github.io")); if (h.getCurrentIndex() < h.getEntries().size() - 1) {
this.setCurrentURL(this.getDefaultURL()); h.go(1);
this.getHtml().setPage(this.getCurrentURL()); }
this.getHtml().setEditable(false);
this.getHtml().addHyperlinkListener(this.getLinkListener());
} catch (IOException e1) {
this.getHtml().setText("Cannot display the page.\n" + e1.getMessage());
} }
}
});
HelpDialog.this.setVisible(true);
HelpDialog.this.pack();
});
// Detect ESCAPE button // Detect ESCAPE button
KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addKeyEventPostProcessor(e -> { focusManager.addKeyEventPostProcessor(e -> {
if (!e.isConsumed() && e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ESCAPE) { if (!e.isConsumed() && e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
HelpDialog.this.setVisible(false); HelpDialog.this.dispose();
} }
return false; return false;
}); });
this.pack();
this.setVisible(true);
}
private HyperlinkListener getLinkListener() {
return e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if (e instanceof HTMLFrameHyperlinkEvent) {
((HTMLDocument) this.getHtml().getDocument())
.processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) e);
} else {
try {
this.setCurrentURL(e.getURL());
String s = this.getCurrentURL().toString();
int offset = s.indexOf(".html");
if (offset > 0) { // .html is in the string
s = s.substring(0, offset + 5);
s += "?help";
if (this.getCurrentURL().getRef() != null) {
s += "#" + this.getCurrentURL().getRef();
}
this.setCurrentURL(new URL(s));
HelpDialog.this.setEnabled(true);
if (this.getMenuDlg() != null) {
this.getMenuDlg().setVisible(false);
this.setMenuDlg(null);
}
}
this.getHtml().setPage(this.getCurrentURL());
} catch (IOException e1) {
this.getHtml().setText("Cannot display the page.\n" + e1.getMessage());
}
}
}
};
}
private MenuDialog menuDlg; // The menu dialog if its currently shown, otherwise null
private void showMenu() {
Point p = this.getMenuButton().getLocationOnScreen();
this.setMenuDlg(new MenuDialog(this, p));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(this.getMenuButton())) {
this.showMenu();
}
}
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
class MenuDialog extends JWindow implements ActionListener {
private static final long serialVersionUID = -950395591867596455L;
private JFrame parentFrame;
private JButton closeButton = new JButton("Close");
private JButton resetButton = new JButton("Reset");
private JEditorPane ePane;
private String defaultMenuURL = "https://github.com/Sinalgo/sinalgo/";
MenuDialog(JFrame owner, Point pos) {
super(owner);
this.setParentFrame(owner);
this.setLayout(new BorderLayout());
this.setEPane(new JEditorPane());
// ePane.getEditorKit().
this.getEPane().setPreferredSize(new Dimension(250, 400));
this.getEPane().setEditable(false);
JScrollPane scroller = new JScrollPane();
JViewport vp = scroller.getViewport();
vp.add(this.getEPane());
this.add(scroller, BorderLayout.CENTER);
try {
// create the URL for the menu (ensure that the url still points to a Sinalgo
// page
String s = (HelpDialog.this.getCurrentURL() == null ? this.getDefaultMenuURL() : HelpDialog.this.getCurrentURL().toString());
URL myURL;
int offset = s.indexOf(".html");
if (offset > 0) { // .html is in the string
if (!s.contains("github.com/andrebrait/sinalgo/")) { // went to a different site
myURL = new URL(this.getDefaultMenuURL());
} else { // add the ?menu option
s = s.substring(0, offset + 5);
s += "?menu";
myURL = new URL(s);
}
} else {
myURL = new URL(this.getDefaultMenuURL());
}
this.getEPane().setPage(myURL); // load the page
this.getEPane().addHyperlinkListener(HelpDialog.this.getLinkListener());
} catch (IOException e1) {
this.getEPane().setText("Cannot display the page.\n" + e1.getMessage());
}
JPanel menuPanel = new JPanel();
menuPanel.setLayout(new BoxLayout(menuPanel, BoxLayout.X_AXIS));
this.add(menuPanel, BorderLayout.NORTH);
this.getCloseButton().addActionListener(this);
menuPanel.add(this.getCloseButton());
this.getResetButton().addActionListener(this);
menuPanel.add(this.getResetButton());
this.setLocation(pos);
this.pack();
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(this.getCloseButton())) {
this.setVisible(false);
this.getParentFrame().setEnabled(true);
HelpDialog.this.setMenuDlg(null);
}
if (e.getSource().equals(this.getResetButton())) {
this.setVisible(false);
this.getParentFrame().setEnabled(true);
HelpDialog.this.setMenuDlg(null);
try {
HelpDialog.this.setCurrentURL(HelpDialog.this.getDefaultURL());
HelpDialog.this.getHtml().setPage(HelpDialog.this.getCurrentURL());
} catch (IOException e1) {
HelpDialog.this.getHtml().setText("Cannot display the page.\n" + e1.getMessage());
}
}
}
} }
private void saveWindowState() { private void saveWindowState() {
...@@ -257,14 +115,20 @@ public class HelpDialog extends JFrame implements ActionListener, WindowListener ...@@ -257,14 +115,20 @@ public class HelpDialog extends JFrame implements ActionListener, WindowListener
} }
private void restoreWindowState() { private void restoreWindowState() {
this.setPreferredSize(new Dimension(AppConfig.getAppConfig().getHelpWindowWidth(),
this.setPreferredSize(new Dimension(AppConfig.getAppConfig().getHelpWindowWidth(), AppConfig.getAppConfig().getHelpWindowHeight())); AppConfig.getAppConfig().getHelpWindowHeight()));
this.setLocation(new Point(AppConfig.getAppConfig().getHelpWindowPosX(), AppConfig.getAppConfig().getHelpWindowPosY())); this.setLocation(new Point(AppConfig.getAppConfig().getHelpWindowPosX(),
AppConfig.getAppConfig().getHelpWindowPosY()));
if (AppConfig.getAppConfig().isHelpWindowIsMaximized()) { if (AppConfig.getAppConfig().isHelpWindowIsMaximized()) {
this.setExtendedState(Frame.MAXIMIZED_BOTH); this.setExtendedState(Frame.MAXIMIZED_BOTH);
} }
} }
@Override
public void actionPerformed(ActionEvent e) {
}
@Override @Override
public void windowClosed(WindowEvent e) { public void windowClosed(WindowEvent e) {
this.saveWindowState(); this.saveWindowState();
...@@ -297,25 +161,7 @@ public class HelpDialog extends JFrame implements ActionListener, WindowListener ...@@ -297,25 +161,7 @@ public class HelpDialog extends JFrame implements ActionListener, WindowListener
} }
public static void showHelp(JFrame parent) { public static void showHelp(JFrame parent) {
Runner r = new Runner(parent); new HelpDialog(parent);
r.start();
}
@Getter(AccessLevel.PRIVATE)
@Setter(AccessLevel.PRIVATE)
static class Runner extends Thread {
private JFrame p;
Runner(JFrame parent) {
this.setP(parent);
}
@Override
public void run() {
new HelpDialog(this.getP());
}
} }
} }
...@@ -53,7 +53,7 @@ public class VersionTester extends Thread { ...@@ -53,7 +53,7 @@ public class VersionTester extends Thread {
public void run() { public void run() {
setRunning(true); setRunning(true);
try { try {
URL url = new URL("https://github.com/Sinalgo/sinalgo/raw/master/VERSION"); URL url = new URL(Configuration.SINALGO_REPO + "/raw/master/VERSION");
URLConnection con = url.openConnection(); URLConnection con = url.openConnection();
con.setDoOutput(true); con.setDoOutput(true);
con.setDoInput(true); con.setDoInput(true);
...@@ -77,7 +77,7 @@ public class VersionTester extends Thread { ...@@ -77,7 +77,7 @@ public class VersionTester extends Thread {
+ "| A more recent version of Sinalgo is available (" + line + ")\n" + "| A more recent version of Sinalgo is available (" + line + ")\n"
+ "+---------------------------------------------------------------------\n" + "+---------------------------------------------------------------------\n"
+ "| To download the latest version, please visit\n" + "| To download the latest version, please visit\n"
+ "| https://github.com/Sinalgo/sinalgo/\n" + "| " + Configuration.SINALGO_REPO + "/\n"
+ "+---------------------------------------------------------------------\n" + "+---------------------------------------------------------------------\n"
+ "| You may turn off these version checks through the 'Settings' dialog.\n" + "| You may turn off these version checks through the 'Settings' dialog.\n"
+ "| Note: Sinalgo automatically tests for updates at most once\n" + "| Note: Sinalgo automatically tests for updates at most once\n"
...@@ -92,7 +92,7 @@ public class VersionTester extends Thread { ...@@ -92,7 +92,7 @@ public class VersionTester extends Thread {
+ Configuration.VERSION_STRING + "\n" + Configuration.VERSION_STRING + "\n"
+ ">---------------------------------------------------------------------\n" + ">---------------------------------------------------------------------\n"
+ "> To check for more recent versions, please visit\n" + "> To check for more recent versions, please visit\n"
+ "> https://github.com/Sinalgo/sinalgo/\n" + "> " + Configuration.SINALGO_REPO + "/\n"
+ ">---------------------------------------------------------------------\n" + ">---------------------------------------------------------------------\n"
+ "> You may turn off these version checks through the 'Settings' dialog.\n" + "> You may turn off these version checks through the 'Settings' dialog.\n"
+ "| Note: Sinalgo automatically tests for updates at most once\n" + "| every 24 hours.\n" + "| Note: Sinalgo automatically tests for updates at most once\n" + "| every 24 hours.\n"
......
...@@ -36,6 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -36,6 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package sinalgo.runtime; package sinalgo.runtime;
import javafx.application.Platform;
import lombok.Getter; import lombok.Getter;
import sinalgo.configuration.AppConfig; import sinalgo.configuration.AppConfig;
import sinalgo.configuration.Configuration; import sinalgo.configuration.Configuration;
...@@ -50,6 +51,14 @@ import sinalgo.gui.dialogs.ProgressBarUser; ...@@ -50,6 +51,14 @@ import sinalgo.gui.dialogs.ProgressBarUser;
*/ */
public class GUIRuntime extends SinalgoRuntime implements ProgressBarUser { public class GUIRuntime extends SinalgoRuntime implements ProgressBarUser {
/**
* Default GUI Constructor
*/
GUIRuntime() {
super();
Platform.setImplicitExit(false);
}
/** /**
* The gui instance. * The gui instance.
* *
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment