Merge branch 'master' of https://github.com/badvision/lawless-legends
@ -252,7 +252,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Toggle Debug",
|
||||
category = "debug",
|
||||
description = "Show/hide the debug panel",
|
||||
alternatives = "Show Debug;Hide Debug",
|
||||
alternatives = "Show Debug;Hide Debug;Inspect",
|
||||
defaultKeyMapping = "ctrl+shift+d")
|
||||
public static void toggleDebugPanel() {
|
||||
// AbstractEmulatorFrame frame = Emulator.getFrame();
|
||||
@ -268,7 +268,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Toggle fullscreen",
|
||||
category = "general",
|
||||
description = "Activate/deactivate fullscreen mode",
|
||||
alternatives = "fullscreen,maximize",
|
||||
alternatives = "fullscreen;maximize",
|
||||
defaultKeyMapping = "ctrl+shift+f")
|
||||
public static void toggleFullscreen() {
|
||||
Platform.runLater(() -> {
|
||||
@ -283,7 +283,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Save Raw Screenshot",
|
||||
category = "general",
|
||||
description = "Save raw (RAM) format of visible screen",
|
||||
alternatives = "screendump, raw screenshot",
|
||||
alternatives = "screendump;raw screenshot",
|
||||
defaultKeyMapping = "ctrl+shift+z")
|
||||
public static void saveScreenshotRaw() throws FileNotFoundException, IOException {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
|
||||
@ -324,7 +324,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Save Screenshot",
|
||||
category = "general",
|
||||
description = "Save image of visible screen",
|
||||
alternatives = "Save image,save framebuffer,screenshot",
|
||||
alternatives = "Save image;save framebuffer;screenshot",
|
||||
defaultKeyMapping = "ctrl+shift+s")
|
||||
public static void saveScreenshot() throws IOException {
|
||||
FileChooser select = new FileChooser();
|
||||
@ -353,7 +353,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Configuration",
|
||||
category = "general",
|
||||
description = "Edit emulator configuraion",
|
||||
alternatives = "Reconfigure,Preferences,Settings",
|
||||
alternatives = "Reconfigure;Preferences;Settings;Config",
|
||||
defaultKeyMapping = {"f4", "ctrl+shift+c"})
|
||||
public static void showConfig() {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(EmulatorUILogic.class.getResource("/fxml/Configuration.fxml"));
|
||||
@ -375,7 +375,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Open IDE",
|
||||
category = "development",
|
||||
description = "Open new IDE window for Basic/Assembly/Plasma coding",
|
||||
alternatives = "dev,development,acme,assembler,editor",
|
||||
alternatives = "IDE;dev;development;acme;assembler;editor",
|
||||
defaultKeyMapping = {"ctrl+shift+i"})
|
||||
public static void showIDE() {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(EmulatorUILogic.class.getResource("/fxml/editor.fxml"));
|
||||
@ -399,7 +399,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
name = "Resize window",
|
||||
category = "general",
|
||||
description = "Resize the screen to 1x/1.5x/2x/3x video size",
|
||||
alternatives = "Adjust screen;Adjust window size;Adjust aspect ratio;Fix screen;Fix window size;Fix aspect ratio;Correct aspect ratio;",
|
||||
alternatives = "Aspect;Adjust screen;Adjust window size;Adjust aspect ratio;Fix screen;Fix window size;Fix aspect ratio;Correct aspect ratio;",
|
||||
defaultKeyMapping = {"ctrl+shift+a"})
|
||||
public static void scaleIntegerRatio() {
|
||||
Platform.runLater(() -> {
|
||||
@ -445,6 +445,16 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
});
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
name = "About",
|
||||
category = "general",
|
||||
description = "Display about window",
|
||||
alternatives = "info;credits",
|
||||
defaultKeyMapping = {"ctrl+shift+."})
|
||||
public static void showAboutWindow() {
|
||||
//TODO: Implement
|
||||
}
|
||||
|
||||
public static boolean confirm(String message) {
|
||||
// return JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(Emulator.getFrame(), message);
|
||||
return false;
|
||||
|
@ -8,6 +8,8 @@ package jace;
|
||||
import com.sun.glass.ui.Application;
|
||||
import jace.core.Card;
|
||||
import jace.core.Computer;
|
||||
import jace.core.Motherboard;
|
||||
import jace.core.Utility;
|
||||
import jace.library.MediaCache;
|
||||
import jace.library.MediaConsumer;
|
||||
import jace.library.MediaConsumerParent;
|
||||
@ -28,8 +30,10 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.DoubleBinding;
|
||||
import javafx.beans.binding.NumberBinding;
|
||||
import javafx.beans.binding.When;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
@ -37,7 +41,11 @@ import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.effect.DropShadow;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.DragEvent;
|
||||
@ -47,11 +55,14 @@ import javafx.scene.input.TransferMode;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Background;
|
||||
import javafx.scene.layout.BackgroundFill;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.CornerRadii;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -74,9 +85,21 @@ public class JaceUIController {
|
||||
@FXML
|
||||
private ImageView appleScreen;
|
||||
|
||||
@FXML
|
||||
private BorderPane controlOverlay;
|
||||
|
||||
@FXML
|
||||
private Slider speedSlider;
|
||||
|
||||
@FXML
|
||||
private AnchorPane menuButtonPane;
|
||||
|
||||
@FXML
|
||||
private Button menuButton;
|
||||
|
||||
Computer computer;
|
||||
|
||||
private BooleanProperty aspectRatioCorrectionEnabled = new SimpleBooleanProperty(false);
|
||||
private final BooleanProperty aspectRatioCorrectionEnabled = new SimpleBooleanProperty(false);
|
||||
|
||||
@FXML
|
||||
void initialize() {
|
||||
@ -84,6 +107,8 @@ public class JaceUIController {
|
||||
assert stackPane != null : "fx:id=\"stackPane\" was not injected: check your FXML file 'JaceUI.fxml'.";
|
||||
assert notificationBox != null : "fx:id=\"notificationBox\" was not injected: check your FXML file 'JaceUI.fxml'.";
|
||||
assert appleScreen != null : "fx:id=\"appleScreen\" was not injected: check your FXML file 'JaceUI.fxml'.";
|
||||
controlOverlay.setVisible(false);
|
||||
menuButtonPane.setVisible(false);
|
||||
NumberBinding aspectCorrectedWidth = rootPane.heightProperty().multiply(3.0).divide(2.0);
|
||||
NumberBinding width = new When(
|
||||
aspectRatioCorrectionEnabled.and(aspectCorrectedWidth.lessThan(rootPane.widthProperty()))
|
||||
@ -94,6 +119,142 @@ public class JaceUIController {
|
||||
rootPane.setOnDragEntered(this::processDragEnteredEvent);
|
||||
rootPane.setOnDragExited(this::processDragExitedEvent);
|
||||
rootPane.setBackground(new Background(new BackgroundFill(Color.BLACK, null, null)));
|
||||
rootPane.setOnMouseMoved(this::showMenuButton);
|
||||
rootPane.setOnMouseExited(this::hideControlOverlay);
|
||||
menuButton.setOnMouseClicked(this::showControlOverlay);
|
||||
controlOverlay.setOnMouseClicked(this::hideControlOverlay);
|
||||
delayTimer.getKeyFrames().add(new KeyFrame(Duration.millis(3000), evt -> {
|
||||
hideControlOverlay(null);
|
||||
}));
|
||||
}
|
||||
|
||||
private void showMenuButton(MouseEvent evt) {
|
||||
if (!evt.isPrimaryButtonDown() && !evt.isSecondaryButtonDown() && !controlOverlay.isVisible()) {
|
||||
resetMenuButtonTimer();
|
||||
if (!menuButtonPane.isVisible()) {
|
||||
menuButtonPane.setVisible(true);
|
||||
FadeTransition ft = new FadeTransition(Duration.millis(500), menuButtonPane);
|
||||
ft.setFromValue(0.0);
|
||||
ft.setToValue(1.0);
|
||||
ft.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timeline delayTimer = new Timeline();
|
||||
private void resetMenuButtonTimer() {
|
||||
delayTimer.playFromStart();
|
||||
}
|
||||
|
||||
private void showControlOverlay(MouseEvent evt) {
|
||||
if (!evt.isPrimaryButtonDown() && !evt.isSecondaryButtonDown()) {
|
||||
delayTimer.stop();
|
||||
menuButtonPane.setVisible(false);
|
||||
controlOverlay.setVisible(true);
|
||||
FadeTransition ft = new FadeTransition(Duration.millis(500), controlOverlay);
|
||||
ft.setFromValue(0.0);
|
||||
ft.setToValue(1.0);
|
||||
ft.play();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideControlOverlay(MouseEvent evt) {
|
||||
if (menuButtonPane.isVisible()) {
|
||||
FadeTransition ft1 = new FadeTransition(Duration.millis(500), menuButtonPane);
|
||||
ft1.setFromValue(1.0);
|
||||
ft1.setToValue(0.0);
|
||||
ft1.setOnFinished(evt1 -> menuButtonPane.setVisible(false));
|
||||
ft1.play();
|
||||
}
|
||||
if (controlOverlay.isVisible()) {
|
||||
FadeTransition ft2 = new FadeTransition(Duration.millis(500), controlOverlay);
|
||||
ft2.setFromValue(1.0);
|
||||
ft2.setToValue(0.0);
|
||||
ft2.setOnFinished(evt1 -> controlOverlay.setVisible(false));
|
||||
ft2.play();
|
||||
}
|
||||
}
|
||||
|
||||
private double convertSpeedToRatio(Double setting) {
|
||||
if (setting < 1.0) {
|
||||
return 0.5;
|
||||
} else if (setting == 1.0) {
|
||||
return 1.0;
|
||||
} else if (setting >= 10) {
|
||||
return Double.MAX_VALUE;
|
||||
} else {
|
||||
double val = Math.pow(2.0, (setting - 1.0) / 1.5);
|
||||
val = Math.floor(val * 2.0) / 2.0;
|
||||
if (val > 2.0) {
|
||||
val = Math.floor(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
private void connectControls(Stage primaryStage) {
|
||||
connectButtons(controlOverlay);
|
||||
if (computer.getKeyboard() != null) {
|
||||
EventHandler<KeyEvent> keyboardHandler = computer.getKeyboard().getListener();
|
||||
primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState());
|
||||
rootPane.setOnKeyPressed(keyboardHandler);
|
||||
rootPane.setOnKeyReleased(keyboardHandler);
|
||||
rootPane.setFocusTraversable(true);
|
||||
}
|
||||
speedSlider.setValue(1.0);
|
||||
speedSlider.setMinorTickCount(0);
|
||||
speedSlider.setMajorTickUnit(1);
|
||||
speedSlider.setLabelFormatter(new StringConverter<Double>() {
|
||||
@Override
|
||||
public String toString(Double val) {
|
||||
if (val < 1.0) {
|
||||
return "Half";
|
||||
} else if (val >= 10.0) {
|
||||
return "∞";
|
||||
}
|
||||
double v = convertSpeedToRatio(val);
|
||||
if (v != Math.floor(v)) {
|
||||
return String.valueOf(v) + "x";
|
||||
} else {
|
||||
return String.valueOf((int) v) + "x";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double fromString(String string) {
|
||||
return 1.0;
|
||||
}
|
||||
});
|
||||
speedSlider.valueProperty().addListener((val, oldValue, newValue) -> setSpeed(newValue.doubleValue()));
|
||||
}
|
||||
|
||||
private void connectButtons(Node n) {
|
||||
if (n instanceof Button) {
|
||||
Button button = (Button) n;
|
||||
Runnable action = Utility.getNamedInvokableAction(button.getText());
|
||||
button.setOnMouseClicked(evt -> action.run());
|
||||
} else if (n instanceof Parent) {
|
||||
for (Node child : ((Parent) n).getChildrenUnmodifiable()) {
|
||||
connectButtons(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setSpeed(double speed) {
|
||||
double speedRatio = convertSpeedToRatio(speed);
|
||||
if (speedRatio > 100.0) {
|
||||
Emulator.computer.getMotherboard().maxspeed = true;
|
||||
Motherboard.cpuPerClock = 3;
|
||||
} else {
|
||||
if (speedRatio > 25) {
|
||||
Motherboard.cpuPerClock = 2;
|
||||
} else {
|
||||
Motherboard.cpuPerClock = 1;
|
||||
}
|
||||
Emulator.computer.getMotherboard().maxspeed = false;
|
||||
Emulator.computer.getMotherboard().speedRatio = (int) (speedRatio * 100);
|
||||
}
|
||||
Emulator.computer.getMotherboard().reconfigure();
|
||||
}
|
||||
|
||||
public void toggleAspectRatio() {
|
||||
@ -110,13 +271,7 @@ public class JaceUIController {
|
||||
}
|
||||
this.computer = computer;
|
||||
Platform.runLater(() -> {
|
||||
if (computer.getKeyboard() != null) {
|
||||
EventHandler<KeyEvent> keyboardHandler = computer.getKeyboard().getListener();
|
||||
primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState());
|
||||
rootPane.setOnKeyPressed(keyboardHandler);
|
||||
rootPane.setOnKeyReleased(keyboardHandler);
|
||||
rootPane.setFocusTraversable(true);
|
||||
}
|
||||
connectControls(primaryStage);
|
||||
appleScreen.setImage(computer.getVideo().getFrameBuffer());
|
||||
appleScreen.setVisible(true);
|
||||
rootPane.requestFocus();
|
||||
|
@ -89,7 +89,7 @@ public class VideoNTSC extends VideoDHGR {
|
||||
static int currentMode = -1;
|
||||
@InvokableAction(name = "Toggle video mode",
|
||||
category = "video",
|
||||
alternatives = "mode,color,b&w,monochrome",
|
||||
alternatives = "Gfx mode;color;b&w;monochrome",
|
||||
defaultKeyMapping = {"ctrl+shift+g"})
|
||||
public static void changeVideoMode() {
|
||||
VideoNTSC thiss = (VideoNTSC) Emulator.computer.video;
|
||||
|
@ -41,7 +41,7 @@ public abstract class Cheats extends Device {
|
||||
super(computer);
|
||||
}
|
||||
|
||||
@InvokableAction(name = "Toggle Cheats", alternatives = "cheat", defaultKeyMapping = "ctrl+shift+m")
|
||||
@InvokableAction(name = "Toggle Cheats", alternatives = "cheat;Plug-in", defaultKeyMapping = "ctrl+shift+m")
|
||||
public void toggleCheats() {
|
||||
cheatsActive = !cheatsActive;
|
||||
if (cheatsActive) {
|
||||
|
@ -49,6 +49,7 @@ import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.image.Image;
|
||||
@ -255,6 +256,12 @@ public class Configuration implements Reconfigurable {
|
||||
getChangedIcon().ifPresent(this::setGraphic);
|
||||
}
|
||||
}
|
||||
|
||||
public Stream<ConfigNode> getTreeAsStream() {
|
||||
return Stream.concat(
|
||||
Stream.of(this),
|
||||
children.stream().flatMap(ConfigNode::getTreeAsStream));
|
||||
}
|
||||
}
|
||||
public static ConfigNode BASE;
|
||||
public static EmulatorUILogic ui = Emulator.logic;
|
||||
@ -494,7 +501,9 @@ public class Configuration implements Reconfigurable {
|
||||
newRoot.getChildren().stream().forEach((child) -> {
|
||||
String childName = child.toString();
|
||||
ConfigNode oldChild = oldRoot.findChild(childName);
|
||||
if (oldChild == null) {oldChild = oldRoot.findChild(child.id);}
|
||||
if (oldChild == null) {
|
||||
oldChild = oldRoot.findChild(child.id);
|
||||
}
|
||||
// System.out.println("Applying settings for " + childName);
|
||||
applyConfigTree(child, oldChild);
|
||||
});
|
||||
|
@ -169,7 +169,7 @@ public abstract class Computer implements Reconfigurable {
|
||||
name = "Warm boot",
|
||||
description = "Process user-initatiated reboot (ctrl+apple+reset)",
|
||||
category = "general",
|
||||
alternatives = "reboot;reset;three-finger-salute",
|
||||
alternatives = "reboot;reset;three-finger-salute;restart",
|
||||
defaultKeyMapping = {"Ctrl+Ignore Alt+Ignore Meta+Backspace", "Ctrl+Ignore Alt+Ignore Meta+Delete"})
|
||||
public void invokeWarmStart() {
|
||||
warmStart();
|
||||
@ -193,7 +193,7 @@ public abstract class Computer implements Reconfigurable {
|
||||
return result;
|
||||
}
|
||||
|
||||
@InvokableAction(name = "Resume", description = "Resumes the computer if it was previously paused", alternatives = "unpause;unfreeze;resume", defaultKeyMapping = {"meta+shift+pause", "alt+shift+pause"})
|
||||
@InvokableAction(name = "Resume", description = "Resumes the computer if it was previously paused", alternatives = "unpause;unfreeze;resume;play", defaultKeyMapping = {"meta+shift+pause", "alt+shift+pause"})
|
||||
public void resume() {
|
||||
doResume();
|
||||
getRunningProperty().set(true);
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package jace.core;
|
||||
|
||||
import jace.config.Configuration;
|
||||
import jace.config.InvokableAction;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
@ -33,13 +35,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Alert;
|
||||
@ -73,11 +72,11 @@ public class Utility {
|
||||
*
|
||||
* @param s
|
||||
* @param t
|
||||
* @return Distance (higher is better)
|
||||
* @return Distance (lower means a closer match, zero is identical)
|
||||
*/
|
||||
public static int levenshteinDistance(String s, String t) {
|
||||
if (s == null || t == null || s.length() == 0 || t.length() == 0) {
|
||||
return -1;
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
s = s.toLowerCase().replaceAll("[^a-zA-Z0-9\\s]", "");
|
||||
@ -103,9 +102,20 @@ public class Utility {
|
||||
}
|
||||
}
|
||||
}
|
||||
return Math.max(m, n) - dist[m][n];
|
||||
return dist[m][n];
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize distance based on longest string
|
||||
* @param s
|
||||
* @param t
|
||||
* @return Similarity ranking, higher is better
|
||||
*/
|
||||
public static int adjustedLevenshteinDistance(String s, String t) {
|
||||
return Math.max(s.length(), t.length()) - levenshteinDistance(s, t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare strings based on a tally of similar patterns found, using a fixed
|
||||
* search window The resulting score is heavily penalized if the strings
|
||||
@ -115,7 +125,7 @@ public class Utility {
|
||||
* @param c1
|
||||
* @param c2
|
||||
* @param width Search window size
|
||||
* @return Overall similarity score (higher is beter)
|
||||
* @return Overall similarity score (higher is better)
|
||||
*/
|
||||
public static double rankMatch(String c1, String c2, int width) {
|
||||
double score = 0;
|
||||
@ -237,8 +247,8 @@ public class Utility {
|
||||
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
double s1 = levenshteinDistance(match, o1);
|
||||
double s2 = levenshteinDistance(match, o2);
|
||||
double s1 = adjustedLevenshteinDistance(match, o1);
|
||||
double s2 = adjustedLevenshteinDistance(match, o2);
|
||||
if (s2 == s1) {
|
||||
s1 = rankMatch(o1, match, 3) + rankMatch(o1, match, 2);
|
||||
s2 = rankMatch(o2, match, 3) + rankMatch(o2, match, 2);
|
||||
@ -278,7 +288,7 @@ public class Utility {
|
||||
// System.out.println(match + "->" + c + ":" + l + " -- "+ m2 + "," + m3 + "," + "(" + (m2 + m3) + ")");
|
||||
// }
|
||||
// double score = rankMatch(match, candidates.get(0), 2);
|
||||
double score = levenshteinDistance(match, candidates.get(0));
|
||||
double score = adjustedLevenshteinDistance(match, candidates.get(0));
|
||||
if (score > 1) {
|
||||
return candidates.get(0);
|
||||
}
|
||||
@ -472,4 +482,47 @@ public class Utility {
|
||||
}
|
||||
return setChild(object, paths[paths.length - 1], value, hex);
|
||||
}
|
||||
|
||||
static Map<InvokableAction, Runnable> allActions = null;
|
||||
|
||||
public static Map<InvokableAction, Runnable> getAllInvokableActions() {
|
||||
if (allActions == null) {
|
||||
allActions = new HashMap<>();
|
||||
Configuration.BASE.getTreeAsStream().forEach((Configuration.ConfigNode node) -> {
|
||||
for (Method m : node.subject.getClass().getMethods()) {
|
||||
if (m.isAnnotationPresent(InvokableAction.class)) {
|
||||
allActions.put(m.getAnnotation(InvokableAction.class), () -> {
|
||||
try {
|
||||
m.invoke(node.subject);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return allActions;
|
||||
}
|
||||
|
||||
public static Runnable getNamedInvokableAction(String action) {
|
||||
Map<InvokableAction, Runnable> actions = getAllInvokableActions();
|
||||
List<InvokableAction> actionsList = new ArrayList(actions.keySet());
|
||||
actionsList.sort((a,b) -> Integer.compare(getActionNameMatch(action, a), getActionNameMatch(action, b)));
|
||||
// for (InvokableAction a : actionsList) {
|
||||
// String actionName = a.alternatives() == null ? a.name() : (a.name() + ";" + a.alternatives());
|
||||
// System.out.println("Score for " + action + " evaluating " + a.name() + ": " + getActionNameMatch(action, a));
|
||||
// }
|
||||
return actions.get(actionsList.get(0));
|
||||
}
|
||||
|
||||
private static int getActionNameMatch(String str, InvokableAction action) {
|
||||
int nameMatch = levenshteinDistance(str, action.name());
|
||||
if (action.alternatives() != null) {
|
||||
for (String alt : action.alternatives().split(";")) {
|
||||
nameMatch = Math.min(nameMatch, levenshteinDistance(str, alt));
|
||||
}
|
||||
}
|
||||
return nameMatch;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,188 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Slider?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.TilePane?>
|
||||
|
||||
<AnchorPane id="AnchorPane" fx:id="rootPane" prefHeight="384.0" prefWidth="560.0" style="-fx-background-color: BLACK;" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="jace.JaceUIController">
|
||||
<AnchorPane id="AnchorPane" fx:id="rootPane" prefHeight="384.0" prefWidth="560.0" style="-fx-background-color: black;" stylesheets="@../styles/style.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="jace.JaceUIController">
|
||||
<children>
|
||||
<StackPane fx:id="stackPane" prefHeight="384.0" prefWidth="560.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<children>
|
||||
<ImageView fx:id="appleScreen" fitHeight="384.0" fitWidth="560.0" pickOnBounds="true" style="-fx-background-color: BLACK;" />
|
||||
<HBox fx:id="notificationBox" alignment="BOTTOM_RIGHT" blendMode="SCREEN" fillHeight="false" maxHeight="45.0" mouseTransparent="true" prefHeight="45.0" prefWidth="560.0" StackPane.alignment="BOTTOM_CENTER" />
|
||||
<AnchorPane fx:id="menuButtonPane" prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Button fx:id="menuButton" layoutX="494.0" layoutY="14.0" mnemonicParsing="false" styleClass="menuButton" text="☰" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<BorderPane fx:id="controlOverlay" visible="false">
|
||||
<center>
|
||||
<HBox maxHeight="64.0" prefHeight="64.0" styleClass="uiSpeedSlider" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<Pane prefHeight="200.0" prefWidth="200.0" HBox.hgrow="SOMETIMES" />
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<ImageView layoutX="2.0" layoutY="2.0">
|
||||
<image>
|
||||
<Image url="@../styles/icons/slow.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<Slider fx:id="speedSlider" blockIncrement="1.0" majorTickUnit="5.0" max="10.0" minorTickCount="5" prefHeight="64.0" prefWidth="300.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="1.0" HBox.hgrow="ALWAYS">
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
<padding>
|
||||
<Insets top="18.0" />
|
||||
</padding>
|
||||
</Slider>
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<ImageView layoutX="2.0" layoutY="2.0">
|
||||
<image>
|
||||
<Image url="@../styles/icons/fast.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<Pane prefHeight="200.0" prefWidth="200.0" HBox.hgrow="SOMETIMES" />
|
||||
</children>
|
||||
</HBox>
|
||||
</center>
|
||||
<top>
|
||||
<HBox fillHeight="false" nodeOrientation="LEFT_TO_RIGHT" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<TilePane hgap="5.0" nodeOrientation="LEFT_TO_RIGHT" vgap="5.0" HBox.hgrow="SOMETIMES">
|
||||
<children>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Info">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/info.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Config">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/config.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</TilePane>
|
||||
<TilePane alignment="TOP_RIGHT" hgap="5.0" vgap="5.0" HBox.hgrow="ALWAYS">
|
||||
<children>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="IDE">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/ide.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Inspect">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/inspect.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button alignment="TOP_LEFT" contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Plug-in" TilePane.alignment="TOP_RIGHT">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/plugin.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</TilePane>
|
||||
</children>
|
||||
</HBox>
|
||||
</top>
|
||||
<bottom>
|
||||
<HBox fillHeight="false" nodeOrientation="LEFT_TO_RIGHT" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<TilePane hgap="5.0" nodeOrientation="LEFT_TO_RIGHT" vgap="5.0" HBox.hgrow="SOMETIMES">
|
||||
<children>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Fullscreen">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/fullscreen.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Aspect">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/aspect.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Gfx Mode">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/screenshot.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</TilePane>
|
||||
<TilePane alignment="TOP_RIGHT" hgap="5.0" vgap="5.0" HBox.hgrow="ALWAYS">
|
||||
<children>
|
||||
<Button contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Play">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/play.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button alignment="TOP_LEFT" contentDisplay="TOP" mnemonicParsing="false" styleClass="uiActionButton" text="Restart" TilePane.alignment="TOP_RIGHT">
|
||||
<graphic>
|
||||
<ImageView>
|
||||
<image>
|
||||
<Image url="@../styles/icons/reboot.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</children>
|
||||
</TilePane>
|
||||
</children>
|
||||
</HBox>
|
||||
</bottom>
|
||||
<StackPane.margin>
|
||||
<Insets />
|
||||
</StackPane.margin>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</padding>
|
||||
</BorderPane>
|
||||
</children>
|
||||
</StackPane>
|
||||
</children>
|
||||
|
After Width: | Height: | Size: 724 B |
After Width: | Height: | Size: 976 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 914 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 567 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 701 B |
After Width: | Height: | Size: 959 B |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.3 KiB |
@ -19,3 +19,30 @@
|
||||
-fx-font-size: 9pt;
|
||||
-fx-font-family: "Courier New";
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
-fx-font-size:16pt;
|
||||
-fx-border-radius: 10px;
|
||||
-fx-background-radius: 10px;
|
||||
}
|
||||
|
||||
.menuButton, .uiActionButton, .uiSpeedSlider ImageView, .uiSpeedSlider Slider, .uiSpeedSlider AnchorPane {
|
||||
-fx-background-color: rgba(0, 0, 0, 0.75);
|
||||
-fx-text-fill: #a0FFa0
|
||||
}
|
||||
|
||||
.uiActionButton ImageView, .uiSpeedSlider ImageView {
|
||||
-fx-effect: dropshadow(gaussian , rgba(128,255,128,0.75) , 2,1.0,0,0);
|
||||
}
|
||||
|
||||
.uiSpeedSlider AnchorPane {
|
||||
-fx-padding: 0 5 0 5
|
||||
}
|
||||
|
||||
.uiSpeedSlider Slider {
|
||||
-fx-padding: 18 0 10 0
|
||||
}
|
||||
|
||||
.uiSpeedSlider Slider NumberAxis {
|
||||
-fx-tick-label-fill: #80ff80
|
||||
}
|