Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.neuronrobotics.bowlerstudio; import haar.HaarFactory; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.ResourceBundle; import javax.swing.UIManager; import org.apache.commons.io.IOUtils; import org.kohsuke.github.GHGist; import org.kohsuke.github.GHMyself; import org.kohsuke.github.GHRepository; import org.kohsuke.github.GitHub; import org.kohsuke.github.PagedIterable; import org.opencv.core.Core; import org.reactfx.util.FxTimer; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.Event; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.scene.Group; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.SubScene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.CheckMenuItem; import javafx.scene.control.ChoiceDialog; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; //import javafx.scene.control.ScrollPane; import javafx.scene.control.TextArea; import javafx.scene.control.TextInputDialog; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; import com.neuronrobotics.bowlerstudio.creature.CreatureLab; import com.neuronrobotics.bowlerstudio.scripting.CommandLineWidget; import com.neuronrobotics.bowlerstudio.scripting.GithubLoginFX; import com.neuronrobotics.bowlerstudio.scripting.IGitHubLoginManager; import com.neuronrobotics.bowlerstudio.scripting.IGithubLoginListener; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; import com.neuronrobotics.bowlerstudio.scripting.ScriptingFileWidget; import com.neuronrobotics.bowlerstudio.scripting.ScriptingWidgetType; import com.neuronrobotics.bowlerstudio.threed.BowlerStudio3dEngine; import com.neuronrobotics.bowlerstudio.utils.BowlerStudioResourceFactory; import com.neuronrobotics.imageprovider.CHDKImageProvider; import com.neuronrobotics.imageprovider.NativeResource; import com.neuronrobotics.imageprovider.OpenCVJNILoader; import com.neuronrobotics.nrconsole.util.FileSelectionFactory; import com.neuronrobotics.nrconsole.util.GroovyFilter; import com.neuronrobotics.nrconsole.util.PromptForGist; import com.neuronrobotics.nrconsole.util.XmlFilter; import com.neuronrobotics.pidsim.LinearPhysicsEngine; import com.neuronrobotics.replicator.driver.NRPrinter; import com.neuronrobotics.replicator.driver.Slic3r; import com.neuronrobotics.sdk.pid.VirtualGenericPIDDevice; import com.neuronrobotics.sdk.util.ThreadUtil; import com.neuronrobotics.sdk.addons.kinematics.DHParameterKinematics; import com.neuronrobotics.sdk.addons.kinematics.MobileBase; import com.neuronrobotics.sdk.addons.kinematics.gui.*; import com.sun.crypto.provider.DHParameterGenerator; import com.sun.speech.freetts.VoiceManager; import javafx.scene.control.Menu; /** * FXML Controller class * * @author Michael Hoffer <info@michaelhoffer.de> */ public class MainController implements Initializable { private static int sizeOfTextBuffer = 40000; private static ByteArrayOutputStream out = null; static boolean opencvOk = true; private static TextArea logViewRef = null; private static String newString = null; @FXML private MenuBar menuBar; @FXML private MenuItem logoutGithub; @FXML private Menu myGists; @FXML private Pane logView; @FXML private AnchorPane editorContainer; @FXML private Pane viewContainer; @FXML private Pane jfx3dControls; private SubScene subScene; private BowlerStudio3dEngine jfx3dmanager; private File openFile; private BowlerStudioController application; private Stage primaryStage; @FXML private CheckMenuItem AddDefaultRightArm; @FXML private CheckMenuItem AddVRCamera; private CommandLineWidget cmdLine; @FXML Menu CreatureLabMenue; private EventHandler<? super KeyEvent> normalKeyPessHandle; @FXML MenuItem createNewGist; @FXML MenuItem addFileToGist; private boolean loginWindowOpen = false; private GithubLoginFX controller = null; public static void updateLog() { if (logViewRef != null) { String current; String finalStr; if (getOut().size() == 0) { newString = null; } else { newString = getOut().toString(); getOut().reset(); } if (newString != null) { current = logViewRef.getText() + newString; try { finalStr = new String(current.substring(current.getBytes().length - sizeOfTextBuffer)); } catch (StringIndexOutOfBoundsException ex) { finalStr = current; } int strlen = finalStr.length() - 1; logViewRef.setText(finalStr); Platform.runLater(() -> logViewRef.positionCaret(strlen)); } } FxTimer.runLater(Duration.ofMillis(100), () -> { updateLog(); }); } // private final CodeArea codeArea = new CodeArea(); /** * Initializes the controller class. * * @param url * @param rb */ @Override public void initialize(URL url, ResourceBundle rb) { ScriptingEngine.setLoginManager(new IGitHubLoginManager() { @Override public String[] prompt(String username) { if (!loginWindowOpen && controller != null) controller.reset(); loginWindowOpen = true; System.err.println("Calling login from BowlerStudio"); // new RuntimeException().printStackTrace(); FXMLLoader fxmlLoader = BowlerStudioResourceFactory.getGithubLogin(); Parent root = fxmlLoader.getRoot(); if (controller == null) { controller = fxmlLoader.getController(); Platform.runLater(() -> { controller.reset(); controller.getUsername().setText(username); Stage stage = new Stage(); stage.setTitle("GitHub Login"); stage.initModality(Modality.APPLICATION_MODAL); controller.setStage(stage, root); stage.centerOnScreen(); stage.show(); }); } // setContent(root); while (!controller.isDone()) { ThreadUtil.wait(100); } String[] creds = controller.getCreds(); loginWindowOpen = false; return creds; } }); jfx3dmanager = new BowlerStudio3dEngine(); setApplication(new BowlerStudioController(jfx3dmanager, this)); Platform.runLater(() -> { editorContainer.getChildren().add(getApplication()); AnchorPane.setTopAnchor(getApplication(), 0.0); AnchorPane.setRightAnchor(getApplication(), 0.0); AnchorPane.setLeftAnchor(getApplication(), 0.0); AnchorPane.setBottomAnchor(getApplication(), 0.0); subScene = jfx3dmanager.getSubScene(); subScene.setFocusTraversable(false); subScene.setOnMouseEntered(mouseEvent -> { // System.err.println("3d window requesting focus"); Scene topScene = BowlerStudio.getScene(); normalKeyPessHandle = topScene.getOnKeyPressed(); jfx3dmanager.handleKeyboard(topScene); }); subScene.setOnMouseExited(mouseEvent -> { // System.err.println("3d window dropping focus"); Scene topScene = BowlerStudio.getScene(); topScene.setOnKeyPressed(normalKeyPessHandle); }); subScene.widthProperty().bind(viewContainer.widthProperty()); subScene.heightProperty().bind(viewContainer.heightProperty()); }); Platform.runLater(() -> { jfx3dControls.getChildren().add(jfx3dmanager.getControlsBox()); viewContainer.getChildren().add(subScene); }); System.out.println("Welcome to BowlerStudio!"); new Thread() { public void run() { setName("Load Haar Thread"); try { HaarFactory.getStream(null); } catch (Exception ex) { } } }.start(); // getAddDefaultRightArm().setOnAction(event -> { // // application.onAddDefaultRightArm(event); // }); // getAddVRCamera().setOnAction(event -> { // if(AddVRCamera.isSelected()) // application.onAddVRCamera(event); // }); FxTimer.runLater(Duration.ofMillis(100), () -> { if (ScriptingEngine.getLoginID() != null) { setToLoggedIn(ScriptingEngine.getLoginID()); } else { setToLoggedOut(); } }); ScriptingEngine.addIGithubLoginListener(new IGithubLoginListener() { @Override public void onLogout(String oldUsername) { setToLoggedOut(); } @Override public void onLogin(String newUsername) { setToLoggedIn(newUsername); } }); cmdLine = new CommandLineWidget(); Platform.runLater(() -> { // logView.resize(250, 300); // after connection manager set up, add scripting widget logViewRef = new TextArea(); logViewRef.prefWidthProperty().bind(logView.widthProperty().divide(2)); logViewRef.prefHeightProperty().bind(logView.heightProperty().subtract(40)); VBox box = new VBox(); box.getChildren().add(logViewRef); box.getChildren().add(cmdLine); VBox.setVgrow(logViewRef, Priority.ALWAYS); box.prefWidthProperty().bind(logView.widthProperty().subtract(10)); logView.getChildren().addAll(box); }); } private void setToLoggedIn(final String name) { // new Exception().printStackTrace(); FxTimer.runLater(Duration.ofMillis(100), () -> { logoutGithub.disableProperty().set(false); logoutGithub.setText("Log out " + name); new Thread() { public void run() { GitHub github = ScriptingEngine.getGithub(); while (github == null) { github = ScriptingEngine.getGithub(); ThreadUtil.wait(20); } try { GHMyself myself = github.getMyself(); PagedIterable<GHGist> gists = myself.listGists(); Platform.runLater(() -> { myGists.getItems().clear(); }); ThreadUtil.wait(20); for (GHGist gist : gists) { String desc = gist.getDescription(); if (desc == null || desc.length() == 0) { desc = gist.getFiles().keySet().toArray()[0].toString(); } Menu tmpGist = new Menu(desc); MenuItem loadWebGist = new MenuItem("Show Web Gist..."); loadWebGist.setOnAction(event -> { String webURL = gist.getHtmlUrl(); try { BowlerStudio.openUrlInNewTab(new URL(webURL)); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }); MenuItem addFile = new MenuItem("Add file to Gist..."); addFile.setOnAction(event -> { new Thread() { public void run() { } }.start(); }); Platform.runLater(() -> { tmpGist.getItems().addAll(addFile, loadWebGist); }); EventHandler<Event> loadFiles = new EventHandler<Event>() { @Override public void handle(Event ev) { // for(ScriptingEngine.) new Thread() { public void run() { System.out.println("Loading files"); ArrayList<String> listofFiles = ScriptingEngine .filesInGit(gist.getGitPushUrl(), "master", null); for (String s : listofFiles) { MenuItem tmp = new MenuItem(s); tmp.setOnAction(event -> { new Thread() { public void run() { try { File fileSelected = ScriptingEngine .fileFromGit(gist.getGitPushUrl(), s); BowlerStudio.createFileTab(fileSelected); } catch (Exception e) { // TODO // Auto-generated // catch block e.printStackTrace(); } } }.start(); }); Platform.runLater(() -> { tmpGist.getItems().add(tmp); tmpGist.setOnShowing(null); }); } Platform.runLater(() -> { tmpGist.hide(); Platform.runLater(() -> { tmpGist.show(); }); }); } }.start(); } }; tmpGist.setOnShowing(loadFiles); Platform.runLater(() -> { myGists.getItems().add(tmpGist); }); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); }); } private void setToLoggedOut() { Platform.runLater(() -> { myGists.getItems().clear(); logoutGithub.disableProperty().set(true); logoutGithub.setText("Anonymous"); }); } /** * Returns the location of the Jar archive or .class file the specified * class has been loaded from. <b>Note:</b> this only works if the class is * loaded from a jar archive or a .class file on the locale file system. * * @param cls * class to locate * @return the location of the Jar archive the specified class comes from */ public static File getClassLocation(Class<?> cls) { // VParamUtil.throwIfNull(cls); String className = cls.getName(); ClassLoader cl = cls.getClassLoader(); URL url = cl.getResource(className.replace(".", "/") + ".class"); String urlString = url.toString().replace("jar:", ""); if (!urlString.startsWith("file:")) { throw new IllegalArgumentException("The specified class\"" + cls.getName() + "\" has not been loaded from a location" + "on the local filesystem."); } urlString = urlString.replace("file:", ""); urlString = urlString.replace("%20", " "); int location = urlString.indexOf(".jar!"); if (location > 0) { urlString = urlString.substring(0, location) + ".jar"; } else { // System.err.println("No Jar File found: " + cls.getName()); } return new File(urlString); } @FXML private void onLoadFile(ActionEvent e) { new Thread() { public void run() { setName("Load File Thread"); openFile = FileSelectionFactory.GetFile(ScriptingEngine.getLastFile(), new ExtensionFilter("Groovy Scripts", "*.groovy", "*.java", "*.txt"), new ExtensionFilter("Clojure", "*.cloj", "*.clj", "*.txt", "*.clojure"), new ExtensionFilter("Python", "*.py", "*.python", "*.txt"), new ExtensionFilter("All", "*.*")); if (openFile == null) { return; } getApplication().createFileTab(openFile); } }.start(); } @FXML private void onConnect(ActionEvent e) { new Thread() { public void run() { setName("Load BowlerDevice Dialog Thread"); ConnectionManager.addConnection(); } }.start(); } @FXML private void onConnectVirtual(ActionEvent e) { ConnectionManager.addConnection(new VirtualGenericPIDDevice(10000), "virtual"); } @FXML private void onClose(ActionEvent e) { System.exit(0); } public TextArea getLogView() { return logViewRef; } public void disconnect() { getApplication().disconnect(); } public void openUrlInNewTab(URL url) { getApplication().openUrlInNewTab(url); } @FXML public void onConnectCHDKCamera(ActionEvent event) { Platform.runLater(() -> { try { ConnectionManager.addConnection(new CHDKImageProvider(), "cameraCHDK"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }); } @FXML public void onConnectCVCamera(ActionEvent event) { Platform.runLater(() -> ConnectionManager.onConnectCVCamera()); } @FXML public void onConnectJavaCVCamera() { Platform.runLater(() -> ConnectionManager.onConnectJavaCVCamera()); } @FXML public void onConnectFileSourceCamera() { Platform.runLater(() -> ConnectionManager.onConnectFileSourceCamera()); } @FXML public void onConnectURLSourceCamera() { Platform.runLater(() -> ConnectionManager.onConnectURLSourceCamera()); } @FXML public void onConnectHokuyoURG(ActionEvent event) { Platform.runLater(() -> ConnectionManager.onConnectHokuyoURG()); } @FXML public void onConnectGamePad(ActionEvent event) { Platform.runLater(() -> ConnectionManager.onConnectGamePad("gamepad")); } // public CheckMenuItem getAddVRCamera() { // return AddVRCamera; // } // // // public void setAddVRCamera(CheckMenuItem addVRCamera) { // AddVRCamera = addVRCamera; // } // // // public CheckMenuItem getAddDefaultRightArm() { // return AddDefaultRightArm; // } // // // public void setAddDefaultRightArm(CheckMenuItem addDefaultRightArm) { // AddDefaultRightArm = addDefaultRightArm; // } @FXML public void onLogin() { new Thread() { public void run() { setName("Login Gist Thread"); try { ScriptingEngine.login(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } @FXML public void onLogout() { ScriptingEngine.logout(); } @FXML public void onConnectPidSim() { LinearPhysicsEngine eng = new LinearPhysicsEngine(); eng.connect(); ConnectionManager.addConnection(eng, "engine"); } @FXML public void onPrint(ActionEvent event) { NRPrinter printer = (NRPrinter) ConnectionManager.pickConnectedDevice(NRPrinter.class); if (printer != null) { // run a print here } } @FXML public void onMobileBaseFromFile() { new Thread() { public void run() { setName("Load Mobile Base Thread"); openFile = FileSelectionFactory.GetFile(ScriptingEngine.getLastFile(), new ExtensionFilter("MobileBase XML", "*.xml", "*.XML")); if (openFile == null) { return; } Platform.runLater(() -> { try { MobileBase mb = new MobileBase(new FileInputStream(openFile)); ConnectionManager.addConnection(mb, mb.getScriptingName()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }); } }.start(); } @FXML public void onRobotArm(ActionEvent event) { loadMobilebaseFromGist("2b0cff20ccee085c9c36", "TrobotLinks.xml"); } @FXML public void onHexapod() { loadMobilebaseFromGist("bcb4760a449190206170", "CarlTheRobot.xml"); } @FXML public void onGrasshopper() { loadMobilebaseFromGist("a6cbefc11693162cf9d4", "GrassHopper.xml"); } @FXML public void onInputArm() { loadMobilebaseFromGist("98892e87253005adbe4a", "TrobotMaster.xml"); } @FXML public void onHumanoid() { loadMobilebaseFromGist("a991ca954460c1ba9860", "humanoid.xml"); } @FXML public void onAddElephant() { loadMobilebaseFromGist("aef13d65093951d13235", "Elephant.xml"); } public Menu getCreatureLabMenue() { return CreatureLabMenue; } public void setCreatureLabMenue(Menu creatureLabMenue) { CreatureLabMenue = creatureLabMenue; } public void loadMobilebaseFromGist(String id, String file) { new Thread() { public void run() { try { BowlerStudio.openUrlInNewTab(new URL("https://gist.github.com/" + id)); String xmlContent = ScriptingEngine.codeFromGistID(id, file)[0]; MobileBase mb = new MobileBase(IOUtils.toInputStream(xmlContent, "UTF-8")); mb.setSelfSource(new String[] { id, file }); ConnectionManager.addConnection(mb, mb.getScriptingName()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } @FXML public void onMobileBaseFromGist() { PromptForGist.prompt("Select a Creature From a Gist", "bcb4760a449190206170", (gitsId, file) -> { loadMobilebaseFromGist(gitsId, file); }); } public ScriptingFileWidget createFileTab(File file) { return getApplication().createFileTab(file); } public BowlerStudioController getApplication() { return application; } public void setApplication(BowlerStudioController application) { this.application = application; } @FXML public void onAddCNC() { loadMobilebaseFromGist("51a9e0bc4ee095b03979", "CNC.xml"); } public static ByteArrayOutputStream getOut() { if (out == null) out = new ByteArrayOutputStream(); return out; } @FXML public void onCreatenewGist() { } @FXML public void onAddFileToGist() { } }