Archived
Private
Public Access
1
0
This repository has been archived on 2026-02-04. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ProjectBackup/Java/BowlerStudio/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenu.java
2022-09-04 12:45:01 +02:00

1435 lines
44 KiB
Java

package com.neuronrobotics.bowlerstudio;
/**
* Sample Skeleton for "BowlerStudioMenuBar.fxml" Controller Class
* You can copy and paste this code into your favorite IDE
**/
import com.google.common.collect.Lists;
import com.neuronrobotics.bowlerstudio.assets.ConfigurationDatabase;
import com.neuronrobotics.bowlerstudio.creature.MobileBaseLoader;
import com.neuronrobotics.bowlerstudio.scripting.IGithubLoginListener;
import com.neuronrobotics.bowlerstudio.scripting.PasswordManager;
import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine;
import com.neuronrobotics.bowlerstudio.scripting.ScriptingFileWidget;
import com.neuronrobotics.bowlerstudio.tabs.LocalFileScriptTab;
import com.neuronrobotics.bowlerstudio.vitamins.Vitamins;
//import com.neuronrobotics.imageprovider.CHDKImageProvider;
import com.neuronrobotics.nrconsole.util.FileSelectionFactory;
import com.neuronrobotics.nrconsole.util.PromptForGit;
import com.neuronrobotics.pidsim.LinearPhysicsEngine;
import com.neuronrobotics.replicator.driver.NRPrinter;
import com.neuronrobotics.sdk.addons.kinematics.MobileBase;
import com.neuronrobotics.sdk.pid.VirtualGenericPIDDevice;
import com.neuronrobotics.sdk.util.ThreadUtil;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.kohsuke.github.*;
import org.reactfx.util.FxTimer;
import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class BowlerStudioMenu implements MenuRefreshEvent,INewVitaminCallback {
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // fx:id="CreaturesMenu"
private Menu CreaturesMenu; // Value injected by FXMLLoader
@FXML // fx:id="GitHubRoot"
private Menu GitHubRoot; // Value injected by FXMLLoader
@FXML // fx:id="workspacemenu"
private Menu workspacemenuHandle; // Value injected by FXMLLoader
@FXML // fx:id="MeneBarBowlerStudio"
private MenuBar MeneBarBowlerStudio; // Value injected by FXMLLoader
@FXML // fx:id="addMarlinGCODEDevice"
private MenuItem addMarlinGCODEDevice; // Value injected by FXMLLoader
@FXML // fx:id="addMarlinGCODEDevice"
private MenuItem loadFirmata; // Value injected by FXMLLoader
@FXML // fx:id="clearCache"
private MenuItem clearCache; // Value injected by FXMLLoader
@FXML // fx:id="createNewGist"
private MenuItem createNewGist; // Value injected by FXMLLoader
@FXML // fx:id="logoutGithub"
private MenuItem logoutGithub; // Value injected by FXMLLoader
@FXML // fx:id="myGists"
private Menu myGists; // Value injected by FXMLLoader
@FXML // fx:id="myOrganizations"
private Menu myOrganizations; // Value injected by FXMLLoader
@FXML // fx:id="myRepos"
private Menu myRepos; // Value injected by FXMLLoader
@FXML // fx:id="showDevicesPanel"
private MenuItem showDevicesPanel; // Value injected by FXMLLoader
@FXML // fx:id="showCreatureLab"
private MenuItem showCreatureLab; // Value injected by FXMLLoader
@FXML // fx:id="showTerminal"
private MenuItem showTerminal;
@FXML // fx:id="watchingRepos"
private Menu WindowMenu;
@FXML // fx:id="watchingRepos"
private Menu watchingRepos; // Value injected by FXMLLoader
@FXML
private Menu vitaminsMenu;
@FXML
private MenuItem addNewVitamin;
private BowlerStudioModularFrame bowlerStudioModularFrame;
private String name;
private static BowlerStudioMenu selfRef = null;
private File openFile;
private Map<String, GHRepository> myPublic;
// PagedIterable<GHGist> gists ;
private HashMap<String, String> messages = new HashMap<String, String>();
private static SimpleDateFormat format = new SimpleDateFormat("E 'the' dd 'in' MMM-yyyy 'at' HH:mm");
private static SimpleDateFormat formatSimple = new SimpleDateFormat("MM-dd");
private static IssueReportingExceptionHandler exp = new IssueReportingExceptionHandler();
private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
private static final Pattern WHITESPACE = Pattern.compile("[\\s]");
private HashMap<String,Menu> vitaminTypeMenus = new HashMap<String, Menu>();
public BowlerStudioMenu(BowlerStudioModularFrame tl) {
bowlerStudioModularFrame = tl;
}
@FXML
public void onMobileBaseFromGist(ActionEvent event) {
PromptForGit.prompt("Select a Creature From a Gist", "bcb4760a449190206170", (gitsId, file) -> {
loadMobilebaseFromGist(gitsId, file);
});
}
public ScriptingFileWidget createFileTab(File file) {
return bowlerStudioModularFrame.createFileTab(file);
}
public void loadMobilebaseFromGist(String id, String file) {
loadMobilebaseFromGit("https://gist.github.com/" + id + ".git", file);
}
public MenuBar getMeneBarBowlerStudio() {
return MeneBarBowlerStudio;
}
public void setMeneBarBowlerStudio(MenuBar meneBarBowlerStudio) {
MeneBarBowlerStudio = meneBarBowlerStudio;
}
public void loadMobilebaseFromGit(String id, String file) {
new Thread() {
public void run() {
try {
MobileBase mb;
if (file.toLowerCase().endsWith(".xml")) {
mb = MobileBaseLoader.fromGit(id, file);
} else {
mb = (MobileBase) ScriptingEngine.gitScriptRun(id, file, null);
}
if(mb!=null)
ConnectionManager.addConnection(mb, mb.getScriptingName());
else
System.out.println("\r\n\r\nNO MOBILE BASE found at "+id+"\t"+file);
} catch (Exception e) {
BowlerStudio.printStackTrace(e);
}
}
}.start();
}
public void openUrlInNewTab(URL url) {
bowlerStudioModularFrame.openUrlInNewTab(url);
}
public void setToLoggedOut() {
Platform.runLater(() -> {
myGists.getItems().clear();
logoutGithub.disableProperty().set(true);
logoutGithub.setText("Anonymous");
});
}
public void setToLoggedIn() {
setToLoggedIn(name);
}
private void setToLoggedIn(final String name) {
if (name == null)
return;
if (this.name != null && name.contentEquals(this.name))
return;
this.name = name;
// new Exception().printStackTrace();
Platform.runLater( () -> {
logoutGithub.disableProperty().set(false);
logoutGithub.setText("Log out " + name);
new Thread() {
public void run() {
ConfigurationDatabase.loginEvent(name);
BowlerStudioMenuWorkspace.loginEvent();
try {
ScriptingEngine.setAutoupdate(false);
} catch (IOException e2) {
e2.printStackTrace();
}
if (!PasswordManager.hasNetwork())
return;
GitHub gh = PasswordManager.getGithub();
while (gh == null && !PasswordManager.loggedIn()) {
gh = PasswordManager.getGithub();
ThreadUtil.wait(200);
}
GitHub github = gh;
LoadGistMenu(github);
loadOrganizations(github);
loadMyRepos(github);
loadWatchingRepos(github);
}
}.start();
});
}
private void loadWatchingRepos(GitHub github) {
new Thread(() -> {
Platform.runLater(() -> watchingRepos.getItems().clear());
ThreadUtil.wait(20);
GHMyself self;
try {
self = github.getMyself();
// Watched repos
List<GHRepository> watching = self.listSubscriptions().asList();
HashMap<String, Menu> ownerMenue = new HashMap<>();
for (GHRepository g : watching) {
if (ownerMenue.get(g.getOwnerName()) == null) {
ownerMenue.put(g.getOwnerName(), new Menu(g.getOwnerName()));
Platform.runLater(() -> {
try {
watchingRepos.getItems().add(ownerMenue.get(g.getOwnerName()));
} catch (Exception e) {
}
});
}
resetRepoMenue(ownerMenue.get(g.getOwnerName()), g);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), e1);
}
}).start();
}
private void loadMyRepos(GitHub github) {
new Thread(() -> {
Platform.runLater(() -> myRepos.getItems().clear());
ThreadUtil.wait(20);
// Repos I own
try {
GHMyself self = github.getMyself();
myPublic = self.getAllRepositories();
HashMap<String, Menu> myownerMenue = new HashMap<>();
for (Map.Entry<String, GHRepository> entry : myPublic.entrySet()) {
GHRepository g = entry.getValue();
if (myownerMenue.get(g.getOwnerName()) == null) {
myownerMenue.put(g.getOwnerName(), new Menu(g.getOwnerName()));
Platform.runLater(() -> {
myRepos.getItems().add(myownerMenue.get(g.getOwnerName()));
});
}
resetRepoMenue(myownerMenue.get(g.getOwnerName()), g);
}
} catch (Exception ex) {
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), ex);
// i have no public repso
}
}).start();
}
private void loadOrganizations(GitHub github) {
new Thread(() -> {
Platform.runLater(() -> myOrganizations.getItems().clear());
ThreadUtil.wait(20);
Map<String, GHOrganization> orgs;
try {
orgs = github.getMyOrganizations();
for (Map.Entry<String, GHOrganization> entry : orgs.entrySet()) {
// System.out.println("Org: "+org);
Menu OrgItem = new Menu(entry.getKey());
GHOrganization ghorg = entry.getValue();
Map<String, GHRepository> repos = ghorg.getRepositories();
for (Map.Entry<String, GHRepository> entry1 : repos.entrySet()) {
resetRepoMenue(OrgItem, entry1.getValue());
}
Platform.runLater(() -> {
myOrganizations.getItems().add(OrgItem);
});
}
} catch (Exception e) {
PasswordManager.checkInternet();
if(PasswordManager.hasNetwork())
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}).start();
}
private void LoadGistMenu(GitHub github) {
new Thread(() -> {
GHMyself myself;
try {
myself = github.getMyself();
System.out.println("Loading all my Gists");
Platform.runLater(() -> {
myGists.getItems().clear();
});
List<GHGist> gists = myself.listGists().asList();
for (GHGist gist : gists) {
String url = gist.getGitPushUrl();
String desc = gist.getDescription();
if (desc == null || desc.length() == 0
|| desc.contentEquals("Adding new file from BowlerStudio")) {
desc = gist.getFiles().keySet().toArray()[0].toString();
}
String descriptionString = desc;
selfRef.messages.put(url, "GIST: " + descriptionString);
// Menu tmpGist = new Menu(desc);
// setUpRepoMenue(ownerMenue.get(g.getOwnerName()), g);
setUpRepoMenue(myGists, url, true, true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}).start();
}
public static String gitURLtoMessage(String url) {
while (true) {
try {
if (selfRef.messages.get(url) != null)
break;
throw new RuntimeException();
} catch (Exception e) {
// System.err.println("Waiting for API to load message data..."+url);
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}
return selfRef.messages.get(url);
}
public static void setUpRepoMenue(Menu repoMenue, String url, boolean useAddToWorkspaceItem, boolean threaded) {
setUpRepoMenue(repoMenue, url, useAddToWorkspaceItem, threaded, gitURLtoMessage(url));
}
private static void resetRepoMenue(Menu repoMenue, GHRepository repo) {
String url = repo.getGitTransportUrl().replace("git://", "https://");
selfRef.messages.put(url, repo.getFullName());
setUpRepoMenue(repoMenue, url, true, true);
}
public static void setUpRepoMenue(Menu repoMenue, String url, boolean useAddToWorkspaceItem, boolean threaded,
String message) {
Thread t = new Thread() {
public void run() {
// String menueMessage = repo.getFullName();
Menu orgRepo = new Menu(message);
Menu orgFiles = new Menu("Files");
Menu orgCommits = new Menu("Commits");
Menu orgBranches = new Menu("Branches");
MenuItem updateRepo = new MenuItem("Update Repo...");
MenuItem addToWs = new MenuItem("Add Repo to Workspace");
addToWs.setOnAction(event -> {
new Thread() {
public void run() {
BowlerStudioMenuWorkspace.add(url);
}
}.start();
});
// String url = repo.getGitTransportUrl().replace("git://", "https://");
MenuResettingEventHandler loadCommitsEvent = createLoadCommitsEvent(url, orgCommits);
MenuResettingEventHandler loadBranchesEvent = createLoadBranchesEvent(url, orgBranches);
MenuResettingEventHandler loadFilesEvent = createLoadFileEvent(url, orgFiles);
Runnable myEvent = new Runnable() {
@Override
public void run() {
try {
// System.err.println("\n\nCommit event Detected " + url + " on branch "
// + ScriptingEngine.getBranch(url));
//new RuntimeException().printStackTrace();
Platform.runLater(() ->resetMenueForLoadingFiles("Files:",orgFiles, loadFilesEvent));
Platform.runLater(() ->resetMenueForLoadingFiles("Commits:",orgCommits, loadCommitsEvent));
Platform.runLater(() ->resetMenueForLoadingFiles("Branches:",orgBranches, loadBranchesEvent));
} catch (Throwable e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
};
loadCommitsEvent.setMenuReset(myEvent);
loadBranchesEvent.setMenuReset(myEvent);
loadFilesEvent.setMenuReset(myEvent);
updateRepo.setOnAction(event -> {
new Thread() {
public void run() {
try {
ScriptingEngine.pull(url, ScriptingEngine.getBranch(url));
} catch (Exception e) {
exp.uncaughtException(Thread.currentThread(), e);
}
myEvent.run();
//selfRef.onRefresh(null);
}
}.start();
});
MenuItem addFile = new MenuItem("Add file to Git Repo...");
addFile.setOnAction(event -> {
System.out.println("Adding file to : " + url);
Platform.runLater(() -> {
Stage s = new Stage();
AddFileToGistController controller = new AddFileToGistController(url, selfRef);
try {
controller.start(s);
} catch (Exception e) {
e.printStackTrace();
}
myEvent.run();
//selfRef.onRefresh(null);
});
});
ScriptingEngine.addOnCommitEventListeners(url, myEvent);
orgRepo.setOnShowing(event -> {
//On showing the menu, set up the rest of the handlers
new Thread(myEvent).start();
});
Platform.runLater(() -> {
if (useAddToWorkspaceItem)
orgRepo.getItems().add(addToWs);
orgRepo.getItems().addAll(updateRepo, addFile, orgFiles, orgCommits, orgBranches);
//Platform.runLater(() -> {
repoMenue.getItems().add(orgRepo);
//});
});
}
};
if (threaded)
t.start();
else
t.run();
}
private static MenuResettingEventHandler createLoadCommitsEvent(String url, Menu orgCommits) {
return new MenuResettingEventHandler() {
public boolean gistFlag = false;
@Override
public void handle(Event event) {
if (gistFlag) {
System.err.println("Another thread is managing this event " + url);
return;// another thread is
// servicing this gist
}
gistFlag = true;
String branchName;
try {
branchName = ScriptingEngine.getFullBranch(url);
} catch (IOException e1) {
exp.uncaughtException(Thread.currentThread(), e1);
return;
}
System.out.println("Load Commits event " + url + " on branch " + branchName);
new Thread(() -> {
Platform.runLater(() -> {
// removing this listener
// after menue is activated
// for the first time
orgCommits.setOnShowing(null);
gistFlag = false;
});
try {
ScriptingEngine.checkout(url, branchName);
Repository repo = ScriptingEngine.getRepository(url);
Git git = new Git(repo);
// System.out.println("Commits of branch: " + branchName);
// System.out.println("-------------------------------------");
Iterable<RevCommit> commits = git.log().add(repo.resolve(branchName)).call();
List<RevCommit> commitsList = Lists.newArrayList(commits.iterator());
Platform.runLater(() -> {
try {
orgCommits.getItems().add(new MenuItem("On Branch " + ScriptingEngine.getBranch(url)));
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
orgCommits.getItems().add(new SeparatorMenuItem());
});
RevCommit previous =null;
for (RevCommit commit : commitsList) {
String date = format.format(new Date(commit.getCommitTime() * 1000L));
String fullData = commit.getName() + "\r\n" + commit.getAuthorIdent().getName() + "\r\n"
+ date + "\r\n" + commit.getFullMessage()
+ "\r\n" + "---------------------------------------------------\r\n";//+
//previous==null?"":getDiffOfCommit(previous,commit, repo, git);
previous=commit;
String string = date + " " +commit.getAuthorIdent().getName()+" "+ commit.getShortMessage();
if (string.length() > 80)
string = string.substring(0, 80);
//MenuItem tmp = new MenuItem(string);
CustomMenuItem tmp = new CustomMenuItem(new Label(string));
Tooltip tooltip = new Tooltip(fullData);
Tooltip.install(tmp.getContent(), tooltip);
tmp.setOnAction(ev -> {
new Thread() {
public void run() {
System.out.println("Selecting \r\n\r\n" + fullData);
String branch;
try {
branch = ScriptingEngine.getBranch(url);
} catch (IOException e1) {
branch="newBranch";
}
String dateString = formatSimple.format( new Date(commit.getCommitTime() * 1000L) );
promptForNewBranch(branch+"-"+dateString,"Creating Branch From Commit:\n\n"+fullData,newBranch -> {
new Thread() {
public void run() {
try {
String slugify = slugify(newBranch);
System.out.println("Creating " + slugify);
ScriptingEngine.setCommitContentsAsCurrent(url, slugify,
commit);
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (GitAPIException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}.start();
});
}
}.start();
});
Platform.runLater(() -> {
orgCommits.getItems().add(tmp);
});
}
git.close();
Platform.runLater(() -> {
orgCommits.hide();
Platform.runLater(() -> {
orgCommits.show();
});
});
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (RevisionSyntaxException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (NoHeadException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (GitAPIException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (Throwable e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}).start();
}
};
}
public static String slugify(String input) {
String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
String normalized = Normalizer.normalize(nowhitespace, Form.NFD);
String slug = NONLATIN.matcher(normalized).replaceAll("").replace('-', '_');
return slug;
}
private static void promptForNewBranch(String exampleName,String reasonForCreating,Consumer<String> resultEvent) {
Platform.runLater(() -> {
TextInputDialog dialog = new TextInputDialog(exampleName);
dialog.setTitle("Create New Branch");
dialog.setHeaderText(reasonForCreating);
dialog.setContentText("Enter a new branch name: ");
// Traditional way to get the response value.
Optional<String> result = dialog.showAndWait();
// The Java 8 way to get the response value (with lambda expression).
result.ifPresent(resultEvent);
});
}
private static MenuResettingEventHandler createLoadBranchesEvent(String url, Menu orgBranches) {
return new MenuResettingEventHandler() {
public boolean gistFlag = false;
EventHandler<Event> thisEvent = this;
@Override
public void handle(Event event) {
if (gistFlag) {
System.err.println("Another thread is managing this event " + url);
return;// another thread is
// servicing this gist
}
gistFlag = true;
System.out.println("Load Branches event " + url);
final MenuItem onBranch;
try {
onBranch = new MenuItem("On Branch " + ScriptingEngine.getBranch(url));
} catch (IOException e1) {
exp.uncaughtException(Thread.currentThread(), e1);
return;
}
;
new Thread(() -> {
Platform.runLater(() -> {
// removing this listener
// after menue is activated
// for the first time
orgBranches.setOnShowing(null);
gistFlag = false;
});
MenuItem newBranchItem = new MenuItem("New Branch...");
String newBranchName="";
try {
newBranchName = ScriptingEngine.getBranch(url);
} catch (IOException e1) {}
String newBranchName1=newBranchName;
String dateString = formatSimple.format( new Date() );
newBranchItem.setOnAction(event1 -> {
promptForNewBranch(newBranchName1+"-"+dateString,
"Create a new Branch from "+newBranchName1,
newBranch -> {
new Thread() {
public void run() {
try {
String slugify = slugify(newBranch);
System.out.println("Creating Branch " + slugify);
ScriptingEngine.newBranch(url, slugify);
getMenuReset().run();
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (GitAPIException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}.start();
});
});
Platform.runLater(() -> {
try {
onBranch.setText("On Branch " + ScriptingEngine.getBranch(url));
orgBranches.getItems().add(onBranch);
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
orgBranches.getItems().add(new SeparatorMenuItem());
orgBranches.getItems().add(newBranchItem);
orgBranches.getItems().add(new SeparatorMenuItem());
});
try {
Collection<Ref> branches = ScriptingEngine.getAllBranches(url);
for (Ref r : branches) {
createRepoMenuItem(url, orgBranches, onBranch, r,getMenuReset());
}
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
} catch (GitAPIException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
System.err.println("Refreshing menu Branches");
Platform.runLater(() -> {
orgBranches.hide();
Platform.runLater(() -> {
orgBranches.show();
});
});
}).start();
}
};
}
private static void createRepoMenuItem(String url, Menu orgBranches, final MenuItem onBranch, Ref r, Runnable menureset) {
String[] name2 = r.getName().split("/");
MenuItem tmp = new MenuItem(name2[name2.length - 1]);
Ref select = r;
String[] name = select.getName().split("/");
String myName = name[name.length - 1];
// System.out.println("Selecting Branch\r\n"+url+" \t\t"+myName);
tmp.setOnAction(ev -> {
new Thread() {
public void run() {
try {
switchToThisNewBranch(url, onBranch, select, myName);
menureset.run();
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
private void switchToThisNewBranch(String url, final MenuItem onBranch, Ref select, String myName)
throws IOException {
String was = ScriptingEngine.getBranch(url);
ScriptingEngine.checkout(url, select);
String s = ScriptingEngine.getBranch(url);
if (myName.contentEquals(s))
System.out.println("Changing from " + was + " to " + myName + " is now "
+ s + "... Success!");
onBranch.setText("On Branch " + s);
}
}.start();
});
Platform.runLater(() -> {
orgBranches.getItems().add(tmp);
});
}
@FXML
public void onLoadFile(ActionEvent e) {
new Thread() {
public void run() {
setName("Load File Thread");
if (openFile == null)
openFile = ScriptingEngine.getLastFile();
openFile = FileSelectionFactory.GetFile(openFile, new ExtensionFilter("All", "*.*"),
new ExtensionFilter("Groovy Scripts", "*.groovy", "*.java", "*.txt"),
new ExtensionFilter("Clojure", "*.cloj", "*.clj", "*.txt", "*.clojure"),
new ExtensionFilter("Python", "*.py", "*.python", "*.txt"),
new ExtensionFilter("DXF", "*.dxf", "*.DXF"),
new ExtensionFilter("GCODE", "*.gcode", "*.nc", "*.ncg", "*.txt"),
new ExtensionFilter("Image", "*.jpg", "*.jpeg", "*.JPG", "*.png", "*.PNG"),
new ExtensionFilter("STL", "*.stl", "*.STL", "*.Stl"));
if (openFile == null) {
return;
}
bowlerStudioModularFrame.createFileTab(openFile);
}
}.start();
}
private static void resetMenueForLoadingFiles(String string, Menu orgFiles, EventHandler<Event> loadFiles) {
Platform.runLater(() -> {
try {
Platform.runLater(() ->{
orgFiles.getItems().clear();
//orgFiles.hide();
Platform.runLater(() ->{
orgFiles.getItems().add(new MenuItem(string));
orgFiles.getItems().add(new SeparatorMenuItem());
orgFiles.setOnShowing(loadFiles);
//Platform.runLater(() ->orgFiles.show());
});
});
} catch (Throwable t) {
t.printStackTrace();
}
});
}
private static MenuResettingEventHandler createLoadFileEvent(String url, Menu orgFiles) {
return new MenuResettingEventHandler() {
public boolean gistFlag = false;
@Override
public void handle(Event ev) {
if (gistFlag) {
System.err.println("Another thread is managing this event");
return;// another thread is
// servicing this gist
}
gistFlag = true;
System.out.println("Load file event " + url);
new Thread() {
public void run() {
setName("Load file Thread " + url);
System.out.println("Loading files for " + url + " ");
ArrayList<String> listofFiles;
try {
listofFiles = ScriptingEngine.filesInGit(url, ScriptingEngine.getFullBranch(url), null);
System.out.println("Clone Done for " + url + listofFiles.size() + " files");
} catch (Exception e1) {
e1.printStackTrace();
return;
}
// if (orgFiles.getItems().size() != 1) {
// Log.warning("Bailing out of loading thread");
// return;// menue populated by
// // another thread
// }
Platform.runLater(() -> {
// removing this listener
// after menue is activated
// for the first time
orgFiles.setOnShowing(null);
gistFlag = false;
});
for (String s : listofFiles) {
System.err.println("Adding file: " + s);
String string = s;
if (s.length() > 80)
s = s.substring(0, 10) + "..." + s.substring(s.length() - 70, s.length() - 1);
MenuItem tmp = new MenuItem(s);
tmp.setOnAction(event -> {
new Thread() {
public void run() {
try {
File fileSelected = ScriptingEngine.fileFromGit(url, string);
BowlerStudio.createFileTab(fileSelected);
BowlerStudioMenuWorkspace.add(url);
getMenuReset().run();
} catch (Exception e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}.start();
});
Platform.runLater(() -> {
orgFiles.getItems().add(tmp);
});
}
System.out.println("Refreshing menu");
Platform.runLater(() -> {
orgFiles.hide();
Platform.runLater(() -> {
orgFiles.show();
});
});
}
}.start();
}
};
}
@FXML
public void onConnect(ActionEvent e) {
ConnectionManager.addConnection();
}
@FXML
public void onConnectVirtual(ActionEvent e) {
ConnectionManager.addConnection(new VirtualGenericPIDDevice(10000), "virtual");
}
@FXML
public void onClose(ActionEvent e) {
BowlerStudio.closeBowlerStudio();
}
@FXML
public void onConnectCHDKCamera(ActionEvent event) {
// Platform.runLater(() -> {
// try {
// ConnectionManager.addConnection(new CHDKImageProvider(), "cameraCHDK");
// } catch (Exception e) {
// exp.uncaughtException(Thread.currentThread(), e);
// }
// });
}
@FXML
public void onConnectCVCamera(ActionEvent event) {
// Platform.runLater(() -> ConnectionManager.onConnectCVCamera());
}
@FXML
public void onConnectFileSourceCamera(ActionEvent event) {
Platform.runLater(() -> ConnectionManager.onConnectFileSourceCamera());
}
@FXML
public void onConnectURLSourceCamera(ActionEvent event) {
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"));
}
@FXML
public void onLogin(ActionEvent event) {
new Thread() {
public void run() {
PasswordManager.checkInternet();
ScriptingEngine.setLoginManager(new GitHubLoginManager());
setName("Login Gist Thread");
try {
ScriptingEngine.logout();
while(!ScriptingEngine.isLoginSuccess() && !PasswordManager.isAnonMode()) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
ScriptingEngine.login();
}
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}.start();
}
@FXML
public void onLogout(ActionEvent event) {
try {
ScriptingEngine.logout();
} catch (IOException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
@FXML
public void onConnectPidSim(ActionEvent event) {
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(ActionEvent event) {
new Thread() {
public void run() {
setName("Load Mobile Base Thread");
File 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) {
exp.uncaughtException(Thread.currentThread(), e);
}
});
}
}.start();
}
@FXML
public void onCreatenewGist(ActionEvent event) {
Stage s = new Stage();
new Thread(() -> {
AddFileToGistController controller = new AddFileToGistController(null, selfRef);
try {
controller.start(s);
setToLoggedIn(name);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
@FXML
public void onOpenGitter(ActionEvent event) {
String url = "https://gitter.im";
try {
BowlerStudio.openUrlInNewTab(new URL(url));
} catch (MalformedURLException e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
@FXML
public void clearScriptCache(ActionEvent event) {
Platform.runLater(() -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Are you sure you have published all your work?");
alert.setHeaderText("This will wipe out the local cache");
alert.setContentText("All files that are not published will be deleted");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK) {
new Thread(() -> {
BowlerStudio.setDeleteFlag(true);
BowlerStudio.exit();
}).start();
} else {
System.out.println("Nothing was deleted");
}
});
}
@FXML
public void changeAssetRepoButtonPressed(ActionEvent event) {
Stage s = new Stage();
new Thread(() -> {
ChangeAssetRepoController controller = new ChangeAssetRepoController();
try {
controller.start(s);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
@FXML
public void onMobileBaseFromGit(ActionEvent event) {
PromptForGit.prompt("Select a Creature From a Git", "https://github.com/madhephaestus/carl-the-hexapod.git",
(gitsId, file) -> {
loadMobilebaseFromGit(gitsId, file);
});
}
@FXML
void onSaveConfiguration(ActionEvent event) {
System.err.println("Saving database");
new Thread() {
public void run() {
ConfigurationDatabase.save();
}
}.start();
}
@FXML // This method is called by the FXMLLoader when initialization is
// complete
void initialize() {
assert CreaturesMenu != null : "fx:id=\"CreaturesMenu\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert GitHubRoot != null : "fx:id=\"GitHubRoot\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert getMeneBarBowlerStudio() != null : "fx:id=\"MeneBarBowlerStudio\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert addMarlinGCODEDevice != null : "fx:id=\"addMarlinGCODEDevice\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert clearCache != null : "fx:id=\"clearCache\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert createNewGist != null : "fx:id=\"createNewGist\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert logoutGithub != null : "fx:id=\"logoutGithub\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert myGists != null : "fx:id=\"myGists\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert myOrganizations != null : "fx:id=\"myOrganizations\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert myRepos != null : "fx:id=\"myRepos\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert watchingRepos != null : "fx:id=\"watchingRepos\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert workspacemenuHandle != null : "fx:id=\"workspacemenuHandle\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert vitaminsMenu != null : "fx:id=\"vitaminsMenu\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
assert addNewVitamin != null : "fx:id=\"addNewVitamin\" was not injected: check your FXML file 'BowlerStudioMenuBar.fxml'.";
selfRef = this;
BowlerStudioMenuWorkspace.init(workspacemenuHandle);
showDevicesPanel.setOnAction(event -> {
bowlerStudioModularFrame.showConectionManager();
});
showCreatureLab.setOnAction(event -> {
bowlerStudioModularFrame.showCreatureLab();
;
});
showTerminal.setOnAction(event -> {
bowlerStudioModularFrame.showTerminal();
});
new Thread() {
public void run() {
try {
ScriptingEngine.setAutoupdate(true);
File f = ScriptingEngine.fileFromGit(
"https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", // git
// repo,
// change
// this
// if
// you
// fork
// this
// demo
"exampleRobots.json"// File from within the Git repo
);
MenuItem newCreatureWiz= new MenuItem("New Creature...");
newCreatureWiz.setOnAction(event -> {
NewCreatureWizard.run();
});
Platform.runLater(() -> {
CreaturesMenu.getItems().add(new SeparatorMenuItem());
CreaturesMenu.getItems().add(newCreatureWiz);
CreaturesMenu.getItems().add(new SeparatorMenuItem());
});
@SuppressWarnings("unchecked")
HashMap<String, HashMap<String, Object>> map = (HashMap<String, HashMap<String, Object>>) ScriptingEngine
.inlineFileScriptRun(f, null);
for (Map.Entry<String, HashMap<String, Object>> entry : map.entrySet()) {
HashMap<String, Object> script = entry.getValue();
MenuItem item = new MenuItem(entry.getKey());
item.setOnAction(event -> {
loadMobilebaseFromGit((String) script.get("scriptGit"), (String) script.get("scriptFile"));
});
Platform.runLater(() -> {
CreaturesMenu.getItems().add(item);
});
}
} catch (Exception e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}.start();
addMarlinGCODEDevice.setOnAction(event -> {
Platform.runLater(() -> ConnectionManager.onMarlinGCODE());
});
loadFirmata.setOnAction(event -> {
Platform.runLater(() -> ConnectionManager.onFirmata());
});
Thread t = new Thread(new Runnable() {
@Override
public void run() {
ScriptingEngine.addIGithubLoginListener(new IGithubLoginListener() {
@Override
public void onLogout(String oldUsername) {
setToLoggedOut();
}
@Override
public void onLogin(String newUsername) {
setToLoggedIn(newUsername);
}
});
FxTimer.runLater(Duration.ofMillis(100), () -> {
if (PasswordManager.getUsername() != null) {
setToLoggedIn(PasswordManager.getUsername());
} else {
setToLoggedOut();
}
});
IGithubLoginListener listener = new IGithubLoginListener() {
private boolean loggingIn = false;
@Override
public void onLogout(String arg0) {
}
@Override
public void onLogin(String arg0) {
if (loggingIn)
return;
loggingIn = true;
new Thread(new Runnable() {
@Override
public void run() {
HashMap<String, Object> openGits = ConfigurationDatabase.getParamMap("studio-open-git");
Object[] set = openGits.keySet().toArray();
for (int i = 0; i < set.length; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if (String.class.isInstance(set[i])) {
String s = (String) set[i];
try {
@SuppressWarnings("unchecked")
ArrayList<String> repoFile = (ArrayList<String>) openGits.get(s);
File f = ScriptingEngine.fileFromGit(repoFile.get(0), repoFile.get(1));
if (!f.exists() || createFileTab(f) == null) {
openGits.remove(s);
System.err.println("Removing missing " + s);
}
} catch (Throwable e) {
openGits.remove(s);
System.out.println("Error loading file " + s);
}
}
}
HashMap<String, Object> openWeb = ConfigurationDatabase.getParamMap("studio-open-web");
for (String s : openWeb.keySet()) {
String repoFile = (String) openWeb.get(s);
try {
bowlerStudioModularFrame.openUrlInNewTab(new URL(repoFile));
} catch (Exception e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
loggingIn = false;
}
}).start();
}
};
if (ScriptingEngine.isLoginSuccess()) {
listener.onLogin(null);
}
ScriptingEngine.addIGithubLoginListener(listener);
if (PasswordManager.hasNetwork() && !PasswordManager.loggedIn()) {
new Thread(() -> {
try {
onLogin(null);
} catch (Exception e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}).start();
} else {
setToLoggedIn(PasswordManager.getUsername());
}
}
});
if (ScriptingEngine.hasNetwork())
t.start();
else if (PasswordManager.getUsername() != null) {
setToLoggedIn(PasswordManager.getUsername());
} else {
setToLoggedOut();
}
// WindowMenu
int[] fonts = new int[] { 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40 };
Menu fontSelect = new Menu("Font Size");
ToggleGroup toggleGroup = new ToggleGroup();
int defSize = ((Number) ConfigurationDatabase.getObject("BowlerStudioConfigs", "fontsize", 12)).intValue();
for (int i = 0; i < fonts.length; i++) {
int myFoneNum = fonts[i];
RadioMenuItem ftmp = new RadioMenuItem(myFoneNum + " pt");
if (defSize == myFoneNum) {
ftmp.setSelected(true);
} else
ftmp.setSelected(false);
ftmp.setOnAction((event) -> {
if (ftmp.isSelected()) {
BowlerStudioController.getBowlerStudio().setFontSize(myFoneNum);
}
});
ftmp.setToggleGroup(toggleGroup);
fontSelect.getItems().add(ftmp);
}
WindowMenu.getItems().add(fontSelect);
new Thread() {
public void run() {
setUncaughtExceptionHandler(new IssueReportingExceptionHandler());
try {
if(vitaminsMenu==null)
throw new RuntimeException("Vitamins menu was not inserted");
if(vitaminsMenu.getItems()==null)
throw new RuntimeException("Vitamins menu items are null");
Platform.runLater(()->{
vitaminsMenu.getItems().add(new SeparatorMenuItem());
});
List<String> types = Vitamins.listVitaminTypes().stream().sorted().collect(Collectors.toList());
for(String s:types) {
addVitaminType(s);
Vitamins.getVitaminFile(s, () -> {
Platform.runLater(()->{
getTypeMenu(s).getItems().clear();
});
setUpSizes(getTypeMenu(s), s ) ;
addVitaminType(s);
}, false);
}
} catch (Exception e) {
exp.uncaughtException(Thread.currentThread(), e);
}
}
}.start();
}
public void addVitaminType(String s) {
getTypeMenu(s);
ArrayList<String> sizes = Vitamins.listVitaminSizes(s);
for(String size:sizes) {
addSizesToMenu(size,s);
}
}
public Menu getTypeMenu(String type) {
if(vitaminTypeMenus.get(type)==null) {
Menu typeMenu = new Menu(type);
vitaminTypeMenus.put(type, typeMenu);
Platform.runLater(()->{
vitaminsMenu.getItems().add(typeMenu);
});
setUpSizes( typeMenu, type );
}
return vitaminTypeMenus.get(type);
}
private void setUpSizes(Menu typeMenu, String type ) {
MenuItem editScript = new MenuItem("Edit "+type+" Cad Generator...");
editScript.setOnAction(event -> {
new Thread(() -> BowlerStudio.createFileTab(Vitamins.getScriptFile(type))).start();
});
Platform.runLater(()->{
typeMenu.getItems().add(new MenuItem("Sizes:"));
typeMenu.getItems().add(new SeparatorMenuItem());
typeMenu.getItems().add(editScript);
typeMenu.getItems().add(new SeparatorMenuItem());
});
}
public void addSizesToMenu( String size,String type) {
MenuItem sizeMenu =new MenuItem(size);
Platform.runLater(()->{
getTypeMenu(type).getItems().add(sizeMenu);
});
sizeMenu.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
new Thread() {
public void run() {
LocalFileScriptTab tab =LocalFileScriptTab.getSelectedTab();
if(tab!=null)
tab.insertString("CSG vitamin_"+slugify(type)+"_"+slugify(size)+" = Vitamins.get(\""+type+"\", \""+size+"\")\n");
}
}.start();
}
});
}
@FXML
void onRefresh(ActionEvent event) {
String current = this.name;//=null;
this.name=null;
setToLoggedIn(current);
}
@FXML
void onCreateNewVitamin(ActionEvent event) {
try {
NewVitaminWizardController.launchWizard(this);
} catch (Exception e) {
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}
@FXML
void onBowlerStudioHelp(ActionEvent event) {
new Thread(()->{
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(new URI("https://hackaday.io/project/6423-bowlerstudio-a-robotics-development-platform"));
} catch (IOException e) {
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), e);
} catch (URISyntaxException e) {
new IssueReportingExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}
}) .start();
}
}