editor workspace foundation

This commit is contained in:
bQUARKz 2026-03-31 07:11:54 +01:00
parent 5f7e0e2bef
commit d9ba5e3cb4
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
14 changed files with 1431 additions and 313 deletions

View File

@ -0,0 +1,230 @@
package p.studio.controls;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TitledPane;
import java.util.Objects;
public abstract class WorkspaceDockPane extends TitledPane {
private static final double DEFAULT_MAXIMUM_DOCK_SHARE = 0.50;
private static final double DEFAULT_FALLBACK_HEIGHT = 520.0;
private final double collapsedHeight;
private final double minimumExpandedHeight;
private final double defaultExpandedHeight;
private final double maximumDockShare;
private final ChangeListener<Number> dividerPositionListener = (ignored, previous, current) -> normalizeDivider();
private boolean syncingDivider;
private SplitPane dockSplit;
private SplitPane.Divider observedDivider;
private Double lastExpandedDividerPosition;
protected WorkspaceDockPane(
final ObservableValue<String> titleBinding,
final double collapsedHeight,
final double minimumExpandedHeight,
final double defaultExpandedHeight,
final boolean expandedByDefault,
final String... styleClasses) {
this(titleBinding, collapsedHeight, minimumExpandedHeight, defaultExpandedHeight, DEFAULT_MAXIMUM_DOCK_SHARE, expandedByDefault, styleClasses);
}
protected WorkspaceDockPane(
final ObservableValue<String> titleBinding,
final double collapsedHeight,
final double minimumExpandedHeight,
final double defaultExpandedHeight,
final double maximumDockShare,
final boolean expandedByDefault,
final String... styleClasses) {
this.collapsedHeight = collapsedHeight;
this.minimumExpandedHeight = minimumExpandedHeight;
this.defaultExpandedHeight = defaultExpandedHeight;
this.maximumDockShare = maximumDockShare;
textProperty().bind(Objects.requireNonNull(titleBinding, "titleBinding"));
getStyleClass().add("workspace-dock-pane");
if (styleClasses != null && styleClasses.length > 0) {
getStyleClass().addAll(styleClasses);
}
setCollapsible(true);
setExpanded(expandedByDefault);
setAnimated(false);
setMinHeight(expandedByDefault ? minimumExpandedHeight : collapsedHeight);
setPrefHeight(defaultExpandedHeight);
setMaxHeight(expandedByDefault ? Double.MAX_VALUE : collapsedHeight);
expandedProperty().addListener((ignored, previous, expanded) -> {
if (expanded) {
expandDock();
} else {
collapseDock();
}
});
}
public final double collapsedHeight() {
return collapsedHeight;
}
public final double minimumExpandedHeight() {
return minimumExpandedHeight;
}
public final double defaultExpandedHeight() {
return defaultExpandedHeight;
}
public final SplitPane createBottomDockLayout(final Node primaryContent, final String... splitStyleClasses) {
final var split = new SplitPane(Objects.requireNonNull(primaryContent, "primaryContent"), this);
split.setOrientation(Orientation.VERTICAL);
split.getStyleClass().add("workspace-dock-split");
if (splitStyleClasses != null && splitStyleClasses.length > 0) {
split.getStyleClass().addAll(splitStyleClasses);
}
SplitPane.setResizableWithParent(primaryContent, true);
SplitPane.setResizableWithParent(this, true);
dockSplit = split;
bindDividerPositionListener();
dockSplit.heightProperty().addListener((ignored, previous, current) -> {
if (isExpanded()) {
normalizeDivider();
} else {
applyCollapsedDivider();
}
});
dockSplit.getDividers().addListener((javafx.collections.ListChangeListener<? super SplitPane.Divider>) change -> {
while (change.next()) {
if (change.wasAdded() && !change.getAddedSubList().isEmpty()) {
bindDividerPositionListener();
}
}
});
if (isExpanded()) {
expandDock();
} else {
collapseDock();
}
return split;
}
protected final void setDockContent(final Node content) {
setContent(Objects.requireNonNull(content, "content"));
}
private void expandDock() {
setMinHeight(minimumExpandedHeight);
setPrefHeight(defaultExpandedHeight);
setMaxHeight(Double.MAX_VALUE);
getStyleClass().remove("workspace-dock-pane-collapsed");
if (dockSplit != null) {
dockSplit.getStyleClass().remove("workspace-dock-split-collapsed");
updateDividerInteractivity(false);
final double restored = lastExpandedDividerPosition != null ? lastExpandedDividerPosition : defaultDividerPosition();
setDivider(clampExpandedDivider(restored));
}
}
private void collapseDock() {
setMinHeight(collapsedHeight);
setPrefHeight(collapsedHeight);
setMaxHeight(collapsedHeight);
if (!getStyleClass().contains("workspace-dock-pane-collapsed")) {
getStyleClass().add("workspace-dock-pane-collapsed");
}
if (dockSplit != null && !dockSplit.getStyleClass().contains("workspace-dock-split-collapsed")) {
dockSplit.getStyleClass().add("workspace-dock-split-collapsed");
}
if (dockSplit != null) {
applyCollapsedDivider();
updateDividerInteractivity(true);
}
}
private void applyCollapsedDivider() {
final double height = currentHeight();
final double collapsedPosition = Math.max(0.0, 1.0 - (collapsedHeight / height));
setDivider(Math.min(collapsedPosition, 0.985));
}
private void normalizeDivider() {
if (syncingDivider || dockSplit == null || dockSplit.getDividers().isEmpty()) {
return;
}
final double clamped = clampExpandedDivider(currentDivider());
lastExpandedDividerPosition = clamped;
if (Math.abs(clamped - currentDivider()) > 0.0001) {
setDivider(clamped);
}
}
private double clampExpandedDivider(final double position) {
final double minDivider = 1.0 - maximumDockShare;
final double maxDivider = Math.max(minDivider, 1.0 - (minimumExpandedHeight / currentHeight()));
if (position < minDivider) {
return minDivider;
}
if (position > maxDivider) {
return maxDivider;
}
return position;
}
private double defaultDividerPosition() {
final double preferred = 1.0 - (defaultExpandedHeight / currentHeight());
return clampExpandedDivider(preferred);
}
private double currentHeight() {
if (dockSplit == null || dockSplit.getHeight() <= 0) {
return DEFAULT_FALLBACK_HEIGHT;
}
return dockSplit.getHeight();
}
private double currentDivider() {
return dockSplit == null || dockSplit.getDividers().isEmpty() ? defaultDividerPosition() : dockSplit.getDividers().get(0).getPosition();
}
private void setDivider(final double position) {
if (dockSplit == null) {
return;
}
syncingDivider = true;
try {
dockSplit.setDividerPositions(position);
} finally {
syncingDivider = false;
}
}
private void bindDividerPositionListener() {
if (dockSplit == null || dockSplit.getDividers().isEmpty()) {
return;
}
final var divider = dockSplit.getDividers().get(0);
if (observedDivider == divider) {
return;
}
if (observedDivider != null) {
observedDivider.positionProperty().removeListener(dividerPositionListener);
}
observedDivider = divider;
observedDivider.positionProperty().addListener(dividerPositionListener);
}
private void updateDividerInteractivity(final boolean disabled) {
if (dockSplit == null) {
return;
}
Platform.runLater(() -> dockSplit.lookupAll(".split-pane-divider").forEach(node -> {
node.setMouseTransparent(disabled);
node.setVisible(!disabled);
node.setManaged(!disabled);
}));
}
}

