/* * Copyright (c) 2015, Netsyms Technologies * All rights reserved. * * * CODE LICENSE ========== * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * 4. You adhere to the Media License detailed below. If you do not, this license * is automatically revoked and you must purge all copies of the software you * possess, in source or binary form. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * MEDIA LICENSE ========== * All images and other graphical files ("media") included with this * software are copyright (c) 2015 Netsyms Technologies. You may not distribute * the graphics or any program, source code repository, or other digital storage * media containing them without permission from Netsyms Technologies. * This ban on distribution only applies to publicly available systems. * A password-protected network file share, USB drive, or other storage scheme that * cannot be easily accessed by the public is generally allowed. If in doubt, * contact Netsyms Technologies. If Netsyms Technologies allows or denies * you permission, that decision is considered final and binding. * * You may only use the media for personal, * non-commercial, non-educational use unless: * 1, You have paid for the software and media via the SyMAT website, * or 2, you are using it as part of the 15-day trial period. * Other uses are prohibited without permission. * If any part of this license is deemed unenforcable, the remainder * of the license remains in full effect. */ package net.apocalypselabs.symat; import java.awt.BorderLayout; import java.awt.Component; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; import javafx.concurrent.Worker; import javafx.concurrent.Worker.State; import javafx.embed.swing.JFXPanel; import javafx.event.EventHandler; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.web.PromptData; import javafx.scene.web.WebEngine; import javafx.scene.web.WebEvent; import javafx.scene.web.WebView; import javafx.util.Callback; import javax.swing.JInternalFrame; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; /** * * @author Skylar */ public class PadEditor extends javax.swing.JInternalFrame implements RunScriptListener { private WebView browser; private WebEngine webEngine; private JFXPanel jfxPanel; private Group root; private Scene scene; private String padID = ""; private String padURL = ""; private RunScriptThread rt; private JInternalFrame thisFrame; /** * Creates new form PadEditor * * @param padurl Pad URL to load * @param padid Pad ID to load */ public PadEditor(String padurl, String padid) { padID = padid; padURL = padurl; initComponents(); //setFrameIcon(new ImageIcon(getClass().getResource("/net/apocalypselabs/symat/icons/editor.png"))); thisFrame = this; jfxPanel = new JFXPanel(); Platform.runLater(new Runnable() { @Override public void run() { browser = new WebView(); browser.setPrefSize(getWidth(), getHeight()); root = new Group(); scene = new Scene(root); ObservableList children = root.getChildren(); children.add(browser); jfxPanel.setScene(scene); webEngine = browser.getEngine(); webEngine.getLoadWorker().stateProperty().addListener( new ChangeListener() { @Override public void changed(ObservableValue ov, State oldState, State newState) { if (newState == Worker.State.RUNNING) { statusLbl.setText("Loading..."); } else if (newState == Worker.State.SCHEDULED || newState == Worker.State.READY) { } else { statusLbl.setText(""); } } }); webEngine.setOnAlert( new EventHandler>() { @Override public void handle(WebEvent t) { JOptionPane.showMessageDialog(thisFrame, t.getData(), "Message", JOptionPane.INFORMATION_MESSAGE); } }); webEngine.setPromptHandler( new Callback() { @Override public String call(PromptData p) { return JOptionPane.showInputDialog(thisFrame, p.getMessage(), "Question", JOptionPane.QUESTION_MESSAGE); } }); webEngine.setConfirmHandler( new Callback() { @Override public Boolean call(String p) { return (JOptionPane.showConfirmDialog( thisFrame, p, "Question", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION ? true : false); } }); webEngine.setUserAgent("Mozilla/5.0 SyMAT/" + Main.VERSION_NAME); webEngine.loadContent("Loading..."); webEngine.load(padurl); } }); browserBox.add(jfxPanel, BorderLayout.CENTER); outputBox.setBackground(net.apocalypselabs.symat.Theme.boxColor()); outputBox.setForeground(net.apocalypselabs.symat.Theme.textColor()); } /** * * @param url */ public void loadURL(final String url) { Platform.runLater(new Runnable() { @Override public void run() { webEngine.load(url); resizeAll(); } }); } /** * */ public void open() { Main.loadFrame(this, true); } /** * * @param content */ public void loadString(final String content) { Platform.runLater(new Runnable() { @Override public void run() { webEngine.loadContent(content); resizeAll(); } }); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { jSplitPane1 = new javax.swing.JSplitPane(); browserBox = new javax.swing.JPanel(); jPanel1 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); outputBox = new javax.swing.JTextArea(); clearBtn = new javax.swing.JButton(); jLabel1 = new javax.swing.JLabel(); statusBar = new javax.swing.JToolBar(); statusLbl = new javax.swing.JLabel(); jMenuBar1 = new javax.swing.JMenuBar(); runMenu = new javax.swing.JMenu(); runCodeBtn = new javax.swing.JMenuItem(); killButton = new javax.swing.JMenuItem(); codeLangMenu = new javax.swing.JMenu(); javascriptOption = new javax.swing.JRadioButtonMenuItem(); pythonOption = new javax.swing.JRadioButtonMenuItem(); javaOption = new javax.swing.JRadioButtonMenuItem(); setClosable(true); setIconifiable(true); setMaximizable(true); setResizable(true); setTitle("Pad Editor"); setFrameIcon(new javax.swing.ImageIcon(getClass().getResource("/net/apocalypselabs/symat/icons/editor.png"))); // NOI18N setMinimumSize(new java.awt.Dimension(300, 300)); setPreferredSize(new java.awt.Dimension(550, 391)); addInternalFrameListener(new javax.swing.event.InternalFrameListener() { public void internalFrameActivated(javax.swing.event.InternalFrameEvent evt) { } public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt) { } public void internalFrameClosing(javax.swing.event.InternalFrameEvent evt) { } public void internalFrameDeactivated(javax.swing.event.InternalFrameEvent evt) { } public void internalFrameDeiconified(javax.swing.event.InternalFrameEvent evt) { } public void internalFrameIconified(javax.swing.event.InternalFrameEvent evt) { } public void internalFrameOpened(javax.swing.event.InternalFrameEvent evt) { formInternalFrameOpened(evt); } }); addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { formComponentResized(evt); } public void componentShown(java.awt.event.ComponentEvent evt) { formComponentShown(evt); } }); jSplitPane1.setDividerLocation(200); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setResizeWeight(0.7); jSplitPane1.setPreferredSize(new java.awt.Dimension(550, 375)); browserBox.setMinimumSize(new java.awt.Dimension(100, 25)); browserBox.addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { browserBoxComponentResized(evt); } }); browserBox.setLayout(new java.awt.BorderLayout()); jSplitPane1.setLeftComponent(browserBox); outputBox.setColumns(20); outputBox.setRows(1); outputBox.setTabSize(4); jScrollPane1.setViewportView(outputBox); clearBtn.setText("Clear"); clearBtn.setToolTipText(""); clearBtn.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { clearBtnActionPerformed(evt); } }); jLabel1.setText("Output:"); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 437, Short.MAX_VALUE) .addComponent(clearBtn)) .addComponent(jScrollPane1) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel1) .addComponent(clearBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(0, 0, 0) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)) ); jSplitPane1.setBottomComponent(jPanel1); getContentPane().add(jSplitPane1, java.awt.BorderLayout.CENTER); statusBar.setFloatable(false); statusLbl.setText(" "); statusBar.add(statusLbl); getContentPane().add(statusBar, java.awt.BorderLayout.PAGE_END); runMenu.setText("Run"); runCodeBtn.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F5, 0)); runCodeBtn.setText("Run code"); runCodeBtn.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { runCodeBtnActionPerformed(evt); } }); runMenu.add(runCodeBtn); killButton.setText("Kill script"); killButton.setEnabled(false); killButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { killButtonActionPerformed(evt); } }); runMenu.add(killButton); codeLangMenu.setText("Language"); javascriptOption.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_J, java.awt.event.InputEvent.CTRL_MASK)); javascriptOption.setSelected(true); javascriptOption.setText("Javascript"); javascriptOption.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { javascriptOptionActionPerformed(evt); } }); codeLangMenu.add(javascriptOption); pythonOption.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK)); pythonOption.setText("Python"); pythonOption.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pythonOptionActionPerformed(evt); } }); codeLangMenu.add(pythonOption); javaOption.setText("Java"); javaOption.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { javaOptionActionPerformed(evt); } }); codeLangMenu.add(javaOption); runMenu.add(codeLangMenu); jMenuBar1.add(runMenu); setJMenuBar(jMenuBar1); pack(); }// //GEN-END:initComponents private void formInternalFrameOpened(javax.swing.event.InternalFrameEvent evt) {//GEN-FIRST:event_formInternalFrameOpened }//GEN-LAST:event_formInternalFrameOpened private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized resizeAll(); }//GEN-LAST:event_formComponentResized private void formComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentShown resizeAll(); }//GEN-LAST:event_formComponentShown private void runCodeBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_runCodeBtnActionPerformed if (javascriptOption.isSelected()) { rt = new RunScriptThread("javascript", Pads.getPad(padID), outputBox, null); } else if (pythonOption.isSelected()) { rt = new RunScriptThread("python", Pads.getPad(padID), outputBox, null); } else if (javaOption.isSelected()) { rt = new RunScriptThread("java", Pads.getPad(padID), outputBox, null); } else { return; } statusLbl.setText("Running..."); setRunning(true); rt.registerListener(this); rt.setDaemon(true); rt.start(); }//GEN-LAST:event_runCodeBtnActionPerformed @Override public void scriptFinished() { statusLbl.setText("Done"); setRunning(false); } private void killButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_killButtonActionPerformed if (rt.isAlive()) { rt.killme(); outputBox.append("" + "\n=============" + "\nScript killed" + "\n=============\n"); } statusLbl.setText("Killed"); setRunning(false); }//GEN-LAST:event_killButtonActionPerformed private void setRunning(boolean isRunning) { final boolean running = isRunning; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (running) { for (Component mu : jMenuBar1.getComponents()) { mu.setEnabled(false); } runMenu.setEnabled(true); runCodeBtn.setEnabled(false); codeLangMenu.setEnabled(false); killButton.setEnabled(true); } else { for (Component mu : jMenuBar1.getComponents()) { mu.setEnabled(true); } runCodeBtn.setEnabled(true); codeLangMenu.setEnabled(true); killButton.setEnabled(false); } } }); } private void javascriptOptionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_javascriptOptionActionPerformed pythonOption.setSelected(false); javaOption.setSelected(false); javascriptOption.setSelected(true); }//GEN-LAST:event_javascriptOptionActionPerformed private void pythonOptionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pythonOptionActionPerformed pythonOption.setSelected(true); javaOption.setSelected(false); javascriptOption.setSelected(false); }//GEN-LAST:event_pythonOptionActionPerformed private void javaOptionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_javaOptionActionPerformed pythonOption.setSelected(false); javaOption.setSelected(true); javascriptOption.setSelected(false); }//GEN-LAST:event_javaOptionActionPerformed private void browserBoxComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_browserBoxComponentResized resizeAll(); }//GEN-LAST:event_browserBoxComponentResized private void clearBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearBtnActionPerformed outputBox.setText(""); }//GEN-LAST:event_clearBtnActionPerformed private void resizeAll() { Platform.runLater(new Runnable() { @Override public void run() { jfxPanel.setSize(browserBox.getWidth(), browserBox.getHeight()); browser.setPrefSize(browserBox.getWidth(), browserBox.getHeight()); browser.resize(browserBox.getWidth(), browserBox.getHeight()); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel browserBox; private javax.swing.JButton clearBtn; private javax.swing.JMenu codeLangMenu; private javax.swing.JLabel jLabel1; private javax.swing.JMenuBar jMenuBar1; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JRadioButtonMenuItem javaOption; private javax.swing.JRadioButtonMenuItem javascriptOption; private javax.swing.JMenuItem killButton; private javax.swing.JTextArea outputBox; private javax.swing.JRadioButtonMenuItem pythonOption; private javax.swing.JMenuItem runCodeBtn; private javax.swing.JMenu runMenu; private javax.swing.JToolBar statusBar; private javax.swing.JLabel statusLbl; // End of variables declaration//GEN-END:variables }