mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
half done with the widget system
This commit is contained in:
@@ -1,11 +1,10 @@
|
|||||||
package org.toop.app;
|
package org.toop.app;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
import org.toop.app.widget.Widget;
|
||||||
import org.toop.app.view.ViewStack;
|
|
||||||
import org.toop.app.view.views.QuitView;
|
|
||||||
import org.toop.app.widget.WidgetContainer;
|
import org.toop.app.widget.WidgetContainer;
|
||||||
import org.toop.app.widget.complex.ConfirmWidget;
|
import org.toop.app.widget.display.SongDisplay;
|
||||||
import org.toop.app.widget.complex.PopupWidget;
|
import org.toop.app.widget.popup.QuitPopup;
|
||||||
|
import org.toop.app.widget.primary.MainPrimary;
|
||||||
import org.toop.framework.audio.events.AudioEvents;
|
import org.toop.framework.audio.events.AudioEvents;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
import org.toop.framework.resource.ResourceManager;
|
import org.toop.framework.resource.ResourceManager;
|
||||||
@@ -14,12 +13,11 @@ import org.toop.local.AppContext;
|
|||||||
import org.toop.local.AppSettings;
|
import org.toop.local.AppSettings;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
public final class App extends Application {
|
public final class App extends Application {
|
||||||
private static Stage stage;
|
private static Stage stage;
|
||||||
private static Scene scene;
|
private static Scene scene;
|
||||||
@@ -39,6 +37,8 @@ public final class App extends Application {
|
|||||||
final Scene scene = new Scene(root);
|
final Scene scene = new Scene(root);
|
||||||
|
|
||||||
stage.setTitle(AppContext.getString("app-title"));
|
stage.setTitle(AppContext.getString("app-title"));
|
||||||
|
stage.titleProperty().bind(AppContext.bindToKey("app-title"));
|
||||||
|
|
||||||
stage.setWidth(1080);
|
stage.setWidth(1080);
|
||||||
stage.setHeight(720);
|
stage.setHeight(720);
|
||||||
|
|
||||||
@@ -65,21 +65,8 @@ public final class App extends Application {
|
|||||||
AppSettings.applySettings();
|
AppSettings.applySettings();
|
||||||
new EventFlow().addPostEvent(new AudioEvents.StartBackgroundMusic()).asyncPostEvent();
|
new EventFlow().addPostEvent(new AudioEvents.StartBackgroundMusic()).asyncPostEvent();
|
||||||
|
|
||||||
var abc = new ConfirmWidget("abc");
|
WidgetContainer.add(Pos.CENTER, new MainPrimary());
|
||||||
var cab = new ConfirmWidget("cab");
|
WidgetContainer.add(Pos.BOTTOM_RIGHT, new SongDisplay());
|
||||||
|
|
||||||
abc.addButton("test", () -> {
|
|
||||||
abc.replace(cab, Pos.CENTER);
|
|
||||||
});
|
|
||||||
|
|
||||||
abc.addButton("test3333", () -> IO.println("Second test works!"));
|
|
||||||
|
|
||||||
cab.addButton("cab321312", () -> IO.println("Third test"));
|
|
||||||
cab.addButton("cab31232132131", () -> {
|
|
||||||
IO.println("Fourth test");
|
|
||||||
});
|
|
||||||
|
|
||||||
WidgetContainer.add(Pos.CENTER, abc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startQuit() {
|
public static void startQuit() {
|
||||||
@@ -87,47 +74,32 @@ public final class App extends Application {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewStack.push(new QuitView());
|
WidgetContainer.add(Pos.CENTER, new QuitPopup());
|
||||||
isQuitting = true;
|
isQuitting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stopQuit() {
|
public static void stopQuit() {
|
||||||
ViewStack.pop();
|
|
||||||
isQuitting = false;
|
isQuitting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void quit() {
|
public static void quit() {
|
||||||
ViewStack.cleanup();
|
|
||||||
stage.close();
|
stage.close();
|
||||||
System.exit(0); // TODO: This is like dropping a nuke
|
System.exit(0); // TODO: This is like dropping a nuke
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reload() {
|
|
||||||
stage.setTitle(AppContext.getString("app-title"));
|
|
||||||
//ViewStack.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setFullscreen(boolean fullscreen) {
|
public static void setFullscreen(boolean fullscreen) {
|
||||||
stage.setFullScreen(fullscreen);
|
stage.setFullScreen(fullscreen);
|
||||||
|
|
||||||
width = (int) stage.getWidth();
|
width = (int)stage.getWidth();
|
||||||
height = (int) stage.getHeight();
|
height = (int)stage.getHeight();
|
||||||
|
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setStyle(String theme, String layoutSize) {
|
public static void setStyle(String theme, String layoutSize) {
|
||||||
final int stylesCount = scene.getStylesheets().size();
|
scene.getStylesheets().clear();
|
||||||
|
|
||||||
for (int i = 0; i < stylesCount; i++) {
|
|
||||||
scene.getStylesheets().removeLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
scene.getStylesheets().add(ResourceManager.<CssAsset>get("general.css").getUrl());
|
scene.getStylesheets().add(ResourceManager.<CssAsset>get("general.css").getUrl());
|
||||||
scene.getStylesheets().add(ResourceManager.<CssAsset>get(theme + ".css").getUrl());
|
scene.getStylesheets().add(ResourceManager.<CssAsset>get(theme + ".css").getUrl());
|
||||||
scene.getStylesheets().add(ResourceManager.<CssAsset>get(layoutSize + ".css").getUrl());
|
scene.getStylesheets().add(ResourceManager.<CssAsset>get(layoutSize + ".css").getUrl());
|
||||||
|
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWidth() {
|
public static int getWidth() {
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
//package org.toop.app;
|
|
||||||
//
|
|
||||||
//public class Quit {
|
|
||||||
// PopupWidget popup;
|
|
||||||
// Quit() {
|
|
||||||
// this.popup = new PopupWidget(
|
|
||||||
// new ConfirmationWidget(
|
|
||||||
// "are-you-sure",
|
|
||||||
// "yes", () -> App.quit(),
|
|
||||||
// "no", () -> popup.pop()
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package org.toop.app.interfaces;
|
|
||||||
|
|
||||||
public interface Popup {
|
|
||||||
void push();
|
|
||||||
void pop();
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package org.toop.app.view.displays;
|
package org.toop.app.view.displays;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.ProgressBar;
|
import javafx.scene.control.ProgressBar;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
import org.toop.framework.audio.AudioEventListener;
|
import org.toop.framework.audio.AudioEventListener;
|
||||||
import org.toop.framework.audio.events.AudioEvents;
|
import org.toop.framework.audio.events.AudioEvents;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
@@ -13,7 +15,7 @@ import javafx.geometry.Pos;
|
|||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import org.toop.framework.eventbus.GlobalEventBus;
|
import org.toop.framework.eventbus.GlobalEventBus;
|
||||||
|
|
||||||
public class SongDisplay extends VBox {
|
public class SongDisplay extends VBox implements Widget {
|
||||||
|
|
||||||
private final Text songTitle;
|
private final Text songTitle;
|
||||||
private final ProgressBar progressBar;
|
private final ProgressBar progressBar;
|
||||||
@@ -107,6 +109,11 @@ public class SongDisplay extends VBox {
|
|||||||
String time = positionMinutes + ":" + positionSecondsStr + " / " + durationMinutes + ":" + durationSecondsStr;
|
String time = positionMinutes + ":" + positionSecondsStr + " / " + durationMinutes + ":" + durationSecondsStr;
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ public final class OptionsView extends View {
|
|||||||
languageCombobox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> {
|
languageCombobox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> {
|
||||||
AppSettings.getSettings().setLocale(newValue.toString());
|
AppSettings.getSettings().setLocale(newValue.toString());
|
||||||
AppContext.setLocale(newValue);
|
AppContext.setLocale(newValue);
|
||||||
App.reload();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
languageCombobox.setConverter(new StringConverter<>() {
|
languageCombobox.setConverter(new StringConverter<>() {
|
||||||
|
|||||||
@@ -1,63 +1,150 @@
|
|||||||
package org.toop.app.widget;
|
package org.toop.app.widget;
|
||||||
|
|
||||||
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ComboBox;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.control.Separator;
|
||||||
|
import javafx.scene.control.Slider;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
public final class Primitive {
|
public final class Primitive {
|
||||||
public static Text header(String label) {
|
public static Text header(String key) {
|
||||||
var header = new Text(label);
|
var header = new Text();
|
||||||
header.getStyleClass().add("header");
|
header.getStyleClass().add("header");
|
||||||
|
|
||||||
|
header.setText(AppContext.getString(key));
|
||||||
|
header.textProperty().bind(AppContext.bindToKey(key));
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Text text(String label) {
|
public static Text text(String key) {
|
||||||
var text = new Text(label);
|
var text = new Text();
|
||||||
text.getStyleClass().add("text");
|
text.getStyleClass().add("text");
|
||||||
|
|
||||||
|
text.setText(AppContext.getString(key));
|
||||||
|
text.textProperty().bind(AppContext.bindToKey(key));
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Button button(String label) {
|
public static Button button(String key, Runnable onAction) {
|
||||||
var button = new Button(label);
|
var button = new Button();
|
||||||
button.getStyleClass().add("button");
|
button.getStyleClass().add("button");
|
||||||
|
|
||||||
|
button.setText(AppContext.getString(key));
|
||||||
|
button.textProperty().bind(AppContext.bindToKey(key));
|
||||||
|
|
||||||
|
if (onAction != null) {
|
||||||
|
button.setOnAction(_ ->
|
||||||
|
onAction.run());
|
||||||
|
}
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextField input() {
|
public static TextField input(String promptKey, String text, Consumer<String> onValueChanged) {
|
||||||
var input = new TextField();
|
var input = new TextField();
|
||||||
input.getStyleClass().add("input");
|
input.getStyleClass().add("input");
|
||||||
|
|
||||||
|
input.setPromptText(AppContext.getString(promptKey));
|
||||||
|
input.promptTextProperty().bind(AppContext.bindToKey(promptKey));
|
||||||
|
|
||||||
|
input.setText(text);
|
||||||
|
|
||||||
|
if (onValueChanged != null) {
|
||||||
|
input.textProperty().addListener((_, _, newValue) ->
|
||||||
|
onValueChanged.accept(newValue));
|
||||||
|
}
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Slider slider() {
|
public static Slider slider(int min, int max, int value, Consumer<Integer> onValueChanged) {
|
||||||
var slider = new Slider();
|
var slider = new Slider();
|
||||||
slider.getStyleClass().add("slider");
|
slider.getStyleClass().add("slider");
|
||||||
|
|
||||||
|
slider.setMin(min);
|
||||||
|
slider.setMax(max);
|
||||||
|
slider.setValue(value);
|
||||||
|
|
||||||
|
if (onValueChanged != null) {
|
||||||
|
slider.valueProperty().addListener((_, _, newValue) ->
|
||||||
|
onValueChanged.accept(newValue.intValue()));
|
||||||
|
}
|
||||||
|
|
||||||
return slider;
|
return slider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ComboBox<T> choice() {
|
@SafeVarargs
|
||||||
|
public static <T> ComboBox<T> choice(StringConverter<T> converter, T value, Consumer<T> onValueChanged, T... items) {
|
||||||
var choice = new ComboBox<T>();
|
var choice = new ComboBox<T>();
|
||||||
choice.getStyleClass().add("choice");
|
choice.getStyleClass().add("choice");
|
||||||
|
|
||||||
|
if (converter != null) {
|
||||||
|
choice.setConverter(converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
choice.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onValueChanged != null) {
|
||||||
|
choice.valueProperty().addListener((_, _, newValue) ->
|
||||||
|
onValueChanged.accept(newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
choice.setItems(FXCollections.observableArrayList(items));
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScrollPane scroll(Node content) {
|
public static ScrollPane scroll(Node content) {
|
||||||
var scroll = new ScrollPane(content);
|
var scroll = new ScrollPane();
|
||||||
scroll.getStyleClass().add("scroll");
|
scroll.getStyleClass().add("scroll");
|
||||||
|
scroll.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
|
||||||
|
scroll.setFitToWidth(true);
|
||||||
|
|
||||||
|
scroll.setContent(content);
|
||||||
|
|
||||||
return scroll;
|
return scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Separator separator() {
|
||||||
|
var separator = new Separator();
|
||||||
|
separator.getStyleClass().add("separator");
|
||||||
|
|
||||||
|
return separator;
|
||||||
|
}
|
||||||
|
|
||||||
public static HBox hbox(Node... nodes) {
|
public static HBox hbox(Node... nodes) {
|
||||||
var hbox = new HBox(nodes);
|
var hbox = new HBox();
|
||||||
hbox.getStyleClass().add("container");
|
hbox.getStyleClass().add("container");
|
||||||
|
hbox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
|
||||||
|
|
||||||
|
hbox.getChildren().addAll(nodes);
|
||||||
|
|
||||||
return hbox;
|
return hbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VBox vbox(Node... nodes) {
|
public static VBox vbox(Node... nodes) {
|
||||||
var vbox = new VBox(nodes);
|
var vbox = new VBox();
|
||||||
vbox.getStyleClass().add("container");
|
vbox.getStyleClass().add("container");
|
||||||
|
vbox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
|
||||||
|
|
||||||
|
vbox.getChildren().addAll(nodes);
|
||||||
|
|
||||||
return vbox;
|
return vbox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,8 @@ package org.toop.app.widget;
|
|||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
public interface Widget<T extends Node> {
|
public interface Widget {
|
||||||
T getNode();
|
Node getNode();
|
||||||
|
|
||||||
default void show(Pos position) {
|
default void show(Pos position) {
|
||||||
WidgetContainer.add(position, this);
|
WidgetContainer.add(position, this);
|
||||||
@@ -14,8 +14,8 @@ public interface Widget<T extends Node> {
|
|||||||
WidgetContainer.remove(this);
|
WidgetContainer.remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void replace(Widget<?> newWidget, Pos newWidgetPosition) {
|
default void replace(Pos position, Widget widget) {
|
||||||
this.hide();
|
widget.show(position);
|
||||||
newWidget.show(newWidgetPosition);
|
hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
package org.toop.app.widget;
|
package org.toop.app.widget;
|
||||||
|
|
||||||
|
import org.toop.app.widget.complex.PopupWidget;
|
||||||
|
import org.toop.app.widget.complex.PrimaryWidget;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
|
||||||
public final class WidgetContainer {
|
public final class WidgetContainer {
|
||||||
|
private static final Deque<PopupWidget> popups = new ArrayDeque<>();
|
||||||
|
|
||||||
private static StackPane root;
|
private static StackPane root;
|
||||||
|
|
||||||
public static StackPane setup() {
|
public static synchronized StackPane setup() {
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
@@ -17,12 +26,45 @@ public final class WidgetContainer {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void add(Pos position, Widget<?> widget) {
|
public static void add(Pos position, Widget widget) {
|
||||||
|
if (root == null || widget == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
if (root.getChildren().contains(widget.getNode())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
StackPane.setAlignment(widget.getNode(), position);
|
StackPane.setAlignment(widget.getNode(), position);
|
||||||
|
|
||||||
|
if (widget instanceof PrimaryWidget) {
|
||||||
|
root.getChildren().addFirst(widget.getNode());
|
||||||
|
} else {
|
||||||
root.getChildren().add(widget.getNode());
|
root.getChildren().add(widget.getNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void remove(Widget<?> widget) {
|
if (widget instanceof PopupWidget popup) {
|
||||||
|
popups.push(popup);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void remove(Widget widget) {
|
||||||
|
if (root == null || widget == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
root.getChildren().remove(widget.getNode());
|
root.getChildren().remove(widget.getNode());
|
||||||
|
|
||||||
|
if (widget instanceof PrimaryWidget) {
|
||||||
|
for (var popup : popups) {
|
||||||
|
root.getChildren().remove(popup.getNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
popups.clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,31 @@
|
|||||||
package org.toop.app.widget.complex;
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
import javafx.scene.layout.HBox;
|
|
||||||
import org.toop.app.widget.Primitive;
|
import org.toop.app.widget.Primitive;
|
||||||
import org.toop.app.widget.Widget;
|
import org.toop.app.widget.Widget;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
public class ConfirmWidget implements Widget<VBox> {
|
public class ConfirmWidget implements Widget {
|
||||||
private final HBox buttonsContainer;
|
private final HBox buttonsContainer;
|
||||||
private final VBox container;
|
private final VBox container;
|
||||||
|
|
||||||
public ConfirmWidget(String confirm) {
|
public ConfirmWidget(String confirm) {
|
||||||
buttonsContainer = Primitive.hbox();
|
buttonsContainer = Primitive.hbox();
|
||||||
container = Primitive.vbox(Primitive.text(confirm), buttonsContainer);
|
container = Primitive.vbox(Primitive.header(confirm), buttonsContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addButton(String label, Runnable onClick) {
|
public void addButton(String key, Runnable onClick) {
|
||||||
var button = Primitive.button(label);
|
Platform.runLater(() -> {
|
||||||
button.setOnAction(_ -> onClick.run());
|
var button = Primitive.button(key, onClick);
|
||||||
buttonsContainer.getChildren().add(button);
|
buttonsContainer.getChildren().add(button);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VBox getNode() { return container; }
|
public Node getNode() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.ComboBox;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
|
public class LabeledChoiceWidget<T> implements Widget {
|
||||||
|
private final ComboBox<T> comboBox;
|
||||||
|
private final VBox container;
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public LabeledChoiceWidget(
|
||||||
|
String key,
|
||||||
|
StringConverter<T> converter,
|
||||||
|
T initialValue,
|
||||||
|
Consumer<T> onValueChanged,
|
||||||
|
T... items
|
||||||
|
) {
|
||||||
|
var label = Primitive.text(key);
|
||||||
|
comboBox = Primitive.choice(converter, initialValue, onValueChanged, items);
|
||||||
|
container = Primitive.vbox(label, comboBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getValue() {
|
||||||
|
return comboBox.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(T value) {
|
||||||
|
comboBox.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
public class LabeledInputWidget implements Widget {
|
||||||
|
private final TextField input;
|
||||||
|
private final VBox container;
|
||||||
|
|
||||||
|
public LabeledInputWidget(String key, String promptKey, String initialText, Consumer<String> onValueChanged) {
|
||||||
|
var label = Primitive.text(key);
|
||||||
|
input = Primitive.input(promptKey, initialText, onValueChanged);
|
||||||
|
container = Primitive.vbox(label, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return input.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String text) {
|
||||||
|
input.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Slider;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
|
||||||
|
public class LabeledSliderWidget implements Widget {
|
||||||
|
private final Slider slider;
|
||||||
|
private final Text labelValue;
|
||||||
|
private final VBox container;
|
||||||
|
|
||||||
|
public LabeledSliderWidget(String key, int min, int max, int value, Consumer<Integer> onValueChanged) {
|
||||||
|
var label = Primitive.text(key);
|
||||||
|
|
||||||
|
labelValue = new Text(String.valueOf(value));
|
||||||
|
labelValue.getStyleClass().add("text");
|
||||||
|
|
||||||
|
slider = Primitive.slider(min, max, value, newValue -> {
|
||||||
|
labelValue.setText(String.valueOf(newValue));
|
||||||
|
|
||||||
|
if (onValueChanged != null) {
|
||||||
|
onValueChanged.accept(newValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var sliderRow = Primitive.hbox(slider, labelValue);
|
||||||
|
container = Primitive.vbox(label, sliderRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return (int)slider.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(int newValue) {
|
||||||
|
slider.setValue(newValue);
|
||||||
|
labelValue.setText(String.valueOf(newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
package org.toop.app.widget.complex;
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
import org.toop.app.interfaces.Popup;
|
public abstract class PopupWidget extends StackWidget {
|
||||||
import org.toop.app.widget.WidgetContainer;
|
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
|
||||||
|
|
||||||
public abstract class PopupWidget extends ViewWidget implements Popup {
|
|
||||||
public PopupWidget() {
|
public PopupWidget() {
|
||||||
super("bg-popup");
|
super("bg-popup");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void push() {
|
|
||||||
WidgetContainer.add(Pos.CENTER, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pop() {
|
|
||||||
WidgetContainer.remove(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,43 @@
|
|||||||
package org.toop.app.widget.complex;
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import org.toop.app.widget.WidgetContainer;
|
import org.toop.app.widget.Primitive;
|
||||||
|
|
||||||
|
public abstract class PrimaryWidget extends StackWidget {
|
||||||
|
private PrimaryWidget previous = null;
|
||||||
|
|
||||||
public abstract class PrimaryWidget extends ViewWidget implements TransitionAnimation {
|
|
||||||
public PrimaryWidget() {
|
public PrimaryWidget() {
|
||||||
super("bg-primary");
|
super("bg-primary");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void transitionNext(PrimaryWidget primary) {
|
||||||
public void transition(PrimaryWidget primary) {
|
primary.previous = this;
|
||||||
WidgetContainer.add(Pos.CENTER, primary);
|
replace(Pos.CENTER, primary);
|
||||||
WidgetContainer.remove(this);
|
|
||||||
|
var backButton = Primitive.button("back", () -> {
|
||||||
|
primary.transitionPrevious();
|
||||||
|
});
|
||||||
|
|
||||||
|
primary.add(Pos.BOTTOM_LEFT, Primitive.vbox(backButton));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transitionPrevious() {
|
||||||
|
if (previous == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace(Pos.CENTER, previous);
|
||||||
|
previous = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload(PrimaryWidget primary) {
|
||||||
|
primary.previous = previous;
|
||||||
|
replace(Pos.CENTER, primary);
|
||||||
|
|
||||||
|
var backButton = Primitive.button("back", () -> {
|
||||||
|
primary.transitionPrevious();
|
||||||
|
});
|
||||||
|
|
||||||
|
primary.add(Pos.BOTTOM_LEFT, Primitive.vbox(backButton));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
|
||||||
|
public abstract class StackWidget implements Widget {
|
||||||
|
private final StackPane container;
|
||||||
|
|
||||||
|
public StackWidget(String cssClass) {
|
||||||
|
container = new StackPane();
|
||||||
|
container.getStyleClass().add(cssClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Pos position, Node node) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
if (container.getChildren().contains(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackPane.setAlignment(node, position);
|
||||||
|
container.getChildren().add(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Pos position, Widget widget) {
|
||||||
|
add(position, widget.getNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Node node) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
container.getChildren().remove(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Widget widget) {
|
||||||
|
remove(widget.getNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package org.toop.app.widget.complex;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
public class ToggleWidget implements Widget {
|
||||||
|
private final Button button;
|
||||||
|
private final VBox container;
|
||||||
|
|
||||||
|
private final String onKey;
|
||||||
|
private final String offKey;
|
||||||
|
|
||||||
|
private boolean state;
|
||||||
|
|
||||||
|
public ToggleWidget(String onKey, String offKey, boolean initialState, Consumer<Boolean> onToggle) {
|
||||||
|
this.onKey = onKey;
|
||||||
|
this.offKey = offKey;
|
||||||
|
this.state = initialState;
|
||||||
|
|
||||||
|
button = new Button(AppContext.getString(getCurrentKey()));
|
||||||
|
button.setOnAction(_ -> {
|
||||||
|
state = !state;
|
||||||
|
updateText();
|
||||||
|
if (onToggle != null) {
|
||||||
|
onToggle.accept(state);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
container = Primitive.vbox(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCurrentKey() {
|
||||||
|
return state? offKey : onKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateText() {
|
||||||
|
button.setText(AppContext.getString(getCurrentKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(boolean newState) {
|
||||||
|
if (state != newState) {
|
||||||
|
state = newState;
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package org.toop.app.widget.complex;
|
|
||||||
|
|
||||||
public interface TransitionAnimation {
|
|
||||||
void transition(PrimaryWidget primary);
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package org.toop.app.widget.complex;
|
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import org.toop.app.widget.Widget;
|
|
||||||
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
|
|
||||||
public abstract class ViewWidget implements Widget<StackPane> {
|
|
||||||
private final StackPane container;
|
|
||||||
|
|
||||||
public ViewWidget(String cssClass) {
|
|
||||||
container = new StackPane();
|
|
||||||
container.getStyleClass().add(cssClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(Pos position, Widget<?> widget) {
|
|
||||||
StackPane.setAlignment(widget.getNode(), position);
|
|
||||||
container.getChildren().add(widget.getNode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StackPane getNode() {
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void reload();
|
|
||||||
}
|
|
||||||
117
app/src/main/java/org/toop/app/widget/display/SongDisplay.java
Normal file
117
app/src/main/java/org/toop/app/widget/display/SongDisplay.java
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
package org.toop.app.widget.display;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Widget;
|
||||||
|
import org.toop.framework.audio.events.AudioEvents;
|
||||||
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
|
import org.toop.framework.eventbus.GlobalEventBus;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ProgressBar;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
|
||||||
|
public class SongDisplay extends VBox implements Widget {
|
||||||
|
private final Text songTitle;
|
||||||
|
private final ProgressBar progressBar;
|
||||||
|
private final Text progressText;
|
||||||
|
|
||||||
|
public SongDisplay() {
|
||||||
|
new EventFlow()
|
||||||
|
.listen(this::updateTheSong);
|
||||||
|
|
||||||
|
setAlignment(Pos.CENTER);
|
||||||
|
setMaxHeight(Region.USE_PREF_SIZE);
|
||||||
|
getStyleClass().add("song-display");
|
||||||
|
|
||||||
|
// TODO ADD GOOD SONG TITLES WITH ARTISTS DISPLAYED
|
||||||
|
songTitle = new Text("song playing");
|
||||||
|
songTitle.getStyleClass().add("song-title");
|
||||||
|
|
||||||
|
progressBar = new ProgressBar(0);
|
||||||
|
progressBar.getStyleClass().add("progress-bar");
|
||||||
|
|
||||||
|
progressText = new Text("0:00/0:00");
|
||||||
|
progressText.getStyleClass().add("progress-text");
|
||||||
|
|
||||||
|
// TODO ADD BETTER CSS FOR THE SKIPBUTTON WHERE ITS AT A NICER POSITION
|
||||||
|
|
||||||
|
Button skipButton = new Button(">>");
|
||||||
|
Button pauseButton = new Button("⏸");
|
||||||
|
Button previousButton = new Button("<<");
|
||||||
|
|
||||||
|
skipButton.getStyleClass().setAll("skip-button");
|
||||||
|
pauseButton.getStyleClass().setAll("pause-button");
|
||||||
|
previousButton.getStyleClass().setAll("previous-button");
|
||||||
|
|
||||||
|
skipButton.setOnAction( event -> {
|
||||||
|
GlobalEventBus.post(new AudioEvents.SkipMusic());
|
||||||
|
});
|
||||||
|
|
||||||
|
pauseButton.setOnAction(event -> {
|
||||||
|
GlobalEventBus.post(new AudioEvents.PauseMusic());
|
||||||
|
if (pauseButton.getText().equals("⏸")) {
|
||||||
|
pauseButton.setText("▶");
|
||||||
|
}
|
||||||
|
else if (pauseButton.getText().equals("▶")) {
|
||||||
|
pauseButton.setText("⏸");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
previousButton.setOnAction( event -> {
|
||||||
|
GlobalEventBus.post(new AudioEvents.PreviousMusic());
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox control = new HBox(10, previousButton, pauseButton, skipButton);
|
||||||
|
control.setAlignment(Pos.CENTER);
|
||||||
|
control.getStyleClass().add("controls");
|
||||||
|
|
||||||
|
getChildren().addAll(songTitle, progressBar, progressText, control);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTheSong(AudioEvents.PlayingMusic event) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
String text = event.name();
|
||||||
|
text = text.substring(0, text.length() - 4);
|
||||||
|
songTitle.setText(text);
|
||||||
|
double currentPos = event.currentPosition();
|
||||||
|
double duration = event.duration();
|
||||||
|
if (currentPos / duration > 0.05) {
|
||||||
|
double progress = currentPos / duration;
|
||||||
|
progressBar.setProgress(progress);
|
||||||
|
}
|
||||||
|
else if (currentPos / duration < 0.05) {
|
||||||
|
progressBar.setProgress(0.05);
|
||||||
|
}
|
||||||
|
progressText.setText(getTimeString(event.currentPosition(), event.duration()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTimeString(long position, long duration) {
|
||||||
|
long positionMinutes = position / 60;
|
||||||
|
long durationMinutes = duration / 60;
|
||||||
|
long positionSeconds = position % 60;
|
||||||
|
long durationSeconds = duration % 60;
|
||||||
|
String positionSecondsStr = String.valueOf(positionSeconds);
|
||||||
|
String durationSecondsStr = String.valueOf(durationSeconds);
|
||||||
|
|
||||||
|
if (positionSeconds < 10) {
|
||||||
|
positionSecondsStr = "0" + positionSeconds;
|
||||||
|
}
|
||||||
|
if (durationSeconds < 10) {
|
||||||
|
durationSecondsStr = "0" + durationSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
String time = positionMinutes + ":" + positionSecondsStr + " / " + durationMinutes + ":" + durationSecondsStr;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getNode() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/src/main/java/org/toop/app/widget/popup/QuitPopup.java
Normal file
24
app/src/main/java/org/toop/app/widget/popup/QuitPopup.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package org.toop.app.widget.popup;
|
||||||
|
|
||||||
|
import org.toop.app.App;
|
||||||
|
import org.toop.app.widget.complex.ConfirmWidget;
|
||||||
|
import org.toop.app.widget.complex.PopupWidget;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
|
||||||
|
public class QuitPopup extends PopupWidget {
|
||||||
|
public QuitPopup() {
|
||||||
|
var confirmWidget = new ConfirmWidget("are-you-sure");
|
||||||
|
|
||||||
|
confirmWidget.addButton("yes", () -> {
|
||||||
|
App.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
confirmWidget.addButton("no", () -> {
|
||||||
|
App.stopQuit();
|
||||||
|
hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
add(Pos.CENTER, confirmWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.toop.app.widget.primary;
|
||||||
|
|
||||||
|
import org.toop.app.App;
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.complex.PrimaryWidget;
|
||||||
|
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.KeyValue;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
|
||||||
|
public class CreditsPrimary extends PrimaryWidget {
|
||||||
|
public CreditsPrimary() {
|
||||||
|
var scrumMasterCredit = newCredit("scrum-master", "Stef");
|
||||||
|
var productOwnerCredit = newCredit("product-owner", "Omar");
|
||||||
|
var mergeCommanderCredit = newCredit("merge-commander", "Bas");
|
||||||
|
var localizationCredit = newCredit("localization", "Ticho");
|
||||||
|
var aiCredit = newCredit("ai", "Michiel");
|
||||||
|
var developersCredit = newCredit("developers", "Michiel, Bas, Stef, Omar, Ticho");
|
||||||
|
var moralSupportCredit = newCredit("moral-support", "Wesley");
|
||||||
|
var openglCredit = newCredit("opengl", "Omar");
|
||||||
|
|
||||||
|
var topSpacer = new Region();
|
||||||
|
topSpacer.setPrefHeight(App.getHeight());
|
||||||
|
|
||||||
|
var bottomSpacer = new Region();
|
||||||
|
bottomSpacer.setPrefHeight(App.getHeight());
|
||||||
|
|
||||||
|
var creditsContainer = Primitive.vbox(
|
||||||
|
topSpacer,
|
||||||
|
|
||||||
|
scrumMasterCredit,
|
||||||
|
productOwnerCredit,
|
||||||
|
mergeCommanderCredit,
|
||||||
|
localizationCredit,
|
||||||
|
aiCredit,
|
||||||
|
developersCredit,
|
||||||
|
moralSupportCredit,
|
||||||
|
openglCredit,
|
||||||
|
|
||||||
|
bottomSpacer
|
||||||
|
);
|
||||||
|
|
||||||
|
var creditsScroll = Primitive.scroll(creditsContainer);
|
||||||
|
|
||||||
|
creditsScroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||||
|
creditsScroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||||
|
|
||||||
|
add(Pos.CENTER, creditsScroll);
|
||||||
|
|
||||||
|
animate(creditsScroll, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HBox newCredit(String key, String other) {
|
||||||
|
var credit = new Text(": " + other);
|
||||||
|
credit.getStyleClass().add("header");
|
||||||
|
|
||||||
|
var creditBox = Primitive.hbox(
|
||||||
|
Primitive.header(key),
|
||||||
|
credit
|
||||||
|
);
|
||||||
|
|
||||||
|
creditBox.setPrefHeight(App.getHeight() / 3.0);
|
||||||
|
return creditBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animate(ScrollPane scroll, int length) {
|
||||||
|
final Timeline timeline = new Timeline(
|
||||||
|
new KeyFrame(Duration.seconds(0), new KeyValue(scroll.vvalueProperty(), 0.0)),
|
||||||
|
new KeyFrame(Duration.seconds(length), new KeyValue(scroll.vvalueProperty(), 1.0))
|
||||||
|
);
|
||||||
|
|
||||||
|
timeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
|
timeline.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.toop.app.widget.primary;
|
||||||
|
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.complex.PrimaryWidget;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
|
||||||
|
public class LocalPrimary extends PrimaryWidget {
|
||||||
|
public LocalPrimary() {
|
||||||
|
var ticTacToeButton = Primitive.button("tic-tac-toe", () -> {
|
||||||
|
});
|
||||||
|
|
||||||
|
var reversiButton = Primitive.button("reversi", () -> {
|
||||||
|
});
|
||||||
|
|
||||||
|
var connect4Button = Primitive.button("connect4", () -> {
|
||||||
|
});
|
||||||
|
|
||||||
|
add(Pos.CENTER, Primitive.vbox(
|
||||||
|
ticTacToeButton,
|
||||||
|
reversiButton,
|
||||||
|
connect4Button
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.toop.app.widget.primary;
|
||||||
|
|
||||||
|
import org.toop.app.App;
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.complex.PrimaryWidget;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
|
||||||
|
public class MainPrimary extends PrimaryWidget {
|
||||||
|
public MainPrimary() {
|
||||||
|
var localButton = Primitive.button("local", () -> {
|
||||||
|
transitionNext(new LocalPrimary());
|
||||||
|
});
|
||||||
|
|
||||||
|
var onlineButton = Primitive.button("online", () -> {
|
||||||
|
transitionNext(new OnlinePrimary());
|
||||||
|
});
|
||||||
|
|
||||||
|
var creditsButton = Primitive.button("credits", () -> {
|
||||||
|
transitionNext(new CreditsPrimary());
|
||||||
|
});
|
||||||
|
|
||||||
|
var optionsButton = Primitive.button("options", () -> {
|
||||||
|
transitionNext(new OptionsPrimary());
|
||||||
|
});
|
||||||
|
|
||||||
|
var quitButton = Primitive.button("quit", () -> {
|
||||||
|
App.startQuit();
|
||||||
|
});
|
||||||
|
|
||||||
|
add(Pos.CENTER, Primitive.vbox(
|
||||||
|
localButton,
|
||||||
|
onlineButton,
|
||||||
|
creditsButton,
|
||||||
|
optionsButton,
|
||||||
|
quitButton
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.toop.app.widget.primary;
|
||||||
|
|
||||||
|
import org.toop.app.Server;
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.complex.LabeledInputWidget;
|
||||||
|
import org.toop.app.widget.complex.PrimaryWidget;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
|
||||||
|
public class OnlinePrimary extends PrimaryWidget {
|
||||||
|
public OnlinePrimary() {
|
||||||
|
var serverInformationHeader = Primitive.header("server-information");
|
||||||
|
|
||||||
|
var serverIPInput = new LabeledInputWidget("ip-address", "enter-the-server-ip", "", _ -> {});
|
||||||
|
var serverPortInput = new LabeledInputWidget("port", "enter-the-server-port", "", _ -> {});
|
||||||
|
var playerNameInput = new LabeledInputWidget("player-name", "enter-your-name", "", _ -> {});
|
||||||
|
|
||||||
|
var connectButton = Primitive.button("connect", () -> {
|
||||||
|
new Server(
|
||||||
|
serverIPInput.getValue(),
|
||||||
|
serverPortInput.getValue(),
|
||||||
|
playerNameInput.getValue()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
add(Pos.CENTER, Primitive.vbox(
|
||||||
|
serverInformationHeader,
|
||||||
|
Primitive.separator(),
|
||||||
|
|
||||||
|
serverIPInput.getNode(),
|
||||||
|
serverPortInput.getNode(),
|
||||||
|
playerNameInput.getNode(),
|
||||||
|
Primitive.separator(),
|
||||||
|
|
||||||
|
connectButton
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
package org.toop.app.widget.primary;
|
||||||
|
|
||||||
|
import org.toop.app.App;
|
||||||
|
import org.toop.app.widget.Primitive;
|
||||||
|
import org.toop.app.widget.complex.LabeledChoiceWidget;
|
||||||
|
import org.toop.app.widget.complex.LabeledSliderWidget;
|
||||||
|
import org.toop.app.widget.complex.PrimaryWidget;
|
||||||
|
import org.toop.app.widget.complex.ToggleWidget;
|
||||||
|
import org.toop.framework.audio.VolumeControl;
|
||||||
|
import org.toop.framework.audio.events.AudioEvents;
|
||||||
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
|
import org.toop.local.AppContext;
|
||||||
|
import org.toop.local.AppSettings;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
|
public class OptionsPrimary extends PrimaryWidget {
|
||||||
|
public OptionsPrimary() {
|
||||||
|
add(Pos.CENTER, Primitive.hbox(
|
||||||
|
generalSection(),
|
||||||
|
volumeSection(),
|
||||||
|
styleSection()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox generalSection() {
|
||||||
|
var languageWidget = new LabeledChoiceWidget<>(
|
||||||
|
"language",
|
||||||
|
new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(Locale locale) {
|
||||||
|
return AppContext.getString(locale.getDisplayName().toLowerCase());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Locale fromString(String s) { return null; }
|
||||||
|
},
|
||||||
|
AppContext.getLocale(),
|
||||||
|
newLocale -> {
|
||||||
|
AppSettings.getSettings().setLocale(newLocale.toString());
|
||||||
|
AppContext.setLocale(newLocale);
|
||||||
|
reload(new OptionsPrimary());
|
||||||
|
},
|
||||||
|
AppContext.getLocalization().getAvailableLocales().toArray(new Locale[0])
|
||||||
|
);
|
||||||
|
|
||||||
|
var fullscreenToggle = new ToggleWidget(
|
||||||
|
"fullscreen", "windowed",
|
||||||
|
AppSettings.getSettings().getFullscreen(),
|
||||||
|
fullscreen -> {
|
||||||
|
AppSettings.getSettings().setFullscreen(fullscreen);
|
||||||
|
App.setFullscreen(fullscreen);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Primitive.vbox(
|
||||||
|
Primitive.header("general"),
|
||||||
|
Primitive.separator(),
|
||||||
|
|
||||||
|
languageWidget.getNode(),
|
||||||
|
fullscreenToggle.getNode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox volumeSection() {
|
||||||
|
var masterVolumeWidget = new LabeledSliderWidget(
|
||||||
|
"master-volume",
|
||||||
|
0, 100,
|
||||||
|
AppSettings.getSettings().getVolume(),
|
||||||
|
val -> {
|
||||||
|
AppSettings.getSettings().setVolume(val);
|
||||||
|
new EventFlow()
|
||||||
|
.addPostEvent(new AudioEvents.ChangeVolume(val, VolumeControl.MASTERVOLUME))
|
||||||
|
.asyncPostEvent();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var effectsVolumeWidget = new LabeledSliderWidget(
|
||||||
|
"effects-volume",
|
||||||
|
0, 100,
|
||||||
|
AppSettings.getSettings().getFxVolume(),
|
||||||
|
val -> {
|
||||||
|
AppSettings.getSettings().setFxVolume(val);
|
||||||
|
new EventFlow()
|
||||||
|
.addPostEvent(new AudioEvents.ChangeVolume(val, VolumeControl.FX))
|
||||||
|
.asyncPostEvent();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var musicVolumeWidget = new LabeledSliderWidget(
|
||||||
|
"music-volume",
|
||||||
|
0, 100,
|
||||||
|
AppSettings.getSettings().getMusicVolume(),
|
||||||
|
val -> {
|
||||||
|
AppSettings.getSettings().setMusicVolume(val);
|
||||||
|
new EventFlow()
|
||||||
|
.addPostEvent(new AudioEvents.ChangeVolume(val, VolumeControl.MUSIC))
|
||||||
|
.asyncPostEvent();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Primitive.vbox(
|
||||||
|
Primitive.header("volume"),
|
||||||
|
Primitive.separator(),
|
||||||
|
|
||||||
|
masterVolumeWidget.getNode(),
|
||||||
|
effectsVolumeWidget.getNode(),
|
||||||
|
musicVolumeWidget.getNode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox styleSection() {
|
||||||
|
var themeWidget = new LabeledChoiceWidget<>(
|
||||||
|
"theme",
|
||||||
|
new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(String theme) {
|
||||||
|
return AppContext.getString(theme);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String fromString(String s) { return null; }
|
||||||
|
},
|
||||||
|
AppSettings.getSettings().getTheme(),
|
||||||
|
newTheme -> {
|
||||||
|
AppSettings.getSettings().setTheme(newTheme);
|
||||||
|
App.setStyle(newTheme, AppSettings.getSettings().getLayoutSize());
|
||||||
|
},
|
||||||
|
"dark", "light", "high-contrast"
|
||||||
|
);
|
||||||
|
|
||||||
|
var layoutWidget = new LabeledChoiceWidget<>(
|
||||||
|
"layout-size",
|
||||||
|
new StringConverter<>() {
|
||||||
|
@Override
|
||||||
|
public String toString(String layout) {
|
||||||
|
return AppContext.getString(layout);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String fromString(String s) { return null; }
|
||||||
|
},
|
||||||
|
AppSettings.getSettings().getLayoutSize(),
|
||||||
|
newLayout -> {
|
||||||
|
AppSettings.getSettings().setLayoutSize(newLayout);
|
||||||
|
App.setStyle(AppSettings.getSettings().getTheme(), newLayout);
|
||||||
|
},
|
||||||
|
"small", "medium", "large"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return Primitive.vbox(
|
||||||
|
Primitive.header("style"),
|
||||||
|
Primitive.separator(),
|
||||||
|
|
||||||
|
themeWidget.getNode(),
|
||||||
|
layoutWidget.getNode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package org.toop.app.widget.simple;
|
|
||||||
|
|
||||||
import org.toop.app.widget.Widget;
|
|
||||||
|
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
import javafx.scene.text.Text;
|
|
||||||
|
|
||||||
public class LabeledButtonWidget extends VBox implements Widget<VBox> {
|
|
||||||
public LabeledButtonWidget(
|
|
||||||
String labelText,
|
|
||||||
String buttonText, Runnable buttonOnAction
|
|
||||||
) {
|
|
||||||
var text = new Text(labelText);
|
|
||||||
|
|
||||||
var button = new Button(buttonText);
|
|
||||||
button.setOnAction(_ -> buttonOnAction.run());
|
|
||||||
|
|
||||||
super(text, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VBox getNode() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
package org.toop.app.widget.view;
|
|
||||||
|
|
||||||
public class MainView {
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package org.toop.app.widget.view;
|
|
||||||
|
|
||||||
import org.toop.app.widget.complex.PopupWidget;
|
|
||||||
|
|
||||||
public class QuitView extends PopupWidget {
|
|
||||||
protected QuitView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reload() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,28 @@
|
|||||||
package org.toop.local;
|
package org.toop.local;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import org.toop.framework.resource.ResourceManager;
|
import org.toop.framework.resource.ResourceManager;
|
||||||
import org.toop.framework.resource.resources.LocalizationAsset;
|
import org.toop.framework.resource.resources.LocalizationAsset;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.binding.StringBinding;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
|
||||||
public class AppContext {
|
public class AppContext {
|
||||||
private static final LocalizationAsset localization = ResourceManager.get("localization");
|
private static final LocalizationAsset localization = ResourceManager.get("localization");
|
||||||
private static Locale locale = Locale.forLanguageTag("en");
|
private static Locale locale = Locale.forLanguageTag("en");
|
||||||
|
|
||||||
|
private static final ObjectProperty<Locale> localeProperty = new SimpleObjectProperty<>(locale);
|
||||||
|
|
||||||
public static LocalizationAsset getLocalization() {
|
public static LocalizationAsset getLocalization() {
|
||||||
return localization;
|
return localization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setLocale(Locale locale) {
|
public static void setLocale(Locale locale) {
|
||||||
AppContext.locale = locale;
|
AppContext.locale = locale;
|
||||||
|
localeProperty.set(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Locale getLocale() {
|
public static Locale getLocale() {
|
||||||
@@ -21,7 +30,13 @@ public class AppContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getString(String key) {
|
public static String getString(String key) {
|
||||||
assert localization != null;
|
|
||||||
return localization.getString(key, locale);
|
return localization.getString(key, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StringBinding bindToKey(String key) {
|
||||||
|
return Bindings.createStringBinding(
|
||||||
|
() -> localization.getString(key, locale),
|
||||||
|
localeProperty
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,36 +3,35 @@
|
|||||||
-fx-padding: 0;
|
-fx-padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container,
|
.container {
|
||||||
.credits-container {
|
|
||||||
-fx-alignment: TOP_CENTER;
|
-fx-alignment: TOP_CENTER;
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fit,
|
.scroll,
|
||||||
.fit .viewport {
|
.scroll .viewport {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-border-color: transparent;
|
-fx-border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fit .scroll-bar .decrement-arrow,
|
.scroll .scroll-bar .decrement-arrow,
|
||||||
.fit .scroll-bar .decrement-button,
|
.scroll .scroll-bar .decrement-button,
|
||||||
.fit .scroll-bar .increment-arrow,
|
.scroll .scroll-bar .increment-arrow,
|
||||||
.fit .scroll-bar .increment-button {
|
.scroll .scroll-bar .increment-button {
|
||||||
-fx-padding: 0;
|
-fx-padding: 0;
|
||||||
-fx-pref-height: 0;
|
-fx-pref-height: 0;
|
||||||
-fx-pref-width: 0;
|
-fx-pref-width: 0;
|
||||||
-fx-shape: "";
|
-fx-shape: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
.fit .scroll-bar .thumb {
|
.scroll .scroll-bar .thumb {
|
||||||
-fx-background-color: #888;
|
-fx-background-color: #888;
|
||||||
-fx-background-insets: 0;
|
-fx-background-insets: 0;
|
||||||
-fx-background-radius: 1px;
|
-fx-background-radius: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fit .scroll-bar:horizontal,
|
.scroll .scroll-bar:horizontal,
|
||||||
.fit .scroll-bar:vertical {
|
.scroll .scroll-bar:vertical {
|
||||||
-fx-pref-height: 4px;
|
-fx-pref-height: 4px;
|
||||||
-fx-pref-width: 4px;
|
-fx-pref-width: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user