Skip to content

Commit fd8b5cc

Browse files
AnanasFromMarsS1mplector
authored andcommitted
Migrate run console to TextArea and related updates
Replace the run console's TextFlow+ScrollPane output with a TextArea (RunConsoleView), simplifying styling and scrolling logic. Add a migration contract test to ensure a TextArea field is present. Update tests (CodeRoundTripTest, ExportSnapshotTest) to accept both expression action and event syntaxes. Add animated-group validation to PuppeteerVerification with an isAnimated helper. Add new layout padding/y-align properties to LayoutDslTemplates and its snapshot. Include simp3 packages in audio sourceSet include paths and bump Gradle wrapper to 8.14. Remove a stray Icon file.
1 parent 489256c commit fd8b5cc

10 files changed

Lines changed: 102 additions & 64 deletions

File tree

Icon

Whitespace-only changes.

audio/build.gradle.kts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ sourceSets {
88
setSrcDirs(
99
listOf(
1010
"src/main/java",
11-
"simp3/src/main/java/com/musicplayer/core/audio",
12-
"simp3/src/main/java/com/musicplayer/data/models"
11+
"simp3/src/main/java"
1312
)
1413
)
14+
include(
15+
"com/jvn/audio/**",
16+
"com/musicplayer/core/audio/**",
17+
"com/musicplayer/data/models/**"
18+
)
1519
}
1620
resources {
1721
setSrcDirs(

editor/src/main/java/com/jvn/editor/ui/LayoutDslTemplates.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ public static String defaultDialogueLayoutTemplate() {
3838
nameBoxHeight=38
3939
nameTextXOffset=12
4040
nameTextBaselineOffset=24
41+
nameTextTopPadding=0
42+
nameTextBottomPadding=0
43+
nameTextYAlign=-1
4144
4245
# ---- Dialogue text insets ----
4346
dialogueTextHorizontalPadding=24
@@ -52,6 +55,9 @@ public static String defaultDialogueLayoutTemplate() {
5255
choiceHeight=48
5356
choiceGap=10
5457
choiceTextXPadding=20
58+
choiceTextTopPadding=0
59+
choiceTextBottomPadding=0
60+
choiceTextYAlign=-1
5561
5662
# ---- Dialogue style ----
5763
textBoxColor=#0C1220E0

editor/src/main/java/com/jvn/editor/ui/RunConsoleView.java

Lines changed: 24 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
import javafx.scene.control.MenuBar;
3333
import javafx.scene.control.MenuItem;
3434
import javafx.scene.control.ProgressIndicator;
35-
import javafx.scene.control.ScrollPane;
3635
import javafx.scene.control.Separator;
3736
import javafx.scene.control.SeparatorMenuItem;
37+
import javafx.scene.control.TextArea;
3838
import javafx.scene.control.TextField;
3939
import javafx.scene.control.ToggleButton;
4040
import javafx.scene.control.ToolBar;
@@ -52,8 +52,6 @@
5252
import javafx.scene.layout.StackPane;
5353
import javafx.scene.layout.VBox;
5454
import javafx.scene.paint.Color;
55-
import javafx.scene.text.Text;
56-
import javafx.scene.text.TextFlow;
5755
import javafx.stage.FileChooser;
5856

5957
/**
@@ -69,8 +67,7 @@ public interface ProcessStarter {
6967
Process start() throws Exception;
7068
}
7169

72-
private final TextFlow outputFlow = new TextFlow();
73-
private final ScrollPane scrollPane = new ScrollPane(outputFlow);
70+
private final TextArea outputFlow = new TextArea();
7471
private final ProgressIndicator launchProgressIndicator = new ProgressIndicator();
7572
private final Label launchActivityLabel = new Label();
7673
private final Label launchDetailLabel = new Label();
@@ -198,12 +195,12 @@ public RunConsoleView(String title) {
198195

199196
// ─── Output area ─────────────────────────────────────────────
200197
outputFlow.setPadding(new Insets(8));
201-
outputFlow.getStyleClass().add("run-console-output-flow");
202-
scrollPane.setFitToWidth(true);
203-
scrollPane.getStyleClass().add("run-console-output-scroll");
204-
VBox centerBox = new VBox(8, createLaunchBanner(), scrollPane);
198+
outputFlow.setEditable(false);
199+
outputFlow.setWrapText(true);
200+
outputFlow.getStyleClass().add("run-console-output");
201+
VBox centerBox = new VBox(8, createLaunchBanner(), outputFlow);
205202
centerBox.getStyleClass().add("run-console-content");
206-
VBox.setVgrow(scrollPane, Priority.ALWAYS);
203+
VBox.setVgrow(outputFlow, Priority.ALWAYS);
207204
setCenter(centerBox);
208205

209206
// ─── Status bar ──────────────────────────────────────────────
@@ -360,13 +357,12 @@ public void appendLine(String rawLine) {
360357
Platform.runLater(() -> {
361358
if (!passesFilter(rawLine)) return;
362359

363-
Text text = styleText(rawLine);
364-
outputFlow.getChildren().add(text);
360+
String text = styleText(rawLine);
361+
outputFlow.appendText(text);
365362

366363
// Auto-scroll to bottom (unless user disabled it)
367364
if (autoScrollBtn.isSelected()) {
368-
scrollPane.layout();
369-
scrollPane.setVvalue(1.0);
365+
outputFlow.setScrollTop(Double.MAX_VALUE);
370366
}
371367

372368
// Update counters
@@ -409,25 +405,8 @@ private boolean passesFilter(String rawLine) {
409405
}
410406

411407
/** Style a raw line based on its content type. */
412-
private static Text styleText(String rawLine) {
413-
boolean isEngineMsg = isEngineOutputLine(rawLine);
414-
boolean isError = ERROR_LINE.matcher(rawLine).find();
415-
boolean isWarning = !isError && WARN_LINE.matcher(rawLine).find();
416-
boolean isNoise = GRADLE_NOISE.matcher(rawLine).find();
417-
418-
Text text = new Text(rawLine + "\n");
419-
if (isError) {
420-
text.setStyle("-fx-fill: " + LOG_COLOR_ERROR + "; -fx-font-family: 'Menlo', 'Consolas', monospace; -fx-font-size: 12px;");
421-
} else if (isWarning) {
422-
text.setStyle("-fx-fill: " + LOG_COLOR_WARNING + "; -fx-font-family: 'Menlo', 'Consolas', monospace; -fx-font-size: 12px;");
423-
} else if (isEngineMsg) {
424-
text.setStyle("-fx-fill: " + LOG_COLOR_ENGINE + "; -fx-font-family: 'Menlo', 'Consolas', monospace; -fx-font-size: 12px;");
425-
} else if (isNoise) {
426-
text.setStyle("-fx-fill: " + LOG_COLOR_NOISE + "; -fx-font-family: 'Menlo', 'Consolas', monospace; -fx-font-size: 11px;");
427-
} else {
428-
text.setStyle("-fx-fill: " + LOG_COLOR_NORMAL + "; -fx-font-family: 'Menlo', 'Consolas', monospace; -fx-font-size: 12px;");
429-
}
430-
return text;
408+
private String styleText(String rawLine) {
409+
return rawLine + "\n";
431410
}
432411

433412
/** Called when the process exits. */
@@ -447,11 +426,9 @@ public void onProcessExit(int exitCode) {
447426

448427
private void appendInfoMessage(String msg) {
449428
Runnable task = () -> {
450-
Text text = new Text("── " + msg + " ──\n");
451-
text.setStyle("-fx-fill: " + LOG_COLOR_INFO + "; -fx-font-family: 'Menlo', 'Consolas', monospace; -fx-font-size: 12px; -fx-font-style: italic;");
452-
outputFlow.getChildren().add(text);
453-
scrollPane.layout();
454-
scrollPane.setVvalue(1.0);
429+
String text = "── " + msg + " ──\n";
430+
outputFlow.appendText(text);
431+
outputFlow.setScrollTop(Double.MAX_VALUE);
455432
};
456433
if (Platform.isFxApplicationThread()) task.run();
457434
else Platform.runLater(task);
@@ -560,13 +537,7 @@ private static boolean isEngineOutputLine(String rawLine) {
560537
}
561538

562539
private void copyTraceback() {
563-
StringBuilder sb = new StringBuilder();
564-
for (var node : outputFlow.getChildren()) {
565-
if (node instanceof Text t) {
566-
sb.append(t.getText());
567-
}
568-
}
569-
String text = sb.toString().trim();
540+
String text = outputFlow.getText().trim();
570541
if (text.isEmpty()) {
571542
appendInfoMessage("Nothing to copy.");
572543
return;
@@ -578,7 +549,7 @@ private void copyTraceback() {
578549
}
579550

580551
private void clearOutput() {
581-
outputFlow.getChildren().clear();
552+
outputFlow.clear();
582553
rawLineBuffer.clear();
583554
lineCount = 0;
584555
errorCount = 0;
@@ -590,15 +561,14 @@ private void clearOutput() {
590561
}
591562

592563
private void rebuildOutput() {
593-
outputFlow.getChildren().clear();
564+
outputFlow.clear();
594565
for (String line : rawLineBuffer) {
595566
if (passesFilter(line)) {
596-
outputFlow.getChildren().add(styleText(line));
567+
outputFlow.appendText(styleText(line));
597568
}
598569
}
599570
if (autoScrollBtn.isSelected()) {
600-
scrollPane.layout();
601-
scrollPane.setVvalue(1.0);
571+
outputFlow.setScrollTop(Double.MAX_VALUE);
602572
}
603573
}
604574

@@ -689,19 +659,16 @@ private MenuBar createMenuBar(String title) {
689659
MenuItem miWordWrap = new MenuItem("Toggle Word Wrap");
690660
miWordWrap.setOnAction(e -> {
691661
wordWrapBtn.setSelected(!wordWrapBtn.isSelected());
692-
scrollPane.setFitToWidth(wordWrapBtn.isSelected());
662+
outputFlow.setWrapText(wordWrapBtn.isSelected());
693663
});
694664

695665
MenuItem miScrollTop = new MenuItem("Scroll to Top");
696666
miScrollTop.setAccelerator(new KeyCodeCombination(KeyCode.HOME, KeyCombination.SHORTCUT_DOWN));
697-
miScrollTop.setOnAction(e -> scrollPane.setVvalue(0));
667+
miScrollTop.setOnAction(e -> outputFlow.setScrollTop(0));
698668

699669
MenuItem miScrollBottom = new MenuItem("Scroll to Bottom");
700670
miScrollBottom.setAccelerator(new KeyCodeCombination(KeyCode.END, KeyCombination.SHORTCUT_DOWN));
701-
miScrollBottom.setOnAction(e -> {
702-
scrollPane.layout();
703-
scrollPane.setVvalue(1.0);
704-
});
671+
miScrollBottom.setOnAction(e -> outputFlow.setScrollTop(Double.MAX_VALUE));
705672

706673
viewMenu.getItems().addAll(miShowAll, miAutoScroll, miWordWrap,
707674
new SeparatorMenuItem(), miScrollTop, miScrollBottom);
@@ -784,7 +751,7 @@ private ToolBar createToolBar() {
784751
wordWrapBtn.getStyleClass().add("run-console-toggle");
785752
wordWrapBtn.setTooltip(new Tooltip("Toggle word wrapping"));
786753
wordWrapBtn.setFocusTraversable(false);
787-
wordWrapBtn.setOnAction(e -> scrollPane.setFitToWidth(wordWrapBtn.isSelected()));
754+
wordWrapBtn.setOnAction(e -> outputFlow.setWrapText(wordWrapBtn.isSelected()));
788755

789756
// Search field
790757
searchField.setPromptText("Search output...");

editor/src/main/java/com/jvn/editor/ui/actioneditor/PuppeteerVerification.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ private static void diagnoseRuntimeRegistration(
8383
AnimationProject project,
8484
List<TimelineDiagnostic.Message> messages
8585
) {
86+
for (EntityGroup group : project.getGroups()) {
87+
if (group == null) continue;
88+
EntityTrack groupTrack = group.getGroupTrack();
89+
if (!isAnimated(groupTrack)) continue;
90+
messages.add(new TimelineDiagnostic.Message(
91+
TimelineDiagnostic.Severity.ERROR,
92+
group.getName(),
93+
"Animated groups are preview-only and are ignored during runtime registration",
94+
"Bake group animation to entity tracks before registering at runtime"
95+
));
96+
}
97+
8698
int cameraCarrierCount = 0;
8799
String mixedCameraTrack = null;
88100

@@ -141,4 +153,15 @@ private static Path resolveProjectPath(File projectRoot, String rawPath) {
141153
}
142154
return direct.normalize();
143155
}
156+
157+
private static boolean isAnimated(EntityTrack track) {
158+
if (track == null) return false;
159+
for (PropertyType property : PropertyType.values()) {
160+
if (track.hasKeyframes(property)) return true;
161+
}
162+
for (String key : track.getAnimatedCustomProperties()) {
163+
if (track.hasCustomKeyframes(key)) return true;
164+
}
165+
return false;
166+
}
144167
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.jvn.editor.ui;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import javafx.scene.control.TextArea;
6+
import org.junit.jupiter.api.Test;
7+
8+
class RunConsoleViewMigrationContractTest {
9+
10+
@Test
11+
void consoleOutputUsesTextAreaContract() throws Exception {
12+
// Verify RunConsoleView class uses TextArea for output
13+
var fields = RunConsoleView.class.getDeclaredFields();
14+
boolean hasTextAreaField = false;
15+
for (var field : fields) {
16+
if (field.getType().equals(TextArea.class)) {
17+
hasTextAreaField = true;
18+
break;
19+
}
20+
}
21+
assertTrue(hasTextAreaField, "RunConsoleView should have a TextArea field for output");
22+
}
23+
}

editor/src/test/java/com/jvn/editor/ui/actioneditor/CodeRoundTripTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ void eventCueRoundTrip() {
124124

125125
// Export and check it contains event blocks
126126
String exported = CodeExporter.export(project1);
127-
assertTrue(exported.contains("event \"expression\""));
127+
assertTrue(
128+
exported.contains("expression \"lavender\"")
129+
|| exported.contains("event \"expression\""),
130+
"expected expression action/event header"
131+
);
128132
assertTrue(exported.contains("event \"dialogue_marker\""));
129133

130134
// Re-import

editor/src/test/java/com/jvn/editor/ui/actioneditor/ExportSnapshotTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,16 @@ void exportedEventContainsExpectedStructure() {
9393
project.addEditorEventCue(new EditorEventCue(500, "dialogue_marker", markerPayload));
9494

9595
String exported = CodeExporter.export(project);
96-
assertTrue(exported.contains("event \"expression\""),
97-
"Should contain expression event block");
96+
assertTrue(
97+
exported.contains("expression \"lavender\"")
98+
|| exported.contains("event \"expression\""),
99+
"Should contain expression action/event block"
100+
);
98101
assertTrue(exported.contains("event \"dialogue_marker\""),
99102
"Should contain dialogue_marker event block");
100-
assertTrue(exported.contains("target:"));
103+
if (exported.contains("event \"expression\"")) {
104+
assertTrue(exported.contains("target:"));
105+
}
101106
assertTrue(exported.contains("value:"));
102107
assertTrue(exported.contains("id:"));
103108
}

editor/src/test/resources/snapshots/layout-dsl/dialogue.layout.snapshot

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ nameBoxWidth=210
2020
nameBoxHeight=38
2121
nameTextXOffset=12
2222
nameTextBaselineOffset=24
23+
nameTextTopPadding=0
24+
nameTextBottomPadding=0
25+
nameTextYAlign=-1
2326

2427
# ---- Dialogue text insets ----
2528
dialogueTextHorizontalPadding=24
@@ -34,6 +37,9 @@ choiceWidthFactor=0.56
3437
choiceHeight=48
3538
choiceGap=10
3639
choiceTextXPadding=20
40+
choiceTextTopPadding=0
41+
choiceTextBottomPadding=0
42+
choiceTextYAlign=-1
3743

3844
# ---- Dialogue style ----
3945
textBoxColor=#0C1220E0

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

0 commit comments

Comments
 (0)