Add placeholder when no previous projects

pull/98/head
James Ball 2022-07-06 15:58:03 +01:00 zatwierdzone przez James H Ball
rodzic a068492a0d
commit 655f2ee90a
10 zmienionych plików z 190 dodań i 152 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
package sh.ball.gui;
@FunctionalInterface
public interface ExceptionConsumer<T> {
void accept(T value) throws Exception;
public interface ExceptionBiConsumer<T, S> {
void accept(T value1, S value2) throws Exception;
}

Wyświetl plik

@ -114,7 +114,7 @@ public class Gui extends Application {
root = loader.load();
MainController controller = loader.getController();
projectSelectController.setApplicationLauncher(path -> launchMainApplication(controller, path));
projectSelectController.setApplicationLauncher((path, muted) -> launchMainApplication(controller, path, muted));
controller.setAddRecentFile(projectSelectController::addRecentFile);
@ -172,9 +172,12 @@ public class Gui extends Application {
editor.setCallback(controller::updateFileData);
}
public void launchMainApplication(MainController controller, String projectPath) throws Exception {
public void launchMainApplication(MainController controller, String projectPath, Boolean muted) throws Exception {
scene.setRoot(root);
controller.openProject(projectPath);
if (muted) {
controller.setVolume(0);
}
}
public static void launchCodeEditor(String code, String fileName) {

Wyświetl plik

@ -321,4 +321,8 @@ public class EffectsController implements Initializable, SubController {
public void disableMouseTranslate() {
translateCheckBox.setSelected(false);
}
public void setVolume(double volumeValue) {
volume.controller.slider.setValue(volumeValue);
}
}

Wyświetl plik

@ -1433,6 +1433,10 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
this.addRecentFile = addRecentFile;
}
public void setVolume(double volume) {
effectsController.setVolume(volume);
}
private record PrintableSlider(Slider slider) {
@Override
public String toString() {

Wyświetl plik

@ -1,142 +1,146 @@
package sh.ball.gui.controller;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ListView;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.html.HTMLAnchorElement;
import sh.ball.gui.ExceptionConsumer;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ResourceBundle;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.prefs.Preferences;
import static sh.ball.gui.Gui.logger;
public class ProjectSelectController implements Initializable {
private static final int MAX_ITEMS = 20;
private static final String RECENT_FILE = "RECENT_FILE_";
private final Preferences userPreferences = Preferences.userNodeForPackage(getClass());
private final ObservableList<String> recentFiles = FXCollections.observableArrayList();
private ExceptionConsumer<String> launchMainApplication;
private Consumer<String> openBrowser;
@FXML
private ListView<String> recentFilesListView;
@FXML
private Button newProjectButton;
@FXML
private CheckBox startMutedCheckBox;
@FXML
private WebView changelogWebView;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
for (int i = 0; i < MAX_ITEMS; i++) {
String path = userPreferences.get(RECENT_FILE + i, null);
if (path != null) {
recentFiles.add(path);
} else {
break;
}
}
recentFilesListView.setItems(recentFiles);
recentFilesListView.setOnMouseClicked(e -> {
try {
launchMainApplication.accept(recentFilesListView.getSelectionModel().getSelectedItem());
} catch (Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
});
newProjectButton.setOnAction(e -> {
try {
launchMainApplication.accept(null);
} catch (Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
});
try {
String changelogHtml = new String(getClass().getResourceAsStream("/html/changelog.html").readAllBytes(), StandardCharsets.UTF_8);
changelogWebView.getEngine().loadContent(changelogHtml);
InputStream changelogInputStream = getClass().getResourceAsStream("/CHANGELOG.md");
String changelog = new String(changelogInputStream.readAllBytes(), StandardCharsets.UTF_8);
changelogWebView.getEngine().getLoadWorker().stateProperty().addListener((e, old, state) -> {
if (state == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) changelogWebView.getEngine().executeScript("window");
window.setMember("changelog", changelog);
changelogWebView.getEngine().executeScript(
"document.getElementById('content').innerHTML = marked.parse(changelog);"
);
Document document = changelogWebView.getEngine().getDocument();
NodeList nodeList = document.getElementsByTagName("a");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node= nodeList.item(i);
EventTarget eventTarget = (EventTarget) node;
eventTarget.addEventListener("click", evt -> {
EventTarget target = evt.getCurrentTarget();
HTMLAnchorElement anchorElement = (HTMLAnchorElement) target;
String href = anchorElement.getHref();
openBrowser.accept(href);
evt.preventDefault();
}, false);
}
}
});
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
public void addRecentFile(String path) {
int index = recentFiles.indexOf(path);
if (index == -1) {
userPreferences.get(RECENT_FILE + recentFiles.size(), path);
recentFiles.add(0, path);
if (recentFiles.size() > MAX_ITEMS) {
recentFiles.remove(recentFiles.size() - 1);
}
} else {
recentFiles.remove(index);
recentFiles.add(0, path);
}
resetRecentFiles();
}
private void resetRecentFiles() {
for (int i = 0; i < MAX_ITEMS; i++) {
userPreferences.remove(RECENT_FILE + i);
}
for (int i = 0; i < recentFiles.size(); i++) {
userPreferences.put(RECENT_FILE + i, recentFiles.get(i));
}
}
public void setApplicationLauncher(ExceptionConsumer<String> launchMainApplication) {
this.launchMainApplication = launchMainApplication;
}
public void setOpenBrowser(Consumer<String> openBrowser) {
this.openBrowser = openBrowser;
}
}
package sh.ball.gui.controller;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ListView;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.html.HTMLAnchorElement;
import sh.ball.gui.ExceptionBiConsumer;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ResourceBundle;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.prefs.Preferences;
import static sh.ball.gui.Gui.logger;
public class ProjectSelectController implements Initializable {
private static final int MAX_ITEMS = 20;
private static final String RECENT_FILE = "RECENT_FILE_";
private static final String START_MUTED = "START_MUTED";
private final Preferences userPreferences = Preferences.userNodeForPackage(getClass());
private final ObservableList<String> recentFiles = FXCollections.observableArrayList();
private ExceptionBiConsumer<String, Boolean> launchMainApplication;
private Consumer<String> openBrowser;
@FXML
private ListView<String> recentFilesListView;
@FXML
private Button newProjectButton;
@FXML
private CheckBox startMutedCheckBox;
@FXML
private WebView changelogWebView;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
for (int i = 0; i < MAX_ITEMS; i++) {
String path = userPreferences.get(RECENT_FILE + i, null);
if (path != null) {
recentFiles.add(path);
} else {
break;
}
}
recentFilesListView.setItems(recentFiles);
recentFilesListView.setOnMouseClicked(e -> {
try {
launchMainApplication.accept(recentFilesListView.getSelectionModel().getSelectedItem(), startMutedCheckBox.isSelected());
} catch (Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
});
newProjectButton.setOnAction(e -> {
try {
launchMainApplication.accept(null, startMutedCheckBox.isSelected());
} catch (Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
});
startMutedCheckBox.setSelected(userPreferences.getBoolean(START_MUTED, false));
startMutedCheckBox.selectedProperty().addListener((e, old, startMuted) -> userPreferences.putBoolean(START_MUTED, startMuted));
try {
String changelogHtml = new String(getClass().getResourceAsStream("/html/changelog.html").readAllBytes(), StandardCharsets.UTF_8);
changelogWebView.getEngine().loadContent(changelogHtml);
InputStream changelogInputStream = getClass().getResourceAsStream("/CHANGELOG.md");
String changelog = new String(changelogInputStream.readAllBytes(), StandardCharsets.UTF_8);
changelogWebView.getEngine().getLoadWorker().stateProperty().addListener((e, old, state) -> {
if (state == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) changelogWebView.getEngine().executeScript("window");
window.setMember("changelog", changelog);
changelogWebView.getEngine().executeScript(
"document.getElementById('content').innerHTML = marked.parse(changelog);"
);
Document document = changelogWebView.getEngine().getDocument();
NodeList nodeList = document.getElementsByTagName("a");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node= nodeList.item(i);
EventTarget eventTarget = (EventTarget) node;
eventTarget.addEventListener("click", evt -> {
EventTarget target = evt.getCurrentTarget();
HTMLAnchorElement anchorElement = (HTMLAnchorElement) target;
String href = anchorElement.getHref();
openBrowser.accept(href);
evt.preventDefault();
}, false);
}
}
});
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
public void addRecentFile(String path) {
int index = recentFiles.indexOf(path);
if (index == -1) {
userPreferences.get(RECENT_FILE + recentFiles.size(), path);
recentFiles.add(0, path);
if (recentFiles.size() > MAX_ITEMS) {
recentFiles.remove(recentFiles.size() - 1);
}
} else {
recentFiles.remove(index);
recentFiles.add(0, path);
}
resetRecentFiles();
}
private void resetRecentFiles() {
for (int i = 0; i < MAX_ITEMS; i++) {
userPreferences.remove(RECENT_FILE + i);
}
for (int i = 0; i < recentFiles.size(); i++) {
userPreferences.put(RECENT_FILE + i, recentFiles.get(i));
}
}
public void setApplicationLauncher(ExceptionBiConsumer<String, Boolean> launchMainApplication) {
this.launchMainApplication = launchMainApplication;
}
public void setOpenBrowser(Consumer<String> openBrowser) {
this.openBrowser = openBrowser;
}
}

Wyświetl plik

@ -385,4 +385,10 @@
-fx-border-width: 1px;
-fx-border-radius: 0;
-fx-border-color: white;
}
.white-border {
-fx-border-width: 1px;
-fx-border-radius: 0;
-fx-border-color: white;
}

Wyświetl plik

@ -63,7 +63,7 @@
</AnchorPane>
<EffectComponentGroup fx:id="translationScale" alwaysEnabled="true" increment="0.05" label="translationScale" majorTickUnit="1.0" max="10.0" min="0.0" name="Translation scale" type="TRANSLATE" value="1.0" />
<EffectComponentGroup fx:id="translationSpeed" alwaysEnabled="true" increment="0.05" label="translationSpeed" majorTickUnit="1.0" max="10.0" min="0.0" name="Translation speed" type="TRANSLATE_SPEED" value="1.0" />
<EffectComponentGroup fx:id="volume" alwaysEnabled="true" increment="0.05" label="volume" majorTickUnit="1.0" max="10.0" min="0.0" name="Volume scale" type="SCALE" value="3.0" />
<EffectComponentGroup fx:id="volume" alwaysEnabled="true" increment="0.05" label="volume" majorTickUnit="1.0" max="10.0" min="0.0" name="Master volume" type="SCALE" value="3.0" />
<EffectComponentGroup fx:id="backingMidi" alwaysEnabled="true" increment="0.005" label="visibility" majorTickUnit="0.1" max="1.0" min="0.0" name="MIDI volume" type="VISIBILITY" value="0.25" />
<Label alignment="CENTER" prefWidth="601.0" text="Rotation" textAlignment="JUSTIFY">
<padding>

Wyświetl plik

@ -21,7 +21,6 @@
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem disable="true" mnemonicParsing="false" text="osci-render v1.26.4" />
<MenuItem fx:id="openProjectMenuItem" mnemonicParsing="false" text="Open Project">
<accelerator>
<KeyCodeCombination alt="UP" code="O" control="UP" meta="UP" shift="UP" shortcut="DOWN" />

Wyświetl plik

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
@ -17,12 +19,27 @@
<Image url="@../images/osci.png" />
</image>
</ImageView>
<ListView fx:id="recentFilesListView" layoutX="28.0" layoutY="333.0" prefHeight="257.0" prefWidth="527.0" />
<ListView fx:id="recentFilesListView" layoutX="28.0" layoutY="333.0" prefHeight="257.0" prefWidth="527.0" styleClass="darkPane" >
<placeholder>
<Label text="No recent projects. Start a new project below." />
</placeholder>
</ListView>
<Button fx:id="newProjectButton" layoutX="222.0" layoutY="609.0" mnemonicParsing="false" prefHeight="40.0" prefWidth="131.0" text="Start new project" />
<CheckBox fx:id="startMutedCheckBox" layoutX="240.0" layoutY="670.0" mnemonicParsing="false" text="Start muted" />
<Label layoutX="188.0" layoutY="294.0" styleClass="title" text="Recently opened projects" />
<Label layoutX="14.0" layoutY="700.0" text="v1.26.4" />
<Label layoutX="727.0" layoutY="40.0" styleClass="title" text="Changelog" />
<WebView fx:id="changelogWebView" layoutX="583.0" layoutY="104.0" prefHeight="590.0" prefWidth="376.0" />
<Label layoutX="727.0" layoutY="20.0" styleClass="title" text="Changelog" />
<AnchorPane layoutX="582.0" layoutY="65.0" prefHeight="200.0" prefWidth="376.0">
<children>
<WebView fx:id="changelogWebView" layoutX="2.0" layoutY="2.0" prefHeight="638.0" prefWidth="376.0" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<styleClass>
<String fx:value="white-border" />
<String fx:value="darkPane" />
</styleClass>
</AnchorPane>
</children></AnchorPane>
</AnchorPane>

Wyświetl plik

@ -7,8 +7,9 @@
body {
background-color: #111111;
color: white;
font-family: Arial,serif;
font-family: Segoe UI,Frutiger,Frutiger Linotype,Dejavu Sans,Helvetica Neue,Arial,sans-serif;
margin: 0 0.5em 0 0;
font-size: 0.8em;
padding: 0;
}