package com.drawbridge;
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import com.drawbridge.dm.DMImageFactory.DMImage;
import com.drawbridge.dm.DMPanel;
import com.drawbridge.text.DBDocument.DBDocumentListener;
import com.drawbridge.text.TextPanel;
import com.drawbridge.utils.AnalyticUtils;
import com.drawbridge.utils.GraphicUtils;
import com.drawbridge.utils.JSUtils;
import com.drawbridge.utils.SegmentPanel;
import com.drawbridge.utils.TitlePanel;
import com.drawbridge.utils.Utils;
import com.drawbridge.vl.VLPanel;
public class WebViewPanel extends SegmentPanel implements MouseListener, DBDocumentListener
{
private static final long serialVersionUID = 157476875799766795L;
public static WebViewPanel instance = null;
private MyBrowser myBrowser = null;
private Scene scene = null;
private boolean mPublishEnabled = false;
private boolean mTestEnabled = true;
private boolean mShowInBrowserEnabled = true;
private final String mTestDir;
public static WebViewPanel getInstance()
{
if (instance != null)
{
return instance;
} else
{
instance = new WebViewPanel();
return instance;
}
}
public WebViewPanel() {
mTestDir = "/DrawBridge" + AnalyticUtils.username;
final JFXPanel fxPanel = new JFXPanel();
this.setLayout(new BorderLayout());
TitlePanel mTitlePanel = new TitlePanel("Web View");
if(mTestEnabled){
JButton test = new JButton("Test");
test.setIcon(GraphicUtils.loadIconFromResource("/Assets/test.png"));
test.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent me)
{
Platform.runLater(new Runnable()
{
@Override
public void run()
{
myBrowser.requestCodeInjection();
AnalyticUtils.recordTestClick();
}
});
}
});
mTitlePanel.addButton(test);
}
if(mShowInBrowserEnabled){
JButton seeInBrowser = new JButton("Test In Browser");
seeInBrowser.setIcon(GraphicUtils.loadIconFromResource("/Assets/browser.png"));
seeInBrowser.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent me)
{
if (Desktop.isDesktopSupported())
{
try
{
File defaultHTML = new File(Utils.getTemporaryFolder() + mTestDir + "/default.html");
if (defaultHTML.exists())
{
Desktop.getDesktop().browse(defaultHTML.toURI());
AnalyticUtils.recordShowInBrowserClick();
}
else
{
JOptionPane.showMessageDialog(WebViewPanel.this, "Could not load webpage because file cannot be found in file system.");
}
} catch (IOException e)
{
JOptionPane.showMessageDialog(WebViewPanel.this, "Could not load webpage because file cannot be found.");
}
}
else {
JOptionPane.showMessageDialog(WebViewPanel.this, "Could not load webpage because system won't tell java what browser to use.");
}
}
});
mTitlePanel.addButton(seeInBrowser);
}
if(mPublishEnabled){
JButton publish = new JButton("Publish");
publish.setIcon(GraphicUtils.loadIconFromResource("/Assets/publish.png"));
publish.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent me)
{
// Popup publish window
}
});
mTitlePanel.addButton(publish);
}
this.add(mTitlePanel, BorderLayout.NORTH);
this.add(fxPanel, BorderLayout.CENTER);
this.setVisible(true);
Platform.runLater(new Runnable()
{
@Override
public void run()
{
initFX(fxPanel);
}
});
}
public void initFX(JFXPanel fxPanel)
{
myBrowser = new MyBrowser();
scene = new Scene(myBrowser, fxPanel.getWidth(), fxPanel.getHeight());
fxPanel.setScene(scene);
}
@Override
public void mouseClicked(MouseEvent me)
{
this.requestFocus();
}
@Override
public void mouseEntered(MouseEvent me)
{
}
@Override
public void mouseExited(MouseEvent arg0)
{
}
@Override
public void mousePressed(MouseEvent arg0)
{
}
@Override
public void mouseReleased(MouseEvent arg0)
{
}
class MyBrowser extends Region
{
HBox toolbar;
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
URL urlDefaultHTML = null;
Long lastTimeInjected = null;
public MyBrowser() {
// Load placeholder html here
webView.getEngine().setOnAlert(new EventHandler<WebEvent<String>>()
{
@Override
public void handle(WebEvent<String> event)
{
Utils.out.println(event.getData());
}
});
toolbar = new HBox();
toolbar.setPadding(new Insets(10, 10, 10, 10));
toolbar.setSpacing(10);
toolbar.setStyle("-fx-background-color: #336699");
getChildren().add(webView);
}
@Override
protected void layoutChildren()
{
double w = getWidth();
double h = getHeight();
double toolbarHeight = toolbar.prefHeight(w);
layoutInArea(webView, 0, 0, w, h - toolbarHeight, 0, HPos.CENTER, VPos.CENTER);
layoutInArea(toolbar, 0, h - toolbarHeight, w, toolbarHeight, 0, HPos.CENTER, VPos.CENTER);
}
// Method requests code injection. It's only allowed to happen every so often (e.g. not every key stroke).
public void requestCodeInjection()
{
long timeDelay = 100;
if (lastTimeInjected == null) {
lastTimeInjected = System.currentTimeMillis() - timeDelay - 1;
}
if (lastTimeInjected <= (System.currentTimeMillis() - timeDelay)) {
injectCode();
lastTimeInjected = System.currentTimeMillis();
}
else {
// TODO add some sort of concurrent checker for this
}
}
public void injectCode()
{
Utils.out.println(this.getClass(), "Injecting code!");
// User Code Loading
StringBuilder userCode = new StringBuilder();
if(TextPanel.hasInstance())
userCode.append("function userCode(){\n" + TextPanel.getInstance().getDocument().getText() + "\n}\n\n");
else if(VLPanel.hasInstance())
userCode.append("function userCode(){\n" + VLPanel.getInstance().mCanvas.getModel().generateCodeFromBlocks(VLPanel.getInstance().mCanvas.mViewGrid) + "\n}\n\n");
else
throw new RuntimeException("Can't find any code representation to execute!");
Utils.out.println(this.getClass(), "UserCode:" + userCode);
boolean canSaveUserCode = Utils.saveTextToFile(userCode.toString(), new File(Utils.getTemporaryFolder() + mTestDir + "/user_code.js"));
boolean canSaveScaffolding = false;
// Scaffolding loading
if (canSaveUserCode) {
String loadCode = "";
if (DMPanel.hasInstance()) {
List<DMImage> list = DMPanel.getInstance().mModel.getModelObjects();
loadCode = getLoadImagesScript(list);
}
String part1 = Utils.loadTextFromPackagedFile("/SimpleTweeningJS/scaffolding1.js");
String part2 = Utils.loadTextFromPackagedFile("/SimpleTweeningJS/scaffolding2.js");
String joinedScaffoldingCode = part1 + loadCode + part2;
canSaveScaffolding = Utils.saveTextToFile(joinedScaffoldingCode, new File(Utils.getTemporaryFolder() + mTestDir + "/scaffolding.js"));
}
Utils.out.println(this.getClass(), "loading default html!");
// Default HTML loading
if (canSaveUserCode && canSaveScaffolding) {
String defaultHTML = Utils.loadTextFromPackagedFile("/SimpleTweeningJS/default.html");
File newHTMLLocation = new File(Utils.getTemporaryFolder() + mTestDir + "/default.html");
Utils.saveTextToFile(defaultHTML, newHTMLLocation);
try
{
webEngine.load(newHTMLLocation.toURI().toURL().toExternalForm());
webEngine.reload();
} catch (MalformedURLException e)
{
e.printStackTrace();
}
}
Utils.out.println(this.getClass(), "after default html!");
}
}
@Override
public void onDocumentUpdate(final String string)
{
Platform.runLater(new Runnable()
{
@Override
public void run()
{
Utils.out.println("Updating canvas..");
myBrowser.webEngine.executeScript(JSUtils.JS_CANVAS_RESET);
myBrowser.webEngine.executeScript(string);
}
});
}
// Loads image from their external URLs rather than internal memory.
private String getLoadImagesScript(List<DMImage> dmImages)
{
String args = "";
int addedCount = 0;
for (int i = 0; i < dmImages.size(); i++) {
URL url = null;
if (dmImages.get(i).getURL() == null) {
if (Utils.saveImageToFile(dmImages.get(i), mTestDir) == true) {
if (dmImages.get(i).getURL() != null) {
url = dmImages.get(i).getURL();
}
}
else {
JOptionPane.showMessageDialog(this, "Failed to save image to file");
Utils.out.println("Failed to save to file:" + dmImages.get(i).getName());
}
}
else {
url = dmImages.get(i).getURL();
}
if (url != null) {
if (addedCount > 0)
args += ", ";
args += "\"" + url.toExternalForm() + "\"";
addedCount++;
}
}
return "preloadImages_helper(" + args + ");";
}
}