update shell
This commit is contained in:
parent
f3eb114359
commit
824a39436a
@ -4,7 +4,7 @@ import javafx.application.Application;
|
|||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import p.studio.utilities.i18n.I18n;
|
import p.studio.utilities.i18n.I18n;
|
||||||
import p.studio.window.MainView;
|
import p.studio.window.StudioRootView;
|
||||||
|
|
||||||
public class App extends Application {
|
public class App extends Application {
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ public class App extends Application {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage stage) {
|
public void start(Stage stage) {
|
||||||
var root = new MainView();
|
var root = new StudioRootView();
|
||||||
var scene = new Scene(root, 1200, 800);
|
var scene = new Scene(root, 1200, 800);
|
||||||
|
|
||||||
scene.getStylesheets().add(Container.theme().getDefaultTheme());
|
scene.getStylesheets().add(Container.theme().getDefaultTheme());
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
package p.studio.events;
|
||||||
|
|
||||||
|
import p.studio.projects.ProjectReference;
|
||||||
|
|
||||||
|
public record StudioProjectCreatedEvent(ProjectReference project) implements StudioEvent {
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
package p.studio.events;
|
||||||
|
|
||||||
|
import p.studio.projects.ProjectReference;
|
||||||
|
|
||||||
|
public record StudioProjectOpenedEvent(ProjectReference project) implements StudioEvent {
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
package p.studio.projects;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ProjectCatalogService {
|
||||||
|
private final Path projectsRoot;
|
||||||
|
|
||||||
|
public ProjectCatalogService(Path projectsRoot) {
|
||||||
|
this.projectsRoot = Objects.requireNonNull(projectsRoot, "projectsRoot").toAbsolutePath().normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path projectsRoot() {
|
||||||
|
return projectsRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProjectReference> listProjects() {
|
||||||
|
if (!Files.isDirectory(projectsRoot)) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Stream<Path> children = Files.list(projectsRoot)) {
|
||||||
|
return children
|
||||||
|
.filter(Files::isDirectory)
|
||||||
|
.map(path -> new ProjectReference(path.getFileName().toString(), path))
|
||||||
|
.sorted(Comparator.comparing(ProjectReference::name, String.CASE_INSENSITIVE_ORDER))
|
||||||
|
.toList();
|
||||||
|
} catch (IOException ioException) {
|
||||||
|
throw new UncheckedIOException(ioException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectReference openProject(Path projectPath) {
|
||||||
|
final Path normalized = Objects.requireNonNull(projectPath, "projectPath").toAbsolutePath().normalize();
|
||||||
|
if (!Files.isDirectory(normalized)) {
|
||||||
|
throw new IllegalArgumentException("project directory does not exist: " + normalized);
|
||||||
|
}
|
||||||
|
return new ProjectReference(normalized.getFileName().toString(), normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectReference createProject(String projectName) {
|
||||||
|
final String sanitized = sanitizeProjectName(projectName);
|
||||||
|
if (sanitized.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("project name must not be blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Path projectRoot = projectsRoot.resolve(sanitized).normalize();
|
||||||
|
if (Files.exists(projectRoot)) {
|
||||||
|
throw new IllegalArgumentException("project already exists: " + sanitized);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.createDirectories(projectRoot.resolve(".workspace"));
|
||||||
|
Files.createDirectories(projectRoot.resolve("src"));
|
||||||
|
Files.createDirectories(projectRoot.resolve("build"));
|
||||||
|
Files.createDirectories(projectRoot.resolve("cartridge"));
|
||||||
|
} catch (IOException ioException) {
|
||||||
|
throw new UncheckedIOException(ioException);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProjectReference(sanitized, projectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sanitizeProjectName(String rawName) {
|
||||||
|
final String normalized = Objects.requireNonNull(rawName, "rawName")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase(Locale.ROOT)
|
||||||
|
.replaceAll("[^a-z0-9]+", "-")
|
||||||
|
.replaceAll("^-+", "")
|
||||||
|
.replaceAll("-+$", "");
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package p.studio.projects;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public record ProjectReference(String name, Path rootPath) {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,6 +16,14 @@ public enum I18n {
|
|||||||
|
|
||||||
SHELL_ACTIVITY("shell.activity"),
|
SHELL_ACTIVITY("shell.activity"),
|
||||||
|
|
||||||
|
LAUNCHER_TITLE("launcher.title"),
|
||||||
|
LAUNCHER_SUBTITLE("launcher.subtitle"),
|
||||||
|
LAUNCHER_EXISTING_PROJECTS("launcher.existingProjects"),
|
||||||
|
LAUNCHER_OPEN_PROJECT("launcher.openProject"),
|
||||||
|
LAUNCHER_CREATE_PROJECT("launcher.createProject"),
|
||||||
|
LAUNCHER_PROJECT_NAME_PROMPT("launcher.projectNamePrompt"),
|
||||||
|
LAUNCHER_CREATE_BUTTON("launcher.createButton"),
|
||||||
|
|
||||||
TOOLBAR_PLAY("toolbar.play"),
|
TOOLBAR_PLAY("toolbar.play"),
|
||||||
TOOLBAR_STOP("toolbar.stop"),
|
TOOLBAR_STOP("toolbar.stop"),
|
||||||
TOOLBAR_EXPORT("toolbar.export"),
|
TOOLBAR_EXPORT("toolbar.export"),
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import javafx.scene.layout.BorderPane;
|
|||||||
import p.studio.Container;
|
import p.studio.Container;
|
||||||
import p.studio.controls.shell.*;
|
import p.studio.controls.shell.*;
|
||||||
import p.studio.events.StudioWorkspaceSelectedEvent;
|
import p.studio.events.StudioWorkspaceSelectedEvent;
|
||||||
|
import p.studio.projects.ProjectReference;
|
||||||
import p.studio.utilities.i18n.I18n;
|
import p.studio.utilities.i18n.I18n;
|
||||||
import p.studio.workspaces.PlaceholderWorkspace;
|
import p.studio.workspaces.PlaceholderWorkspace;
|
||||||
import p.studio.workspaces.WorkspaceHost;
|
import p.studio.workspaces.WorkspaceHost;
|
||||||
@ -14,17 +15,19 @@ import p.studio.workspaces.editor.EditorWorkspace;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class MainView extends BorderPane {
|
public final class MainView extends BorderPane {
|
||||||
private static final WorkspaceHost HOST = new WorkspaceHost();
|
private final WorkspaceHost host = new WorkspaceHost();
|
||||||
|
private final ProjectReference projectReference;
|
||||||
|
|
||||||
public MainView() {
|
public MainView(ProjectReference projectReference) {
|
||||||
|
this.projectReference = projectReference;
|
||||||
final var menuBar = new StudioShellMenuBarControl();
|
final var menuBar = new StudioShellMenuBarControl();
|
||||||
final var runSurface = new StudioRunSurfaceControl();
|
final var runSurface = new StudioRunSurfaceControl();
|
||||||
setTop(new StudioShellTopBarControl(menuBar, runSurface));
|
setTop(new StudioShellTopBarControl(menuBar, runSurface));
|
||||||
|
|
||||||
HOST.register(new EditorWorkspace());
|
host.register(new EditorWorkspace());
|
||||||
HOST.register(new PlaceholderWorkspace(WorkspaceId.ASSETS, I18n.WORKSPACE_ASSETS, "Assets"));
|
host.register(new PlaceholderWorkspace(WorkspaceId.ASSETS, I18n.WORKSPACE_ASSETS, "Assets"));
|
||||||
HOST.register(new BuilderWorkspace());
|
host.register(new BuilderWorkspace(projectReference));
|
||||||
HOST.register(new PlaceholderWorkspace(WorkspaceId.DEBUG, I18n.WORKSPACE_DEBUG, "Debug"));
|
host.register(new PlaceholderWorkspace(WorkspaceId.DEBUG, I18n.WORKSPACE_DEBUG, "Debug"));
|
||||||
|
|
||||||
final var workspaceRail = new StudioWorkspaceRailControl<>(
|
final var workspaceRail = new StudioWorkspaceRailControl<>(
|
||||||
List.of(
|
List.of(
|
||||||
@ -35,7 +38,7 @@ public final class MainView extends BorderPane {
|
|||||||
),
|
),
|
||||||
this::showWorkspace);
|
this::showWorkspace);
|
||||||
setLeft(workspaceRail);
|
setLeft(workspaceRail);
|
||||||
setCenter(HOST);
|
setCenter(host);
|
||||||
setRight(new StudioRightUtilityPanelControl(
|
setRight(new StudioRightUtilityPanelControl(
|
||||||
Container.i18n().bind(I18n.SHELL_ACTIVITY),
|
Container.i18n().bind(I18n.SHELL_ACTIVITY),
|
||||||
StudioRightUtilityPanelControl.createPlaceholderContent(Container.i18n().bind(I18n.SHELL_ACTIVITY))));
|
StudioRightUtilityPanelControl.createPlaceholderContent(Container.i18n().bind(I18n.SHELL_ACTIVITY))));
|
||||||
@ -45,8 +48,12 @@ public final class MainView extends BorderPane {
|
|||||||
showWorkspace(WorkspaceId.EDITOR);
|
showWorkspace(WorkspaceId.EDITOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProjectReference projectReference() {
|
||||||
|
return projectReference;
|
||||||
|
}
|
||||||
|
|
||||||
private void showWorkspace(WorkspaceId workspaceId) {
|
private void showWorkspace(WorkspaceId workspaceId) {
|
||||||
HOST.show(workspaceId);
|
host.show(workspaceId);
|
||||||
Container.events().publish(new StudioWorkspaceSelectedEvent(workspaceId));
|
Container.events().publish(new StudioWorkspaceSelectedEvent(workspaceId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,132 @@
|
|||||||
|
package p.studio.window;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.projects.ProjectCatalogService;
|
||||||
|
import p.studio.projects.ProjectReference;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public final class ProjectLauncherView extends BorderPane {
|
||||||
|
private final ProjectCatalogService projectCatalogService;
|
||||||
|
private final Consumer<ProjectReference> onOpenProject;
|
||||||
|
private final Consumer<ProjectReference> onCreateProject;
|
||||||
|
private final ListView<ProjectReference> projectList = new ListView<>();
|
||||||
|
private final TextField projectNameField = new TextField();
|
||||||
|
private final Label feedbackLabel = new Label();
|
||||||
|
|
||||||
|
public ProjectLauncherView(
|
||||||
|
ProjectCatalogService projectCatalogService,
|
||||||
|
Consumer<ProjectReference> onOpenProject,
|
||||||
|
Consumer<ProjectReference> onCreateProject) {
|
||||||
|
this.projectCatalogService = Objects.requireNonNull(projectCatalogService, "projectCatalogService");
|
||||||
|
this.onOpenProject = Objects.requireNonNull(onOpenProject, "onOpenProject");
|
||||||
|
this.onCreateProject = Objects.requireNonNull(onCreateProject, "onCreateProject");
|
||||||
|
|
||||||
|
getStyleClass().add("studio-project-launcher");
|
||||||
|
setPadding(new Insets(24));
|
||||||
|
setCenter(buildContent());
|
||||||
|
|
||||||
|
reloadProjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox buildContent() {
|
||||||
|
final Label title = new Label();
|
||||||
|
title.textProperty().bind(Container.i18n().bind(I18n.LAUNCHER_TITLE));
|
||||||
|
title.getStyleClass().add("studio-launcher-title");
|
||||||
|
|
||||||
|
final Label subtitle = new Label();
|
||||||
|
subtitle.textProperty().bind(Container.i18n().bind(I18n.LAUNCHER_SUBTITLE));
|
||||||
|
subtitle.getStyleClass().add("studio-launcher-subtitle");
|
||||||
|
|
||||||
|
final Label listTitle = new Label();
|
||||||
|
listTitle.textProperty().bind(Container.i18n().bind(I18n.LAUNCHER_EXISTING_PROJECTS));
|
||||||
|
listTitle.getStyleClass().add("studio-launcher-section-title");
|
||||||
|
|
||||||
|
projectList.getStyleClass().add("studio-project-list");
|
||||||
|
VBox.setVgrow(projectList, Priority.ALWAYS);
|
||||||
|
|
||||||
|
final Button openButton = new Button();
|
||||||
|
openButton.textProperty().bind(Container.i18n().bind(I18n.LAUNCHER_OPEN_PROJECT));
|
||||||
|
openButton.disableProperty().bind(projectList.getSelectionModel().selectedItemProperty().isNull());
|
||||||
|
openButton.setOnAction(ignored -> openSelectedProject());
|
||||||
|
|
||||||
|
final HBox openRow = new HBox(openButton);
|
||||||
|
openRow.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
final Label createTitle = new Label();
|
||||||
|
createTitle.textProperty().bind(Container.i18n().bind(I18n.LAUNCHER_CREATE_PROJECT));
|
||||||
|
createTitle.getStyleClass().add("studio-launcher-section-title");
|
||||||
|
|
||||||
|
projectNameField.promptTextProperty().bind(Container.i18n().bind(I18n.LAUNCHER_PROJECT_NAME_PROMPT));
|
||||||
|
HBox.setHgrow(projectNameField, Priority.ALWAYS);
|
||||||
|
|
||||||
|
final Button createButton = new Button();
|
||||||
|
createButton.textProperty().bind(Container.i18n().bind(I18n.LAUNCHER_CREATE_BUTTON));
|
||||||
|
createButton.setOnAction(ignored -> createProject());
|
||||||
|
|
||||||
|
final HBox createRow = new HBox(12, projectNameField, createButton);
|
||||||
|
createRow.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
feedbackLabel.getStyleClass().add("studio-launcher-feedback");
|
||||||
|
feedbackLabel.setWrapText(true);
|
||||||
|
|
||||||
|
final VBox content = new VBox(16,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
listTitle,
|
||||||
|
projectList,
|
||||||
|
openRow,
|
||||||
|
createTitle,
|
||||||
|
createRow,
|
||||||
|
feedbackLabel);
|
||||||
|
content.setMaxWidth(720);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reloadProjects() {
|
||||||
|
projectList.setItems(FXCollections.observableArrayList(projectCatalogService.listProjects()));
|
||||||
|
if (!projectList.getItems().isEmpty()) {
|
||||||
|
projectList.getSelectionModel().selectFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openSelectedProject() {
|
||||||
|
final ProjectReference selected = projectList.getSelectionModel().getSelectedItem();
|
||||||
|
if (selected == null) {
|
||||||
|
feedbackLabel.textProperty().unbind();
|
||||||
|
feedbackLabel.setText("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
feedbackLabel.setText("");
|
||||||
|
onOpenProject.accept(selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProject() {
|
||||||
|
try {
|
||||||
|
final ProjectReference created = projectCatalogService.createProject(projectNameField.getText());
|
||||||
|
projectNameField.clear();
|
||||||
|
reloadProjects();
|
||||||
|
projectList.getSelectionModel().select(created);
|
||||||
|
feedbackLabel.textProperty().unbind();
|
||||||
|
feedbackLabel.setText("");
|
||||||
|
onCreateProject.accept(created);
|
||||||
|
} catch (IllegalArgumentException illegalArgumentException) {
|
||||||
|
feedbackLabel.textProperty().unbind();
|
||||||
|
feedbackLabel.setText(illegalArgumentException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
package p.studio.window;
|
||||||
|
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.events.StudioProjectCreatedEvent;
|
||||||
|
import p.studio.events.StudioProjectOpenedEvent;
|
||||||
|
import p.studio.projects.ProjectCatalogService;
|
||||||
|
import p.studio.projects.ProjectReference;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public final class StudioRootView extends StackPane {
|
||||||
|
private final ProjectCatalogService projectCatalogService = new ProjectCatalogService(resolveDefaultProjectsRoot());
|
||||||
|
|
||||||
|
public StudioRootView() {
|
||||||
|
showLauncher();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showLauncher() {
|
||||||
|
getChildren().setAll(new ProjectLauncherView(
|
||||||
|
projectCatalogService,
|
||||||
|
this::openProject,
|
||||||
|
this::createProject));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openProject(ProjectReference projectReference) {
|
||||||
|
final ProjectReference opened = projectCatalogService.openProject(projectReference.rootPath());
|
||||||
|
Container.events().publish(new StudioProjectOpenedEvent(opened));
|
||||||
|
showShell(opened);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProject(ProjectReference projectReference) {
|
||||||
|
Container.events().publish(new StudioProjectCreatedEvent(projectReference));
|
||||||
|
Container.events().publish(new StudioProjectOpenedEvent(projectReference));
|
||||||
|
showShell(projectReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showShell(ProjectReference projectReference) {
|
||||||
|
getChildren().setAll(new MainView(projectReference));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path resolveDefaultProjectsRoot() {
|
||||||
|
Path cursor = Path.of(System.getProperty("user.dir")).toAbsolutePath().normalize();
|
||||||
|
while (cursor != null) {
|
||||||
|
if (cursor.resolve("settings.gradle.kts").toFile().exists()
|
||||||
|
&& cursor.resolve("test-projects").toFile().exists()) {
|
||||||
|
return cursor.resolve("test-projects");
|
||||||
|
}
|
||||||
|
cursor = cursor.getParent();
|
||||||
|
}
|
||||||
|
return Path.of("test-projects").toAbsolutePath().normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ import javafx.scene.layout.StackPane;
|
|||||||
import p.studio.Container;
|
import p.studio.Container;
|
||||||
import p.studio.compiler.messages.BuilderPipelineConfig;
|
import p.studio.compiler.messages.BuilderPipelineConfig;
|
||||||
import p.studio.compiler.workspaces.BuilderPipelineService;
|
import p.studio.compiler.workspaces.BuilderPipelineService;
|
||||||
|
import p.studio.projects.ProjectReference;
|
||||||
import p.studio.utilities.i18n.I18n;
|
import p.studio.utilities.i18n.I18n;
|
||||||
import p.studio.utilities.logs.LogAggregator;
|
import p.studio.utilities.logs.LogAggregator;
|
||||||
import p.studio.workspaces.Workspace;
|
import p.studio.workspaces.Workspace;
|
||||||
@ -18,6 +19,7 @@ public class BuilderWorkspace implements Workspace {
|
|||||||
private final TextArea logs = new TextArea();
|
private final TextArea logs = new TextArea();
|
||||||
private final Button buildButton = new Button();
|
private final Button buildButton = new Button();
|
||||||
private final Button clearButton = new Button();
|
private final Button clearButton = new Button();
|
||||||
|
private final ProjectReference projectReference;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorkspaceId id() {
|
public WorkspaceId id() {
|
||||||
@ -34,7 +36,8 @@ public class BuilderWorkspace implements Workspace {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuilderWorkspace() {
|
public BuilderWorkspace(ProjectReference projectReference) {
|
||||||
|
this.projectReference = projectReference;
|
||||||
final var toolbar = buildToolBar();
|
final var toolbar = buildToolBar();
|
||||||
root.setTop(toolbar);
|
root.setTop(toolbar);
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ public class BuilderWorkspace implements Workspace {
|
|||||||
buildButton.setOnAction(e -> {
|
buildButton.setOnAction(e -> {
|
||||||
logs.clear();
|
logs.clear();
|
||||||
final var logAggregator = LogAggregator.with(logs::appendText);
|
final var logAggregator = LogAggregator.with(logs::appendText);
|
||||||
final var config = new BuilderPipelineConfig(false, "../test-projects/main");
|
final var config = new BuilderPipelineConfig(false, projectReference.rootPath().toString());
|
||||||
BuilderPipelineService.INSTANCE.run(config, logAggregator);
|
BuilderPipelineService.INSTANCE.run(config, logAggregator);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,7 +67,7 @@ public class BuilderWorkspace implements Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackPane buildProjectArea() {
|
private StackPane buildProjectArea() {
|
||||||
final var tmpLabel = new Label("Builder project area (WIP)");
|
final var tmpLabel = new Label("Project: " + projectReference.name());
|
||||||
return new StackPane(tmpLabel);
|
return new StackPane(tmpLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,13 @@ menu.view=View
|
|||||||
menu.help=Help
|
menu.help=Help
|
||||||
|
|
||||||
shell.activity=Activity
|
shell.activity=Activity
|
||||||
|
launcher.title=Projects
|
||||||
|
launcher.subtitle=Open an existing project or create a new one to enter the Studio shell.
|
||||||
|
launcher.existingProjects=Existing Projects
|
||||||
|
launcher.openProject=Open Project
|
||||||
|
launcher.createProject=Create New Project
|
||||||
|
launcher.projectNamePrompt=Project name
|
||||||
|
launcher.createButton=Create
|
||||||
|
|
||||||
toolbar.play=Play
|
toolbar.play=Play
|
||||||
toolbar.stop=Stop
|
toolbar.stop=Stop
|
||||||
|
|||||||
@ -71,3 +71,32 @@
|
|||||||
-fx-text-fill: #d4d4d4;
|
-fx-text-fill: #d4d4d4;
|
||||||
-fx-padding: 16;
|
-fx-padding: 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.studio-project-launcher {
|
||||||
|
-fx-background-color: linear-gradient(to bottom, #191919, #101010);
|
||||||
|
}
|
||||||
|
|
||||||
|
.studio-launcher-title {
|
||||||
|
-fx-font-size: 28px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-text-fill: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.studio-launcher-subtitle {
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
-fx-text-fill: #a6a6a6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.studio-launcher-section-title {
|
||||||
|
-fx-font-size: 15px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-text-fill: #dcdcdc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.studio-project-list {
|
||||||
|
-fx-pref-height: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.studio-launcher-feedback {
|
||||||
|
-fx-text-fill: #ff9b7d;
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
package p.studio.projects;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
final class ProjectCatalogServiceTest {
|
||||||
|
@TempDir
|
||||||
|
Path tempDir;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listsExistingProjectDirectories() throws Exception {
|
||||||
|
Files.createDirectories(tempDir.resolve("alpha"));
|
||||||
|
Files.createDirectories(tempDir.resolve("beta"));
|
||||||
|
Files.createDirectories(tempDir.resolve("alpha").resolve("src"));
|
||||||
|
|
||||||
|
final ProjectCatalogService service = new ProjectCatalogService(tempDir);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
java.util.List.of("alpha", "beta"),
|
||||||
|
service.listProjects().stream().map(ProjectReference::name).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsProjectWithExpectedStructure() {
|
||||||
|
final ProjectCatalogService service = new ProjectCatalogService(tempDir);
|
||||||
|
|
||||||
|
final ProjectReference project = service.createProject("My New Project");
|
||||||
|
|
||||||
|
assertEquals("my-new-project", project.name());
|
||||||
|
assertTrue(Files.isDirectory(project.rootPath()));
|
||||||
|
assertTrue(Files.isDirectory(project.rootPath().resolve(".workspace")));
|
||||||
|
assertTrue(Files.isDirectory(project.rootPath().resolve("src")));
|
||||||
|
assertTrue(Files.isDirectory(project.rootPath().resolve("build")));
|
||||||
|
assertTrue(Files.isDirectory(project.rootPath().resolve("cartridge")));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user