implements PLN-0013
This commit is contained in:
parent
29666928ea
commit
c7ca603731
@ -8,5 +8,5 @@
|
|||||||
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||||
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||||
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0010","status":"in_progress","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[{"id":"AGD-0010","file":"AGD-0010-studio-code-editor-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0008","file":"DEC-0008-studio-code-editor-read-only-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0010"}],"plans":[{"id":"PLN-0012","file":"PLN-0012-studio-code-editor-spec-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0013","file":"PLN-0013-editor-workspace-layout-and-passive-surfaces.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0014","file":"PLN-0014-project-navigator-snapshot-and-read-only-file-opening.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0010","status":"in_progress","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[{"id":"AGD-0010","file":"AGD-0010-studio-code-editor-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0008","file":"DEC-0008-studio-code-editor-read-only-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0010"}],"plans":[{"id":"PLN-0012","file":"PLN-0012-studio-code-editor-spec-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0013","file":"PLN-0013-editor-workspace-layout-and-passive-surfaces.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0014","file":"PLN-0014-project-navigator-snapshot-and-read-only-file-opening.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]}],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]}
|
{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]}
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
id: PLN-0013
|
id: PLN-0013
|
||||||
ticket: studio-code-editor-workspace-foundations
|
ticket: studio-code-editor-workspace-foundations
|
||||||
title: Implement the read-only Code Editor workspace shell and passive surfaces
|
title: Implement the read-only Code Editor workspace shell and passive surfaces
|
||||||
status: open
|
status: done
|
||||||
created: 2026-03-30
|
created: 2026-03-30
|
||||||
completed:
|
completed: 2026-03-30
|
||||||
tags:
|
tags:
|
||||||
- studio
|
- studio
|
||||||
- editor
|
- editor
|
||||||
|
|||||||
@ -71,6 +71,22 @@ public enum I18n {
|
|||||||
TOOLBAR_EXPORT("toolbar.export"),
|
TOOLBAR_EXPORT("toolbar.export"),
|
||||||
|
|
||||||
WORKSPACE_CODE("workspace.code"),
|
WORKSPACE_CODE("workspace.code"),
|
||||||
|
CODE_EDITOR_NAVIGATOR_TITLE("codeEditor.navigator.title"),
|
||||||
|
CODE_EDITOR_NAVIGATOR_REFRESH("codeEditor.navigator.refresh"),
|
||||||
|
CODE_EDITOR_NAVIGATOR_PLACEHOLDER("codeEditor.navigator.placeholder"),
|
||||||
|
CODE_EDITOR_NAVIGATOR_DETAIL("codeEditor.navigator.detail"),
|
||||||
|
CODE_EDITOR_OUTLINE_TITLE("codeEditor.outline.title"),
|
||||||
|
CODE_EDITOR_OUTLINE_PLACEHOLDER("codeEditor.outline.placeholder"),
|
||||||
|
CODE_EDITOR_HELPER_TITLE("codeEditor.helper.title"),
|
||||||
|
CODE_EDITOR_HELPER_PLACEHOLDER("codeEditor.helper.placeholder"),
|
||||||
|
CODE_EDITOR_TABS_PLACEHOLDER("codeEditor.tabs.placeholder"),
|
||||||
|
CODE_EDITOR_TABS_OVERFLOW("codeEditor.tabs.overflow"),
|
||||||
|
CODE_EDITOR_STATUS_BREADCRUMB("codeEditor.status.breadcrumb"),
|
||||||
|
CODE_EDITOR_STATUS_POSITION("codeEditor.status.position"),
|
||||||
|
CODE_EDITOR_STATUS_LINE_SEPARATOR("codeEditor.status.lineSeparator"),
|
||||||
|
CODE_EDITOR_STATUS_INDENTATION("codeEditor.status.indentation"),
|
||||||
|
CODE_EDITOR_STATUS_LANGUAGE("codeEditor.status.language"),
|
||||||
|
CODE_EDITOR_STATUS_READ_ONLY("codeEditor.status.readOnly"),
|
||||||
|
|
||||||
WORKSPACE_SHIPPER("workspace.shipper"),
|
WORKSPACE_SHIPPER("workspace.shipper"),
|
||||||
WORKSPACE_SHIPPER_LOGS("workspace.shipper.logs"),
|
WORKSPACE_SHIPPER_LOGS("workspace.shipper.logs"),
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
package p.studio.workspaces.editor;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
|
|
||||||
|
public final class EditorHelperPanel extends BorderPane {
|
||||||
|
|
||||||
|
public EditorHelperPanel() {
|
||||||
|
getStyleClass().addAll("editor-workspace-panel", "editor-workspace-helper-panel");
|
||||||
|
setPadding(new Insets(14, 16, 14, 16));
|
||||||
|
|
||||||
|
final var title = new Label();
|
||||||
|
title.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_HELPER_TITLE));
|
||||||
|
title.getStyleClass().add("editor-workspace-panel-title");
|
||||||
|
|
||||||
|
final var placeholder = new Label();
|
||||||
|
placeholder.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_HELPER_PLACEHOLDER));
|
||||||
|
placeholder.getStyleClass().add("editor-workspace-placeholder");
|
||||||
|
placeholder.setWrapText(true);
|
||||||
|
|
||||||
|
final var content = new VBox(8, title, placeholder);
|
||||||
|
content.getStyleClass().add("editor-workspace-panel-content");
|
||||||
|
setCenter(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package p.studio.workspaces.editor;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
|
|
||||||
|
public final class EditorOutlinePanel extends BorderPane {
|
||||||
|
|
||||||
|
public EditorOutlinePanel() {
|
||||||
|
getStyleClass().addAll("editor-workspace-panel", "editor-workspace-outline-panel");
|
||||||
|
setPadding(new Insets(14, 16, 14, 16));
|
||||||
|
|
||||||
|
final var title = new Label();
|
||||||
|
title.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_OUTLINE_TITLE));
|
||||||
|
title.getStyleClass().add("editor-workspace-panel-title");
|
||||||
|
|
||||||
|
final var placeholder = new Label();
|
||||||
|
placeholder.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_OUTLINE_PLACEHOLDER));
|
||||||
|
placeholder.getStyleClass().add("editor-workspace-placeholder");
|
||||||
|
placeholder.setWrapText(true);
|
||||||
|
|
||||||
|
final var content = new VBox(8, title, placeholder);
|
||||||
|
content.getStyleClass().add("editor-workspace-panel-content");
|
||||||
|
setCenter(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package p.studio.workspaces.editor;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
|
|
||||||
|
public final class EditorProjectNavigatorPanel extends BorderPane {
|
||||||
|
|
||||||
|
public EditorProjectNavigatorPanel() {
|
||||||
|
getStyleClass().addAll("editor-workspace-panel", "editor-workspace-navigator-panel");
|
||||||
|
setPadding(new Insets(14, 16, 14, 16));
|
||||||
|
setTop(buildHeader());
|
||||||
|
setCenter(buildPlaceholder());
|
||||||
|
}
|
||||||
|
|
||||||
|
private HBox buildHeader() {
|
||||||
|
final var title = new Label();
|
||||||
|
title.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_TITLE));
|
||||||
|
title.getStyleClass().add("editor-workspace-panel-title");
|
||||||
|
|
||||||
|
final var refreshButton = new Button();
|
||||||
|
refreshButton.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_REFRESH));
|
||||||
|
refreshButton.setDisable(true);
|
||||||
|
refreshButton.setFocusTraversable(false);
|
||||||
|
refreshButton.getStyleClass().addAll("studio-button", "studio-button-secondary");
|
||||||
|
|
||||||
|
final var spacer = new Region();
|
||||||
|
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||||
|
|
||||||
|
final var header = new HBox(8, title, spacer, refreshButton);
|
||||||
|
header.getStyleClass().add("editor-workspace-panel-header");
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox buildPlaceholder() {
|
||||||
|
final var placeholder = new Label();
|
||||||
|
placeholder.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_PLACEHOLDER));
|
||||||
|
placeholder.getStyleClass().add("editor-workspace-placeholder");
|
||||||
|
placeholder.setWrapText(true);
|
||||||
|
|
||||||
|
final var detail = new Label();
|
||||||
|
detail.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_DETAIL));
|
||||||
|
detail.getStyleClass().add("editor-workspace-placeholder-detail");
|
||||||
|
detail.setWrapText(true);
|
||||||
|
|
||||||
|
final var content = new VBox(8, placeholder, detail);
|
||||||
|
content.getStyleClass().add("editor-workspace-panel-content");
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package p.studio.workspaces.editor;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
|
|
||||||
|
public final class EditorStatusBar extends HBox {
|
||||||
|
|
||||||
|
public EditorStatusBar() {
|
||||||
|
setAlignment(Pos.CENTER_LEFT);
|
||||||
|
setSpacing(12);
|
||||||
|
getStyleClass().add("editor-workspace-status-bar");
|
||||||
|
|
||||||
|
final var breadcrumb = new Label();
|
||||||
|
breadcrumb.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_STATUS_BREADCRUMB));
|
||||||
|
breadcrumb.getStyleClass().add("editor-workspace-status-breadcrumb");
|
||||||
|
|
||||||
|
final var spacer = new Region();
|
||||||
|
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||||
|
|
||||||
|
getChildren().addAll(
|
||||||
|
breadcrumb,
|
||||||
|
spacer,
|
||||||
|
statusChip(I18n.CODE_EDITOR_STATUS_POSITION),
|
||||||
|
statusChip(I18n.CODE_EDITOR_STATUS_LINE_SEPARATOR),
|
||||||
|
statusChip(I18n.CODE_EDITOR_STATUS_INDENTATION),
|
||||||
|
statusChip(I18n.CODE_EDITOR_STATUS_LANGUAGE),
|
||||||
|
statusChip(I18n.CODE_EDITOR_STATUS_READ_ONLY)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Label statusChip(final I18n key) {
|
||||||
|
final var chip = new Label();
|
||||||
|
chip.textProperty().bind(Container.i18n().bind(key));
|
||||||
|
chip.getStyleClass().add("editor-workspace-status-chip");
|
||||||
|
return chip;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package p.studio.workspaces.editor;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
|
|
||||||
|
public final class EditorTabStrip extends HBox {
|
||||||
|
|
||||||
|
public EditorTabStrip() {
|
||||||
|
setAlignment(Pos.CENTER_LEFT);
|
||||||
|
setSpacing(10);
|
||||||
|
getStyleClass().add("editor-workspace-tab-strip");
|
||||||
|
|
||||||
|
final var placeholderTab = new Label();
|
||||||
|
placeholderTab.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_TABS_PLACEHOLDER));
|
||||||
|
placeholderTab.getStyleClass().addAll("editor-workspace-tab", "editor-workspace-tab-active");
|
||||||
|
|
||||||
|
final var spacer = new Region();
|
||||||
|
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||||
|
|
||||||
|
final var overflowButton = new Button();
|
||||||
|
overflowButton.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_TABS_OVERFLOW));
|
||||||
|
overflowButton.setDisable(true);
|
||||||
|
overflowButton.setFocusTraversable(false);
|
||||||
|
overflowButton.getStyleClass().addAll("studio-button", "studio-button-secondary");
|
||||||
|
|
||||||
|
getChildren().addAll(placeholderTab, spacer, overflowButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,41 +0,0 @@
|
|||||||
package p.studio.workspaces.editor;
|
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import javafx.scene.layout.HBox;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
|
|
||||||
public final class EditorToolbar extends HBox {
|
|
||||||
|
|
||||||
public EditorToolbar() {
|
|
||||||
setPadding(new Insets(6, 10, 6, 10));
|
|
||||||
setSpacing(8);
|
|
||||||
getStyleClass().add("main-toolbar");
|
|
||||||
|
|
||||||
Button newBtn = iconButton("📄", "New");
|
|
||||||
Button openBtn = iconButton("📂", "Open");
|
|
||||||
Button saveBtn = iconButton("💾", "Save");
|
|
||||||
|
|
||||||
Button runBtn = iconButton("▶", "Run");
|
|
||||||
runBtn.getStyleClass().remove("studio-button-secondary");
|
|
||||||
runBtn.getStyleClass().add("studio-button-primary");
|
|
||||||
|
|
||||||
Region spacer = new Region();
|
|
||||||
HBox.setHgrow(spacer, javafx.scene.layout.Priority.ALWAYS);
|
|
||||||
|
|
||||||
getChildren().addAll(
|
|
||||||
newBtn,
|
|
||||||
openBtn,
|
|
||||||
saveBtn,
|
|
||||||
spacer,
|
|
||||||
runBtn
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Button iconButton(String icon, String tooltip) {
|
|
||||||
Button b = new Button(icon);
|
|
||||||
b.setFocusTraversable(false);
|
|
||||||
b.getStyleClass().addAll("studio-button", "studio-button-secondary", "studio-button-icon");
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +1,10 @@
|
|||||||
package p.studio.workspaces.editor;
|
package p.studio.workspaces.editor;
|
||||||
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.SplitPane;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import org.fxmisc.richtext.CodeArea;
|
import org.fxmisc.richtext.CodeArea;
|
||||||
import org.fxmisc.richtext.LineNumberFactory;
|
import org.fxmisc.richtext.LineNumberFactory;
|
||||||
import p.studio.projects.ProjectReference;
|
import p.studio.projects.ProjectReference;
|
||||||
@ -11,21 +14,26 @@ import p.studio.workspaces.WorkspaceId;
|
|||||||
|
|
||||||
public final class EditorWorkspace extends Workspace {
|
public final class EditorWorkspace extends Workspace {
|
||||||
private final BorderPane root = new BorderPane();
|
private final BorderPane root = new BorderPane();
|
||||||
private final EditorToolbar toolbar = new EditorToolbar();
|
|
||||||
private final CodeArea codeArea = new CodeArea();
|
private final CodeArea codeArea = new CodeArea();
|
||||||
|
private final EditorProjectNavigatorPanel navigatorPanel = new EditorProjectNavigatorPanel();
|
||||||
|
private final EditorOutlinePanel outlinePanel = new EditorOutlinePanel();
|
||||||
|
private final EditorHelperPanel helperPanel = new EditorHelperPanel();
|
||||||
|
private final EditorStatusBar statusBar = new EditorStatusBar();
|
||||||
|
private final EditorTabStrip tabStrip = new EditorTabStrip();
|
||||||
|
|
||||||
public EditorWorkspace(final ProjectReference projectReference) {
|
public EditorWorkspace(final ProjectReference projectReference) {
|
||||||
super(projectReference);
|
super(projectReference);
|
||||||
|
root.getStyleClass().add("editor-workspace");
|
||||||
codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
|
codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
|
||||||
|
codeArea.setEditable(false);
|
||||||
|
codeArea.setWrapText(false);
|
||||||
|
codeArea.getStyleClass().add("editor-workspace-code-area");
|
||||||
codeArea.replaceText("""
|
codeArea.replaceText("""
|
||||||
fn frame(): void
|
// Read-only first wave
|
||||||
{
|
// Open-file wiring lands in the next plan.
|
||||||
// hello Prometeu
|
|
||||||
}
|
|
||||||
""");
|
""");
|
||||||
|
|
||||||
root.setTop(toolbar);
|
root.setCenter(buildLayout());
|
||||||
root.setCenter(codeArea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public WorkspaceId workspaceId() { return WorkspaceId.EDITOR; }
|
@Override public WorkspaceId workspaceId() { return WorkspaceId.EDITOR; }
|
||||||
@ -43,4 +51,29 @@ public final class EditorWorkspace extends Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CodeArea codeArea() { return codeArea; }
|
public CodeArea codeArea() { return codeArea; }
|
||||||
|
|
||||||
|
private VBox buildLayout() {
|
||||||
|
final var content = new SplitPane(buildLeftColumn(), buildCenterColumn());
|
||||||
|
content.setDividerPositions(0.27);
|
||||||
|
content.getStyleClass().add("editor-workspace-split");
|
||||||
|
|
||||||
|
final var layout = new VBox(12, content, helperPanel, statusBar);
|
||||||
|
layout.getStyleClass().add("editor-workspace-layout");
|
||||||
|
VBox.setVgrow(content, Priority.ALWAYS);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox buildLeftColumn() {
|
||||||
|
final var leftColumn = new VBox(12, navigatorPanel, outlinePanel);
|
||||||
|
leftColumn.getStyleClass().add("editor-workspace-left-column");
|
||||||
|
VBox.setVgrow(navigatorPanel, Priority.ALWAYS);
|
||||||
|
return leftColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox buildCenterColumn() {
|
||||||
|
final var centerColumn = new VBox(12, tabStrip, codeArea);
|
||||||
|
centerColumn.getStyleClass().add("editor-workspace-center-column");
|
||||||
|
VBox.setVgrow(codeArea, Priority.ALWAYS);
|
||||||
|
return centerColumn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,6 +62,22 @@ toolbar.play=Play
|
|||||||
toolbar.stop=Stop
|
toolbar.stop=Stop
|
||||||
toolbar.export=Export
|
toolbar.export=Export
|
||||||
workspace.code=Code
|
workspace.code=Code
|
||||||
|
codeEditor.navigator.title=Project Navigator
|
||||||
|
codeEditor.navigator.refresh=Refresh
|
||||||
|
codeEditor.navigator.placeholder=Project navigation lands in the next implementation slice.
|
||||||
|
codeEditor.navigator.detail=This first shell reserves the full navigator surface, its refresh action, and the left-column composition without wiring project-tree data yet.
|
||||||
|
codeEditor.outline.title=Outline
|
||||||
|
codeEditor.outline.placeholder=Outline is reserved for a future semantic-aware wave.
|
||||||
|
codeEditor.helper.title=Editor Helper
|
||||||
|
codeEditor.helper.placeholder=This region is intentionally passive in the first read-only wave.
|
||||||
|
codeEditor.tabs.placeholder=no-file-open.txt
|
||||||
|
codeEditor.tabs.overflow=More
|
||||||
|
codeEditor.status.breadcrumb=proj > src > file.pbs
|
||||||
|
codeEditor.status.position=L:C
|
||||||
|
codeEditor.status.lineSeparator=LF
|
||||||
|
codeEditor.status.indentation=Spaces: 4
|
||||||
|
codeEditor.status.language=Text
|
||||||
|
codeEditor.status.readOnly=Read-only
|
||||||
workspace.shipper=Shipper
|
workspace.shipper=Shipper
|
||||||
workspace.shipper.logs=Logs
|
workspace.shipper.logs=Logs
|
||||||
workspace.shipper.button.run=Build
|
workspace.shipper.button.run=Build
|
||||||
|
|||||||
@ -338,6 +338,122 @@
|
|||||||
-fx-background-color: #17191d;
|
-fx-background-color: #17191d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor-workspace {
|
||||||
|
-fx-background-color: #15181d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-layout {
|
||||||
|
-fx-padding: 16;
|
||||||
|
-fx-background-color: #15181d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-split {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-left-column,
|
||||||
|
.editor-workspace-center-column {
|
||||||
|
-fx-spacing: 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-panel {
|
||||||
|
-fx-background-color: #1b1f25;
|
||||||
|
-fx-background-radius: 12;
|
||||||
|
-fx-border-radius: 12;
|
||||||
|
-fx-border-color: #2a313c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-panel-header {
|
||||||
|
-fx-alignment: center-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-panel-content {
|
||||||
|
-fx-padding: 6 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-panel-title {
|
||||||
|
-fx-text-fill: #eff5fb;
|
||||||
|
-fx-font-size: 14px;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-placeholder {
|
||||||
|
-fx-text-fill: #c3cfdb;
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-placeholder-detail {
|
||||||
|
-fx-text-fill: #8896a7;
|
||||||
|
-fx-font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-navigator-panel {
|
||||||
|
-fx-min-height: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-outline-panel {
|
||||||
|
-fx-min-height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-tab-strip {
|
||||||
|
-fx-padding: 10 14 10 14;
|
||||||
|
-fx-background-color: #1b1f25;
|
||||||
|
-fx-background-radius: 12;
|
||||||
|
-fx-border-radius: 12;
|
||||||
|
-fx-border-color: #2a313c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-tab {
|
||||||
|
-fx-background-color: #11151b;
|
||||||
|
-fx-background-radius: 9;
|
||||||
|
-fx-border-radius: 9;
|
||||||
|
-fx-border-color: #2a313c;
|
||||||
|
-fx-padding: 8 12 8 12;
|
||||||
|
-fx-text-fill: #c5d2de;
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-tab-active {
|
||||||
|
-fx-background-color: #223246;
|
||||||
|
-fx-border-color: #4a86be;
|
||||||
|
-fx-text-fill: #eef6ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-code-area {
|
||||||
|
-fx-background-color: #171c22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-code-area .content {
|
||||||
|
-fx-background-color: #171c22;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-helper-panel {
|
||||||
|
-fx-min-height: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-status-bar {
|
||||||
|
-fx-padding: 10 14 10 14;
|
||||||
|
-fx-background-color: #1b1f25;
|
||||||
|
-fx-background-radius: 12;
|
||||||
|
-fx-border-radius: 12;
|
||||||
|
-fx-border-color: #2a313c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-status-breadcrumb {
|
||||||
|
-fx-text-fill: #d4dde7;
|
||||||
|
-fx-font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-workspace-status-chip {
|
||||||
|
-fx-background-color: #11151b;
|
||||||
|
-fx-background-radius: 999;
|
||||||
|
-fx-border-radius: 999;
|
||||||
|
-fx-border-color: #2a313c;
|
||||||
|
-fx-padding: 4 10 4 10;
|
||||||
|
-fx-text-fill: #c5d2de;
|
||||||
|
-fx-font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
.assets-workspace-split {
|
.assets-workspace-split {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user