View File

@ -73,6 +73,7 @@ public enum I18n {
WORKSPACE_CODE("workspace.code"),
CODE_EDITOR_NAVIGATOR_TITLE("codeEditor.navigator.title"),
CODE_EDITOR_NAVIGATOR_REFRESH("codeEditor.navigator.refresh"),
CODE_EDITOR_NAVIGATOR_REVEAL_ACTIVE("codeEditor.navigator.revealActive"),
CODE_EDITOR_NAVIGATOR_PLACEHOLDER("codeEditor.navigator.placeholder"),
CODE_EDITOR_NAVIGATOR_DETAIL("codeEditor.navigator.detail"),
CODE_EDITOR_OUTLINE_TITLE("codeEditor.outline.title"),

View File

@ -4,14 +4,18 @@ import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextArea;
import javafx.scene.control.TitledPane;
import p.studio.controls.WorkspaceDockPane;
import p.studio.controls.lifecycle.StudioControlLifecycle;
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
import java.util.Objects;
public abstract class LogsPane implements StudioControlLifecycle {
public abstract class LogsPane extends WorkspaceDockPane implements StudioControlLifecycle {
private static final double COLLAPSED_HEIGHT = 34.0;
private static final double MINIMUM_EXPANDED_HEIGHT = 120.0;
private static final double DEFAULT_EXPANDED_HEIGHT = 180.0;
private final TextArea textArea;
private final TitledPane pane;
protected LogsPane(
ObservableValue<String> titleBinding,
@ -23,6 +27,14 @@ public abstract class LogsPane implements StudioControlLifecycle {
ObservableValue<String> titleBinding,
String workspace,
boolean installLifecycle) {
super(
Objects.requireNonNull(titleBinding, "titleBinding"),
COLLAPSED_HEIGHT,
MINIMUM_EXPANDED_HEIGHT,
DEFAULT_EXPANDED_HEIGHT,
true,
"%s-workspace-logs-pane".formatted(normalizeWorkspaceName(workspace)));
final String workspaceName = Objects.requireNonNull(workspace, "workspace").trim();
if (workspaceName.isBlank()) {
throw new IllegalArgumentException("workspace must not be blank");
@ -34,19 +46,14 @@ public abstract class LogsPane implements StudioControlLifecycle {
textArea.setPrefRowCount(8);
textArea.getStyleClass().add("%s-workspace-logs".formatted(workspaceName));
this.pane = new TitledPane();
pane.textProperty().bind(Objects.requireNonNull(titleBinding, "titleBinding"));
pane.setContent(textArea);
pane.setCollapsible(true);
pane.setExpanded(true);
pane.getStyleClass().add("%s-workspace-logs-pane".formatted(workspaceName));
setDockContent(textArea);
if (installLifecycle) {
StudioControlLifecycleSupport.install(pane, this);
StudioControlLifecycleSupport.install(this, this);
}
}
public final TitledPane getPane() {
return pane;
return this;
}
protected final void appendLine(String line) {
@ -60,4 +67,12 @@ public abstract class LogsPane implements StudioControlLifecycle {
protected final void clearLogs() {
Platform.runLater(textArea::clear);
}
private static String normalizeWorkspaceName(final String workspace) {
final String workspaceName = Objects.requireNonNull(workspace, "workspace").trim();
if (workspaceName.isBlank()) {
throw new IllegalArgumentException("workspace must not be blank");
}
return workspaceName;
}
}

View File

@ -2,28 +2,34 @@ 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.controls.WorkspaceDockPane;
import p.studio.utilities.i18n.I18n;
public final class EditorHelperPanel extends BorderPane {
public final class EditorHelperPanel extends WorkspaceDockPane {
public static final double COLLAPSED_HEIGHT = 34.0;
public static final double MINIMUM_EXPANDED_HEIGHT = 120.0;
public static final double DEFAULT_EXPANDED_HEIGHT = 180.0;
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");
super(
Container.i18n().bind(I18n.CODE_EDITOR_HELPER_TITLE),
COLLAPSED_HEIGHT,
MINIMUM_EXPANDED_HEIGHT,
DEFAULT_EXPANDED_HEIGHT,
false,
"editor-workspace-helper-pane",
"editor-workspace-helper-panel");
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);
final var content = new VBox(8, placeholder);
content.getStyleClass().add("editor-workspace-panel-content");
setCenter(content);
content.setPadding(new Insets(10, 16, 14, 16));
setDockContent(content);
}
}

View File

@ -2,28 +2,33 @@ 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.controls.WorkspaceDockPane;
import p.studio.utilities.i18n.I18n;
public final class EditorOutlinePanel extends BorderPane {
public final class EditorOutlinePanel extends WorkspaceDockPane {
private static final double COLLAPSED_HEIGHT = 34.0;
private static final double MINIMUM_EXPANDED_HEIGHT = 120.0;
private static final double DEFAULT_HEIGHT = 180.0;
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");
super(
Container.i18n().bind(I18n.CODE_EDITOR_OUTLINE_TITLE),
COLLAPSED_HEIGHT,
MINIMUM_EXPANDED_HEIGHT,
DEFAULT_HEIGHT,
true,
"editor-workspace-outline-panel");
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);
final var content = new VBox(8, placeholder);
content.getStyleClass().add("editor-workspace-panel-content");
setCenter(content);
content.setPadding(new Insets(10, 16, 14, 16));
setDockContent(content);
}
}

View File

@ -3,6 +3,7 @@ package p.studio.workspaces.editor;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
@ -23,10 +24,12 @@ import java.util.Set;
import java.util.function.Consumer;
public final class EditorProjectNavigatorPanel extends BorderPane {
private final Button revealActiveButton = new Button();
private final Button refreshButton = new Button();
private final TreeView<EditorProjectNode> treeView = new TreeView<>();
private final Label emptyState = emptyLabel();
private final StackPane content = new StackPane();
private Runnable revealActiveFileAction = () -> { };
private Runnable refreshAction = () -> { };
private Consumer<EditorProjectNode> fileSelectionAction = node -> { };
@ -46,15 +49,29 @@ public final class EditorProjectNavigatorPanel extends BorderPane {
title.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_TITLE));
title.getStyleClass().add("editor-workspace-panel-title");
refreshButton.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_NAVIGATOR_REFRESH));
revealActiveButton.setFocusTraversable(false);
revealActiveButton.setDisable(true);
revealActiveButton.getStyleClass().addAll(
"studio-button",
"studio-button-icon",
"editor-workspace-header-icon-button");
revealActiveButton.setGraphic(EditorWorkspaceIcons.target());
revealActiveButton.setTooltip(new Tooltip(Container.i18n().text(I18n.CODE_EDITOR_NAVIGATOR_REVEAL_ACTIVE)));
revealActiveButton.setOnAction(event -> revealActiveFileAction.run());
refreshButton.setFocusTraversable(false);
refreshButton.getStyleClass().addAll("studio-button", "studio-button-secondary");
refreshButton.getStyleClass().addAll(
"studio-button",
"studio-button-icon",
"editor-workspace-header-icon-button");
refreshButton.setGraphic(EditorWorkspaceIcons.refresh());
refreshButton.setTooltip(new Tooltip(Container.i18n().text(I18n.CODE_EDITOR_NAVIGATOR_REFRESH)));
refreshButton.setOnAction(event -> refreshAction.run());
final var spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
final var header = new HBox(8, title, spacer, refreshButton);
final var header = new HBox(8, title, spacer, revealActiveButton, refreshButton);
header.getStyleClass().add("editor-workspace-panel-header");
return header;
}
@ -96,6 +113,14 @@ public final class EditorProjectNavigatorPanel extends BorderPane {
this.refreshAction = Objects.requireNonNull(refreshAction, "refreshAction");
}
public void setRevealActiveFileAction(final Runnable revealActiveFileAction) {
this.revealActiveFileAction = Objects.requireNonNull(revealActiveFileAction, "revealActiveFileAction");
}
public void setRevealActiveFileAvailable(final boolean available) {
revealActiveButton.setDisable(!available);
}
public void setFileSelectionAction(final Consumer<EditorProjectNode> fileSelectionAction) {
this.fileSelectionAction = Objects.requireNonNull(fileSelectionAction, "fileSelectionAction");
}
@ -109,11 +134,26 @@ public final class EditorProjectNavigatorPanel extends BorderPane {
showEmptyState(false);
}
public void revealPath(final Path path) {
final var normalizedPath = Objects.requireNonNull(path, "path").toAbsolutePath().normalize();
final var rootItem = treeView.getRoot();
if (rootItem == null) {
return;
}
findTreeItem(rootItem, normalizedPath).ifPresent(item -> {
expandAncestors(item);
treeView.getSelectionModel().select(item);
treeView.scrollTo(Math.max(treeView.getRow(item) - 2, 0));
});
}
private TreeItem<EditorProjectNode> buildTreeItem(
final EditorProjectNode node,
final Set<Path> expandedPaths,
final boolean isRoot) {
final var item = new TreeItem<>(node);
final TreeItem<EditorProjectNode> item = node.directory()
? new DirectoryTreeItem(node)
: new TreeItem<>(node);
item.setExpanded(isRoot || expandedPaths.contains(node.path()));
node.children().stream()
.map(child -> buildTreeItem(child, expandedPaths, false))
@ -176,6 +216,14 @@ public final class EditorProjectNavigatorPanel extends BorderPane {
emptyState.setManaged(empty);
}
private void expandAncestors(final TreeItem<EditorProjectNode> item) {
TreeItem<EditorProjectNode> current = item;
while (current != null) {
current.setExpanded(true);
current = current.getParent();
}
}
private Node iconFor(final EditorProjectNode node, final TreeItem<EditorProjectNode> treeItem) {
if (node.directory()) {
if (isBuildTone(node)) {
@ -231,4 +279,15 @@ public final class EditorProjectNavigatorPanel extends BorderPane {
placeholder.setWrapText(true);
return placeholder;
}
private static final class DirectoryTreeItem extends TreeItem<EditorProjectNode> {
private DirectoryTreeItem(final EditorProjectNode node) {
super(node);
}
@Override
public boolean isLeaf() {
return false;
}
}
}

View File

@ -58,6 +58,7 @@ public final class EditorStatusBar extends HBox {
public void showFile(final ProjectReference projectReference, final EditorOpenFileBuffer fileBuffer) {
showBreadcrumb(projectReference, fileBuffer.path());
showMetadata(true);
bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
setText(lineSeparator, fileBuffer.lineSeparator());
bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION);
@ -66,7 +67,8 @@ public final class EditorStatusBar extends HBox {
}
public void showPlaceholder() {
breadcrumb.getChildren().setAll(placeholderLabel());
breadcrumb.getChildren().clear();
showMetadata(false);
bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
bindDefault(lineSeparator, I18n.CODE_EDITOR_STATUS_LINE_SEPARATOR);
bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION);
@ -83,12 +85,6 @@ public final class EditorStatusBar extends HBox {
label.textProperty().bind(Container.i18n().bind(key));
}
private Label placeholderLabel() {
final var label = new Label();
label.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_STATUS_BREADCRUMB));
return label;
}
private void showBreadcrumb(final ProjectReference projectReference, final Path filePath) {
breadcrumb.getChildren().clear();
breadcrumb.getChildren().add(segment(
@ -119,11 +115,10 @@ public final class EditorStatusBar extends HBox {
}
private String rootLabel(final ProjectReference projectReference) {
final var directoryName = Optional.ofNullable(projectReference.rootPath().getFileName())
return Optional.ofNullable(projectReference.rootPath().getFileName())
.map(Path::toString)
.filter(name -> !name.isBlank())
.orElse(projectReference.name());
return directoryName + " (" + projectReference.name() + ")";
}
private HBox segment(final String text, final Node icon, final boolean root) {
@ -167,6 +162,19 @@ public final class EditorStatusBar extends HBox {
label.setText(text);
}
private void showMetadata(final boolean visible) {
setVisibleManaged(position, visible);
setVisibleManaged(lineSeparator, visible);
setVisibleManaged(indentation, visible);
setVisibleManaged(language, visible);
setVisibleManaged(readOnly, visible);
}
private void setVisibleManaged(final Label label, final boolean visible) {
label.setVisible(visible);
label.setManaged(visible);
}
private void styleChip(final Label label) {
if (!label.getStyleClass().contains("editor-workspace-status-chip")) {
label.getStyleClass().add("editor-workspace-status-chip");

View File

@ -2,6 +2,8 @@ package p.studio.workspaces.editor;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.OverrunStyle;
@ -21,7 +23,8 @@ public final class EditorTabStrip extends HBox {
private static final double TAB_WIDTH_HINT = 176.0;
private static final double TAB_HEIGHT_HINT = 34.0;
private static final double STRIP_HEIGHT_HINT = 50.0;
private static final double OVERFLOW_WIDTH_HINT = 110.0;
private static final double OVERFLOW_WIDTH_HINT = 128.0;
private static final double OVERFLOW_MENU_WIDTH_HINT = 180.0;
private final MenuButton overflowButton = new MenuButton();
private final Region spacer = new Region();
@ -44,6 +47,7 @@ public final class EditorTabStrip extends HBox {
"studio-button",
"studio-button-secondary",
"editor-workspace-tab-overflow");
applyOverflowMetrics();
widthProperty().addListener((ignored, previous, current) -> rebuild());
rebuild();
}
@ -107,7 +111,19 @@ public final class EditorTabStrip extends HBox {
continue;
}
final var fileBuffer = openFiles.get(index);
final var item = new MenuItem(fileBuffer.tabLabel());
final var label = new Label(fileBuffer.tabLabel());
label.getStyleClass().add("editor-workspace-tab-overflow-item");
label.setMinWidth(OVERFLOW_MENU_WIDTH_HINT);
label.setPrefWidth(OVERFLOW_MENU_WIDTH_HINT);
label.setMaxWidth(OVERFLOW_MENU_WIDTH_HINT);
label.setMinHeight(TAB_HEIGHT_HINT);
label.setPrefHeight(TAB_HEIGHT_HINT);
label.setMaxHeight(TAB_HEIGHT_HINT);
label.setAlignment(Pos.CENTER_LEFT);
label.setTextOverrun(OverrunStyle.ELLIPSIS);
final var item = new CustomMenuItem(label, true);
item.getStyleClass().add("editor-workspace-tab-overflow-menu-item");
item.setOnAction(event -> tabSelectionAction.accept(fileBuffer.path()));
items.add(item);
}
@ -142,4 +158,14 @@ public final class EditorTabStrip extends HBox {
button.setTextOverrun(OverrunStyle.ELLIPSIS);
button.setMnemonicParsing(false);
}
private void applyOverflowMetrics() {
overflowButton.setMinWidth(OVERFLOW_WIDTH_HINT);
overflowButton.setPrefWidth(OVERFLOW_WIDTH_HINT);
overflowButton.setMaxWidth(OVERFLOW_WIDTH_HINT);
overflowButton.setMinHeight(TAB_HEIGHT_HINT);
overflowButton.setPrefHeight(TAB_HEIGHT_HINT);
overflowButton.setMaxHeight(TAB_HEIGHT_HINT);
overflowButton.setMnemonicParsing(false);
}
}

View File

@ -34,6 +34,7 @@ public final class EditorWorkspace extends Workspace {
codeArea.getStyleClass().add("editor-workspace-code-area");
showEditorPlaceholder();
navigatorPanel.setRefreshAction(this::refreshNavigator);
navigatorPanel.setRevealActiveFileAction(this::revealActiveFileInNavigator);
navigatorPanel.setFileSelectionAction(this::openNode);
tabStrip.setTabSelectionAction(path -> {
openFileSession.activate(path);
@ -76,6 +77,7 @@ public final class EditorWorkspace extends Workspace {
private void renderSession() {
final var activeFile = openFileSession.activeFile();
navigatorPanel.setRevealActiveFileAvailable(activeFile.isPresent());
tabStrip.showOpenFiles(
openFileSession.openFiles(),
activeFile.map(EditorOpenFileBuffer::path).orElse(null));
@ -90,6 +92,12 @@ public final class EditorWorkspace extends Workspace {
statusBar.showFile(projectReference, fileBuffer);
}
private void revealActiveFileInNavigator() {
openFileSession.activeFile()
.map(EditorOpenFileBuffer::path)
.ifPresent(navigatorPanel::revealPath);
}
private void showUnsupportedFileModal(final java.nio.file.Path path) {
final var alert = new Alert(Alert.AlertType.INFORMATION);
if (root.getScene() != null) {
@ -109,20 +117,19 @@ public final class EditorWorkspace extends Workspace {
}
private VBox buildLayout() {
final var content = new SplitPane(buildLeftColumn(), buildCenterColumn());
final var content = new SplitPane(buildLeftColumn(), buildRightColumn());
content.setDividerPositions(0.30);
content.getStyleClass().add("editor-workspace-split");
final var layout = new VBox(12, content, helperPanel, statusBar);
final var layout = new VBox(12, content, 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);
private SplitPane buildLeftColumn() {
final var leftColumn = outlinePanel.createBottomDockLayout(navigatorPanel, "editor-workspace-left-split");
leftColumn.getStyleClass().add("editor-workspace-left-column");
VBox.setVgrow(navigatorPanel, Priority.ALWAYS);
return leftColumn;
}
@ -132,4 +139,8 @@ public final class EditorWorkspace extends Workspace {
VBox.setVgrow(codeArea, Priority.ALWAYS);
return centerColumn;
}
private SplitPane buildRightColumn() {
return helperPanel.createBottomDockLayout(buildCenterColumn(), "editor-workspace-right-split");
}
}

View File

@ -8,6 +8,8 @@ public final class EditorWorkspaceIcons {
private static final String FOLDER_PATH = "M1.5 4.5A1.5 1.5 0 0 1 3 3h3.2l1.1 1.4H13A1.5 1.5 0 0 1 14.5 5.9V12A1.5 1.5 0 0 1 13 13.5H3A1.5 1.5 0 0 1 1.5 12z";
private static final String FILE_PATH = "M4 1.5h5l3 3V13A1.5 1.5 0 0 1 10.5 14.5h-6A1.5 1.5 0 0 1 3 13V3A1.5 1.5 0 0 1 4.5 1.5zm4.7 1.2V5h2.3z";
private static final String COG_PATH = "M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.24-.68-2.64.72-1.96 1.96l.17.31c.446.816.023 1.84-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1c.895.265 1.318 1.289.872 2.105l-.17.31c-.68 1.24.72 2.64 1.96 1.96l.31-.17a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.24.68 2.64-.72 1.96-1.96l-.17-.31a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.68-1.24-.72-2.64-1.96-1.96l-.31.17a1.464 1.464 0 0 1-2.105-.872z";
private static final String REFRESH_PATH = "M8 2.2a5.8 5.8 0 0 1 4.3 1.9V2.8h1.2v3.8H9.7V5.4h1.8A4.6 4.6 0 1 0 12 11h1.3A5.9 5.9 0 1 1 8 2.2z";
private static final String TARGET_PATH = "M7.25 1.5h1.5v1.9a4.85 4.85 0 0 1 3.85 3.85h1.9v1.5h-1.9a4.85 4.85 0 0 1-3.85 3.85v1.9h-1.5v-1.9A4.85 4.85 0 0 1 3.4 8.75H1.5v-1.5h1.9A4.85 4.85 0 0 1 7.25 3.4zm.75 3.25A3.25 3.25 0 1 0 8 11.25 3.25 3.25 0 0 0 8 4.75zm0 1.65a1.6 1.6 0 1 1 0 3.2 1.6 1.6 0 0 1 0-3.2z";
private EditorWorkspaceIcons() {
}
@ -32,6 +34,14 @@ public final class EditorWorkspaceIcons {
return icon(COG_PATH, "editor-workspace-icon-cog");
}
public static Node refresh() {
return icon(REFRESH_PATH, "editor-workspace-icon-refresh");
}
public static Node target() {
return icon(TARGET_PATH, "editor-workspace-icon-target");
}
private static Node icon(final String path, final String toneClass) {
final var shape = new SVGPath();
shape.setContent(path);

View File

@ -64,6 +64,7 @@ toolbar.export=Export
workspace.code=Code
codeEditor.navigator.title=Project Navigator
codeEditor.navigator.refresh=Refresh
codeEditor.navigator.revealActive=Reveal active file
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

View File

@ -351,6 +351,27 @@
-fx-background-color: transparent;
}
.editor-workspace-split > .split-pane-divider {
-fx-background-color: transparent;
-fx-padding: 0 8 0 8;
}
.workspace-dock-split {
-fx-background-color: transparent;
}
.workspace-dock-split > .split-pane-divider {
-fx-background-color: #243243;
-fx-border-color: #556f8b;
-fx-padding: 3 0 3 0;
}
.workspace-dock-split-collapsed > .split-pane-divider {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-padding: 0;
}
.editor-workspace-left-column,
.editor-workspace-center-column {
-fx-spacing: 12;
@ -367,6 +388,19 @@
-fx-alignment: center-left;
}
.editor-workspace-header-icon-button {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-radius: 4;
-fx-border-radius: 4;
-fx-padding: 6;
}
.editor-workspace-header-icon-button:hover {
-fx-background-color: #243243;
-fx-border-color: #556f8b;
}
.editor-workspace-panel-content {
-fx-padding: 6 0 0 0;
}
@ -399,7 +433,7 @@
.editor-workspace-tree .tree-cell {
-fx-background-color: transparent;
-fx-text-fill: #d6e0ea;
-fx-font-size: 13px;
-fx-font-size: 14px;
-fx-padding: 4 6 4 4;
}
@ -408,6 +442,18 @@
-fx-text-fill: #ffffff;
}
.editor-workspace-tree .tree-disclosure-node {
-fx-padding: 0 4 0 0;
}
.editor-workspace-tree .tree-disclosure-node .arrow {
-fx-background-color: #8ea4ba;
}
.editor-workspace-tree .tree-cell:selected .tree-disclosure-node .arrow {
-fx-background-color: #e8f3ff;
}
.editor-workspace-tree-cell-tagged {
-fx-font-weight: bold;
}
@ -452,8 +498,16 @@
-fx-fill: #c6d0da;
}
.editor-workspace-icon-refresh {
-fx-fill: #eff5fb;
}
.editor-workspace-icon-target {
-fx-fill: #eff5fb;
}
.editor-workspace-outline-panel {
-fx-min-height: 150px;
-fx-min-height: 0;
}
.editor-workspace-tab-strip {
@ -533,14 +587,78 @@
-fx-background-radius: 0;
-fx-border-radius: 0;
-fx-padding: 0 12 0 12;
-fx-min-width: 128;
-fx-pref-width: 128;
-fx-max-width: 128;
-fx-min-height: 34;
-fx-pref-height: 34;
-fx-max-height: 34;
}
.editor-workspace-tab-overflow-item {
-fx-text-fill: #d9e2eb;
-fx-font-size: 12px;
-fx-padding: 0 10 0 10;
-fx-background-color: transparent;
}
.editor-workspace-code-area .content {
-fx-background-color: #171c22;
}
.workspace-dock-pane {
-fx-collapsible: true;
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-insets: 0;
-fx-border-insets: 0;
}
.workspace-dock-pane > .title {
-fx-background-color: #1b1f25;
-fx-border-color: #2a313c;
-fx-background-radius: 0;
-fx-border-radius: 0;
-fx-background-insets: 0;
-fx-border-insets: 0;
-fx-padding: 5 12 5 12;
}
.workspace-dock-pane > .title > .text {
-fx-fill: #eff5fb;
-fx-font-size: 14px;
-fx-font-weight: bold;
}
.workspace-dock-pane > .title > .arrow-button {
-fx-padding: 0 6 0 0;
}
.workspace-dock-pane > .content {
-fx-background-color: #1b1f25;
-fx-border-color: #2a313c;
-fx-background-insets: 0;
-fx-border-insets: 0;
}
.editor-workspace-helper-panel {
-fx-min-height: 96px;
-fx-min-height: 0;
}
.workspace-dock-pane-collapsed {
-fx-background-insets: 0;
}
.workspace-dock-pane-collapsed > .title {
-fx-padding: 4 12 4 12;
}
.workspace-dock-pane-collapsed > .content {
-fx-padding: 0;
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-insets: 0;
-fx-border-insets: 0;
}
.editor-workspace-status-bar {
@ -549,6 +667,9 @@
-fx-background-radius: 12;
-fx-border-radius: 12;
-fx-border-color: #2a313c;
-fx-min-height: 40;
-fx-pref-height: 40;
-fx-max-height: 40;
}
.editor-workspace-status-breadcrumb {

View File

@ -1,4 +1,629 @@
[ {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",

View File

@ -53,6 +53,266 @@
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "0 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project ready",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project loading started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Studio",
"message" : "Project opened",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Zelda",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "8 assets loaded",
@ -2238,264 +2498,4 @@
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "7 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "7 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "7 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "7 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: Bigode",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan started",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "7 assets loaded",
"severity" : "SUCCESS",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Asset scan diagnostics updated.",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bla",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: ui_atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: one-more-atlas",
"severity" : "INFO",
"sticky" : false
}, {
"source" : "Assets",
"message" : "Discovered asset: bbb2",
"severity" : "INFO",
"sticky" : false
} ]