diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d2fcba4..4be4e12 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,14 +15,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 18 - uses: actions/setup-java@v3 - with: - java-version: '18' - distribution: 'temurin' - cache: maven - - name: Build with Maven - run: mvn -B package --file pom.xml - - name: Run tests with Maven - run: mvn test + - uses: actions/checkout@v3 + - name: Set up JDK 18 + uses: actions/setup-java@v3 + with: + java-version: '18' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + - name: Run tests with Maven + run: mvn test diff --git a/README.md b/README.md index 3320e69..8d47010 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ # Tynk Dialog Tool + [![Build](https://github.com/jadevogt/tynk_dialog/actions/workflows/maven.yml/badge.svg)](https://github.com/jadevogt/tynk_dialog/actions/workflows/maven.yml) + ## Overview -This is an early development version of a tool that can be used to create, edit, and eventually preview dialog boxes for the upcoming game [Tynk! and the Final Phonorecord](https://tynkga.me/). + +This is an early development version of a tool that can be used to create, edit, and eventually +preview dialog boxes for the upcoming game [Tynk! and the Final Phonorecord](https://tynkga.me/). ## Roadmap + ### Completed + - Proof of Concept * Open dialog files saved in the JSON based file format * Edit the content and settings of the dialog files interactively @@ -19,7 +25,9 @@ This is an early development version of a tool that can be used to create, edit, * Behaviors (text effects) * Print delay * Rich text editing inside the dialog tool interface + ### To-Do + - Game File Integration * Automatically pull data from a configured game data path in the filesystem * Check user input against the character, blip, textbox style info found in the game files @@ -28,5 +36,7 @@ This is an early development version of a tool that can be used to create, edit, * Preview sound blips * Drag and drop capability for rearranging dialog * Preview dialog in styled textbox without opening GameMaker + ### Screenshots + ![image](https://user-images.githubusercontent.com/89030899/189528166-79769f65-7576-483f-a1d2-9d916f1ad37c.png) diff --git a/pom.xml b/pom.xml index 41fccb9..19891be 100644 --- a/pom.xml +++ b/pom.xml @@ -1,74 +1,74 @@ - - 4.0.0 - best.tigers - tynk_dialog - 1.0-SNAPSHOT - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.2 - - - org.apache.maven.plugins - maven-compiler-plugin - - 17 - 17 - - - - - - ${basedir}/src/main/resources - - **/* - - - - - - UTF-8 - 8 - 8 - - - - javax.json - javax.json-api - 1.1.4 - - - org.glassfish - javax.json - 1.1.4 - - - org.junit.jupiter - junit-jupiter - 5.9.0 - test - - - - org.apache.commons - commons-lang3 - 3.12.0 - + + tynk_dialog + + + + maven-surefire-plugin + org.apache.maven.plugins + 2.22.2 + + + maven-compiler-plugin + + 17 + 17 + + org.apache.maven.plugins + + + + + ${basedir}/src/main/resources + + **/* + + + + + + + javax.json-api + javax.json + 1.1.4 + + + javax.json + org.glassfish + 1.1.4 + + + junit-jupiter + org.junit.jupiter + test + 5.9.0 + + + + commons-lang3 + org.apache.commons + 3.12.0 + - - com.formdev - flatlaf - 2.4 - - - com.formdev - flatlaf-intellij-themes - 2.4 - - + + flatlaf + com.formdev + 2.4 + + + flatlaf-intellij-themes + com.formdev + 2.4 + + + best.tigers + 4.0.0 + + 8 + 8 + UTF-8 + + 1.0-SNAPSHOT \ No newline at end of file diff --git a/src/main/java/best/tigers/tynk_dialog/Main.java b/src/main/java/best/tigers/tynk_dialog/Main.java index 91cbb02..9f0eb65 100644 --- a/src/main/java/best/tigers/tynk_dialog/Main.java +++ b/src/main/java/best/tigers/tynk_dialog/Main.java @@ -2,21 +2,19 @@ import best.tigers.tynk_dialog.gui.Assets; import best.tigers.tynk_dialog.gui.controller.PrimaryListController; - -import javax.swing.*; import com.formdev.flatlaf.intellijthemes.FlatMaterialDesignDarkIJTheme; - -import java.awt.*; +import java.awt.EventQueue; +import javax.swing.JEditorPane; public class Main { public static void main(String... args) { Assets.runIntegrations(); - JEditorPane.registerEditorKitForContentType("text/harlowtml", "best.tigers.tynk_dialog.gui.text.HarlowTMLEditorKit"); + JEditorPane.registerEditorKitForContentType( + "text/harlowtml", "best.tigers.tynk_dialog.gui.text.HarlowTMLEditorKit"); FlatMaterialDesignDarkIJTheme.setup(); EventQueue.invokeLater( - () -> { - PrimaryListController.launch(); - }); + () -> { + PrimaryListController.launch(); + }); } } - diff --git a/src/main/java/best/tigers/tynk_dialog/exceptions/DialogFileIOException.java b/src/main/java/best/tigers/tynk_dialog/exceptions/DialogFileIOException.java index 89bc356..b8d6912 100644 --- a/src/main/java/best/tigers/tynk_dialog/exceptions/DialogFileIOException.java +++ b/src/main/java/best/tigers/tynk_dialog/exceptions/DialogFileIOException.java @@ -3,8 +3,7 @@ import java.io.IOException; public class DialogFileIOException extends IOException { - public DialogFileIOException() { - } + public DialogFileIOException() {} public DialogFileIOException(String message) { super(message); diff --git a/src/main/java/best/tigers/tynk_dialog/exceptions/DialogParseException.java b/src/main/java/best/tigers/tynk_dialog/exceptions/DialogParseException.java index 54d7bfc..8e61537 100644 --- a/src/main/java/best/tigers/tynk_dialog/exceptions/DialogParseException.java +++ b/src/main/java/best/tigers/tynk_dialog/exceptions/DialogParseException.java @@ -1,8 +1,7 @@ package best.tigers.tynk_dialog.exceptions; public class DialogParseException extends Exception { - public DialogParseException() { - } + public DialogParseException() {} public DialogParseException(String message) { super(message); @@ -16,4 +15,3 @@ public DialogParseException(String message, Throwable cause) { super(message, cause); } } - diff --git a/src/main/java/best/tigers/tynk_dialog/game/Constants.java b/src/main/java/best/tigers/tynk_dialog/game/Constants.java index 7958063..9958b11 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/Constants.java +++ b/src/main/java/best/tigers/tynk_dialog/game/Constants.java @@ -1,78 +1,86 @@ package best.tigers.tynk_dialog.game; -import java.awt.*; +import java.awt.Color; import java.util.Arrays; -import java.util.Locale; public final class Constants { - public final int textBoxLength = 45; - public final int textBoxHeight = 4; - - public enum Behavior { - WAVE ("Wave", "wave"), - QUAKE ("Quake", "quake"); - private final String behaviorName; - private final String behaviorValue; - Behavior(String behaviorName, String behaviorValue) { - this.behaviorName = behaviorName; - this.behaviorValue = behaviorValue; - } - - public static Behavior fromString(String input) { - return Arrays.stream(Behavior.values()).filter(v -> - v.getBehaviorValue().equals(input.toLowerCase())).findFirst().orElse(null); - } - - public String getBehaviorValue() { - return this.behaviorValue; - } - - public String getBehaviorName() { - return this.behaviorName; - } - - public String asTag() { - return ""; - } + public final int textBoxLength = 45; + public final int textBoxHeight = 4; + + private Constants() {} + + public enum Behavior { + WAVE("Wave", "wave"), + QUAKE("Quake", "quake"); + private final String behaviorName; + private final String behaviorValue; + + Behavior(String behaviorName, String behaviorValue) { + this.behaviorName = behaviorName; + this.behaviorValue = behaviorValue; + } + + public static Behavior fromString(String input) { + return Arrays.stream(Behavior.values()) + .filter(v -> v.getBehaviorValue().equals(input.toLowerCase())) + .findFirst() + .orElse(null); + } + + public String getBehaviorValue() { + return this.behaviorValue; + } + + public String getBehaviorName() { + return this.behaviorName; + } + + public String asTag() { + return ""; + } + } + + public enum TextColor { + WHITE("white", "#F2E9DC"), + GREEN("green", "#4eb569"), + GREY("grey", "#888888"), + RED("red", "#FF5A5F"), + BLUE("blue", "#6DD3CE"), + YELLOW("yellow", "#FFCC00"), + BACKGROUND("background", "#3D2D3A"); + + private final String gameName; + private final String hexCode; + + TextColor(String gameName, String hexCode) { + this.gameName = gameName; + this.hexCode = hexCode; + } + + public static TextColor fromAWT(Color color) { + return Arrays.stream(TextColor.values()) + .filter(v -> v.toAWT().equals(color)) + .findFirst() + .orElse(WHITE); + } + + public static TextColor fromString(String input) { + return Arrays.stream(TextColor.values()) + .filter(v -> v.getGameName().equals(input.toLowerCase())) + .findFirst() + .orElse(WHITE); + } + + public Color toAWT() { + return Color.decode(hexCode); + } + + public String getGameName() { + return gameName; } - public enum TextColor { - WHITE ("white", "#F2E9DC"), - GREEN ("green", "#3F612D"), - RED ("red", "#FF5A5F"), - BLUE ("blue", "#6DD3CE"), - YELLOW ("yellow", "#FFCC00"), - BACKGROUND ("background", "#3D2D3A"); - - private final String gameName; - private final String hexCode; - - TextColor (String gameName, String hexCode) { - this.gameName = gameName; - this.hexCode = hexCode; - } - - public Color toAWT() { - return Color.decode(hexCode); - } - - public String getGameName() { - return gameName; - } - - public static TextColor fromAWT(Color color) { - return Arrays.stream(TextColor.values()).filter(v -> - v.toAWT().equals(color)).findFirst().orElse(WHITE); - } - - public static TextColor fromString(String input) { - return Arrays.stream(TextColor.values()).filter(v -> - v.getGameName().equals(input.toLowerCase())).findFirst().orElse(WHITE); - } - - public String asTag() { - return ""; - } + public String asTag() { + return ""; } - private Constants() {} -} \ No newline at end of file + } +} diff --git a/src/main/java/best/tigers/tynk_dialog/game/Dialog.java b/src/main/java/best/tigers/tynk_dialog/game/Dialog.java index f7d40a5..dcc3e84 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/Dialog.java +++ b/src/main/java/best/tigers/tynk_dialog/game/Dialog.java @@ -1,8 +1,8 @@ package best.tigers.tynk_dialog.game; +import java.util.ArrayList; import javax.json.Json; import javax.json.JsonObject; -import java.util.ArrayList; /** * Represents what the internal documentation refers to as a "Dialog File," essentially a titled @@ -13,8 +13,8 @@ public class Dialog { private static final String defaultTitle = "Untitled"; private static int untitledDialogCount = 0; - private String title; private final ArrayList contents; + private String title; public Dialog(String title, ArrayList contents) { this.title = title; @@ -36,8 +36,7 @@ public Dialog(String title) { * multiple untitled dialogs being created in the same session. */ public Dialog() { - String suffix = - Dialog.untitledDialogCount > 0 ? " " + Dialog.untitledDialogCount : ""; + String suffix = Dialog.untitledDialogCount > 0 ? " " + Dialog.untitledDialogCount : ""; title = defaultTitle + suffix; contents = new ArrayList(); Dialog.untitledDialogCount += 1; @@ -63,9 +62,9 @@ public JsonObject serialize() { pageArray.add(currentPage.serialize()); } return Json.createObjectBuilder() - .add("title", this.title) - .add("contents", pageArray.build()) - .build(); + .add("title", this.title) + .add("contents", pageArray.build()) + .build(); } public ArrayList getPages() { diff --git a/src/main/java/best/tigers/tynk_dialog/game/DialogPage.java b/src/main/java/best/tigers/tynk_dialog/game/DialogPage.java index ce32dbb..5eb82ab 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/DialogPage.java +++ b/src/main/java/best/tigers/tynk_dialog/game/DialogPage.java @@ -11,7 +11,7 @@ public class DialogPage { private boolean canSkip; public DialogPage( - String speaker, String content, String textStyle, String blip, boolean canSkip) { + String speaker, String content, String textStyle, String blip, boolean canSkip) { this.content = content; this.speaker = speaker; this.textStyle = textStyle; @@ -72,17 +72,18 @@ public void setCanSkip(boolean skippable) { } public JsonObject serialize() { - javax.json.JsonObjectBuilder result = Json.createObjectBuilder() + javax.json.JsonObjectBuilder result = + Json.createObjectBuilder() .add("txt", content) - .add("canSkip", canSkip) - .add("speaker", speaker); + .add("canSkip", canSkip) + .add("speaker", speaker); if (blip != null) { result.add("blip", blip); } else { result.add("blip", -1); } if (textStyle != null) { - result.add("textbox", textStyle); + result.add("textbox", textStyle); } else { result.add("textbox", -1); } diff --git a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLCharacterToken.java b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLCharacterToken.java index 7f72f5b..673eeee 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLCharacterToken.java +++ b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLCharacterToken.java @@ -1,18 +1,18 @@ package best.tigers.tynk_dialog.game.harlowtml; public class HarlowTMLCharacterToken extends HarlowTMLToken { - private char tokenContent; + private char tokenContent; - public HarlowTMLCharacterToken(char tokenContent) { - super("CharacterToken"); - this.tokenContent = tokenContent; - } + public HarlowTMLCharacterToken(char tokenContent) { + super("CharacterToken"); + this.tokenContent = tokenContent; + } - public String toString() { - return ""; - } + public String toString() { + return ""; + } - public String getContent() { - return String.valueOf(this.tokenContent); - } + public String getContent() { + return String.valueOf(this.tokenContent); + } } diff --git a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLEntityToken.java b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLEntityToken.java index 01c30ce..6d8337a 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLEntityToken.java +++ b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLEntityToken.java @@ -1,23 +1,28 @@ package best.tigers.tynk_dialog.game.harlowtml; public class HarlowTMLEntityToken extends HarlowTMLToken { - private String entityName; - private String entityValue; - public HarlowTMLEntityToken(String entityName, String entityValue) { - super(entityName); - this.entityName = entityName; - this.entityValue = entityValue; - } - public String getEntityName() { - return entityName; - } - public String getEntityValue() { - return entityValue; - } - public void setEntityName(String entityName) { - this.entityName = entityName; - } - public void setEntityValue(String entityValue) { - this.entityValue = entityValue; - } + private String entityName; + private String entityValue; + + public HarlowTMLEntityToken(String entityName, String entityValue) { + super(entityName); + this.entityName = entityName; + this.entityValue = entityValue; + } + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public String getEntityValue() { + return entityValue; + } + + public void setEntityValue(String entityValue) { + this.entityValue = entityValue; + } } diff --git a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTagToken.java b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTagToken.java index 08814d6..6dde973 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTagToken.java +++ b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTagToken.java @@ -1,56 +1,65 @@ package best.tigers.tynk_dialog.game.harlowtml; public class HarlowTMLTagToken extends HarlowTMLToken { - public enum TagType { - OPEN, CLOSE, ENTITY - } - private String tagName; - private TagType tagType; - private String tagValue; - - public HarlowTMLTagToken(String tagName, TagType tagType, String tagValue) { - super("TagToken"); - this.tagName = tagName; - this.tagType = tagType; - this.tagValue = tagValue; - } + private String tagName; + private final TagType tagType; + private String tagValue; - public HarlowTMLTagToken(TagType tagType, String tagValue) { - this("", tagType, tagValue); - } + public HarlowTMLTagToken(String tagName, TagType tagType, String tagValue) { + super("TagToken"); + this.tagName = tagName; + this.tagType = tagType; + this.tagValue = tagValue; + } - public HarlowTMLTagToken(TagType tagType) { - this(tagType, ""); - } + public HarlowTMLTagToken(TagType tagType, String tagValue) { + this("", tagType, tagValue); + } - public String getTagValue() { - return tagValue; - } + public HarlowTMLTagToken(TagType tagType) { + this(tagType, ""); + } - public void setTagValue(String value) { - this.tagValue = value; - } + public String getTagValue() { + return tagValue; + } - public String getTagName() { - return this.tagName; - } + public void setTagValue(String value) { + this.tagValue = value; + } - public void setTagName(String tagName) { - this.tagName = tagName; - } + public String getTagName() { + return this.tagName; + } - public String toString() { - return ""; - } + public void setTagName(String tagName) { + this.tagName = tagName; + } - public TagType getType() { - switch (getTagName()) { - case "t": - case "wait": - case "time": - return TagType.ENTITY; - default: - return this.tagType; - } + public String toString() { + return ""; + } + + public TagType getType() { + switch (getTagName()) { + case "t": + case "wait": + case "time": + return TagType.ENTITY; + default: + return this.tagType; } + } + + public enum TagType { + OPEN, + CLOSE, + ENTITY + } } diff --git a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLToken.java b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLToken.java index 272d12e..0d8cc3f 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLToken.java +++ b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLToken.java @@ -1,20 +1,21 @@ package best.tigers.tynk_dialog.game.harlowtml; public class HarlowTMLToken { - private String name; - public HarlowTMLToken(String name) { - this.name = name; - } + private String name; - public String getName() { - return name; - } + public HarlowTMLToken(String name) { + this.name = name; + } - public void setName(String name) { - this.name = name; - } + public String getName() { + return name; + } - public String toString() { - return ""; - } + public void setName(String name) { + this.name = name; + } + + public String toString() { + return ""; + } } diff --git a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTokenizer.java b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTokenizer.java index 73aff48..2495ab5 100644 --- a/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTokenizer.java +++ b/src/main/java/best/tigers/tynk_dialog/game/harlowtml/HarlowTMLTokenizer.java @@ -6,170 +6,175 @@ import java.util.ArrayList; public class HarlowTMLTokenizer { - public class TokenizerException extends Throwable { - private String cause; - public TokenizerException(String cause) { - super(); - this.cause = cause; - } - - @Override - public String getMessage() { - return ("Error while tokenizing tag at position #" - + Integer.valueOf(currentPosition).toString() + ": " - + this.cause); - } + private Reader input; + private char[] ch; + private int currentCharacter; + private State currentState; + private int currentPosition; + private HarlowTMLTagToken currentTag; + private ArrayList tokens; + + public HarlowTMLTokenizer(Reader input) throws IOException { + this.input = input; + this.currentCharacter = input.read(); + this.currentState = State.DATA; + this.currentPosition = 0; + this.tokens = new ArrayList<>(); + } + + public ArrayList tokenize() throws TokenizerException { + proceed(); + return tokens; + } + + private void proceed() throws TokenizerException { + try { + switch (currentState) { + case DATA: + data(); + break; + case TAG_OPEN: + tagOpen(); + break; + case END_TAG_OPEN: + endTagOpen(); + break; + case TAG_NAME: + tagName(); + break; + case TAG_VALUE: + tagValue(); + break; + } + } catch (IOException e) { + return; } + } - - public enum State { - DATA, TAG_OPEN, END_TAG_OPEN, TAG_NAME, TAG_VALUE - } - - private Reader input; - private char[] ch; - private int currentCharacter; - private State currentState; - private int currentPosition; - private HarlowTMLTagToken currentTag; - private ArrayList tokens; - - public HarlowTMLTokenizer(Reader input) throws IOException { - this.input = input; - this.currentCharacter = input.read(); - this.currentState = State.DATA; - this.currentPosition = 0; - this.tokens = new ArrayList<>(); + public char getch() throws EOFException { + if (currentCharacter == -1) { + throw new EOFException("End of input reached"); } + return (char) currentCharacter; + } - public ArrayList tokenize() throws TokenizerException{ - proceed(); - return tokens; - } - - private void proceed() throws TokenizerException { - try { - switch (currentState) { - case DATA: - data(); - break; - case TAG_OPEN: - tagOpen(); - break; - case END_TAG_OPEN: - endTagOpen(); - break; - case TAG_NAME: - tagName(); - break; - case TAG_VALUE: - tagValue(); - break; - } - } - catch (IOException e) { - return; - } - } + public void setState(State newState) { + this.currentState = newState; + } - public char getch() throws EOFException { - if (currentCharacter == -1) { - throw new EOFException("End of input reached"); - } - return (char) currentCharacter; + public char consume() throws IOException { + int temp = currentCharacter; + if (temp == -1) { + throw new EOFException("End of input reached"); } - - public void setState(State newState) { - this.currentState = newState; + currentCharacter = input.read(); + return (char) temp; + } + + public void data() throws TokenizerException, IOException { + var c = consume(); + switch (c) { + case '<': + setState(State.TAG_OPEN); + break; + default: + tokens.add(new HarlowTMLCharacterToken(c)); } - - public char consume() throws IOException { - int temp = currentCharacter; - if (temp == -1) { - throw new EOFException("End of input reached"); - } - currentCharacter = input.read(); - return (char) temp; + proceed(); + } + + public void tagOpen() throws TokenizerException, IOException { + var c = getch(); + switch (c) { + case '/': + consume(); + setState(State.END_TAG_OPEN); + break; + case '>': + throw new TokenizerException("The opening tag ended before a name was specified"); + case '=': + throw new TokenizerException( + "The opening tag tried to define a value without having a name"); + default: + currentTag = new HarlowTMLTagToken(HarlowTMLTagToken.TagType.OPEN); + setState(State.TAG_NAME); } - - public void data() throws TokenizerException, IOException { - var c = consume(); - switch (c) { - case '<': - setState(State.TAG_OPEN); - break; - default: - tokens.add(new HarlowTMLCharacterToken(c)); - } - proceed(); + proceed(); + } + + public void endTagOpen() throws TokenizerException, IOException { + var c = getch(); + switch (c) { + case '>': + throw new TokenizerException("The closing tag ended before a name was specified"); + case '=': + throw new TokenizerException("The closing tag tried to define a value"); + default: + currentTag = new HarlowTMLTagToken(HarlowTMLTagToken.TagType.CLOSE); + setState(State.TAG_NAME); } - - public void tagOpen() throws TokenizerException, IOException { - var c = getch(); - switch (c) { - case '/': - consume(); - setState(State.END_TAG_OPEN); - break; - case '>': - throw new TokenizerException("The opening tag ended before a name was specified"); - case '=': - throw new TokenizerException("The opening tag tried to define a value without having a name"); - default: - currentTag = new HarlowTMLTagToken(HarlowTMLTagToken.TagType.OPEN); - setState(State.TAG_NAME); - } - proceed(); + proceed(); + } + + public void tagName() throws TokenizerException, IOException { + char c = consume(); + switch (c) { + case '=': + setState(State.TAG_VALUE); + break; + case '>': + tokens.add(currentTag); + currentTag = null; + setState(State.DATA); + break; + case '<': + throw new TokenizerException("Attempted to open a new tag while inside of a tag"); + default: + currentTag.setTagName(currentTag.getTagName() + c); + break; } - - public void endTagOpen() throws TokenizerException, IOException { - var c = getch(); - switch (c) { - case '>': - throw new TokenizerException("The closing tag ended before a name was specified"); - case '=': - throw new TokenizerException("The closing tag tried to define a value"); - default: - currentTag = new HarlowTMLTagToken(HarlowTMLTagToken.TagType.CLOSE); - setState(State.TAG_NAME); - } - proceed(); + proceed(); + } + + public void tagValue() throws TokenizerException, IOException { + var c = consume(); + switch (c) { + case '=': + throw new TokenizerException("Encountered an unexpected equals sign in the tag's value"); + case '>': + tokens.add(currentTag); + currentTag = null; + setState(State.DATA); + break; + default: + currentTag.setTagValue(currentTag.getTagValue() + c); + break; } - - public void tagName() throws TokenizerException, IOException { - char c = consume(); - switch (c) { - case '=': - setState(State.TAG_VALUE); - break; - case '>': - tokens.add(currentTag); - currentTag = null; - setState(State.DATA); - break; - case '<': - throw new TokenizerException("Attempted to open a new tag while inside of a tag"); - default: - currentTag.setTagName(currentTag.getTagName() + c); - break; - } - proceed(); + proceed(); + } + + public enum State { + DATA, + TAG_OPEN, + END_TAG_OPEN, + TAG_NAME, + TAG_VALUE + } + + public class TokenizerException extends Throwable { + private String cause; + + public TokenizerException(String cause) { + super(); + this.cause = cause; } - public void tagValue() throws TokenizerException, IOException { - var c = consume(); - switch (c) { - case '=': - throw new TokenizerException("Encountered an unexpected equals sign in the tag's value"); - case '>': - tokens.add(currentTag); - currentTag = null; - setState(State.DATA); - break; - default: - currentTag.setTagValue(currentTag.getTagValue() + c); - break; - } - proceed(); + @Override + public String getMessage() { + return ("Error while tokenizing tag at position #" + + Integer.valueOf(currentPosition).toString() + + ": " + + this.cause); } + } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/Assets.java b/src/main/java/best/tigers/tynk_dialog/gui/Assets.java index cb58652..414914e 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/Assets.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/Assets.java @@ -1,15 +1,21 @@ package best.tigers.tynk_dialog.gui; import best.tigers.tynk_dialog.util.Log; - -import javax.imageio.ImageIO; -import javax.swing.*; -import javax.swing.text.DefaultEditorKit; -import java.awt.*; +import java.awt.Desktop; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.awt.Image; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import javax.imageio.ImageIO; +import javax.swing.InputMap; +import javax.swing.KeyStroke; +import javax.swing.UIManager; +import javax.swing.text.DefaultEditorKit; public class Assets { public static final String APPLICATION_NAME = "Tynk Dialog Editor"; @@ -23,10 +29,9 @@ public class Assets { private Assets() { ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("terminus.ttf").getFile()); - terminus = new Font ("Terminus (TTF)", 0, 20); + terminus = new Font("Terminus (TTF)", 0, 20); try { - GraphicsEnvironment ge = - GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, file)); BufferedImage timer = ImageIO.read(classLoader.getResource("timer.png").openStream()); System.out.println(timer.getWidth()); @@ -35,10 +40,6 @@ private Assets() { } } - public Image getTimer() { - return timer; - } - public static Assets getInstance() { if (singleInstance == null) { singleInstance = new Assets(); @@ -46,15 +47,18 @@ public static Assets getInstance() { return singleInstance; } - public Font getFont() { - return terminus; - } - private static void addOSXKeyStrokes(InputMap inputMap) { - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.META_DOWN_MASK), DefaultEditorKit.copyAction); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.META_DOWN_MASK), DefaultEditorKit.cutAction); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), DefaultEditorKit.pasteAction); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.META_DOWN_MASK), DefaultEditorKit.selectAllAction); + inputMap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.META_DOWN_MASK), + DefaultEditorKit.copyAction); + inputMap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.META_DOWN_MASK), DefaultEditorKit.cutAction); + inputMap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), + DefaultEditorKit.pasteAction); + inputMap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.META_DOWN_MASK), + DefaultEditorKit.selectAllAction); } public static void runIntegrations() { @@ -73,6 +77,13 @@ public static void runIntegrations() { addOSXKeyStrokes((InputMap) UIManager.get("Table.ancestorInputMap")); addOSXKeyStrokes((InputMap) UIManager.get("Tree.focusInputMap")); } + } + + public Image getTimer() { + return timer; + } + public Font getFont() { + return terminus; } -} \ No newline at end of file +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogController.java b/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogController.java index 4aff651..131e9f1 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogController.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogController.java @@ -1,67 +1,78 @@ package best.tigers.tynk_dialog.gui.controller; +import best.tigers.tynk_dialog.game.DialogPage; import best.tigers.tynk_dialog.gui.model.DialogModel; import best.tigers.tynk_dialog.gui.model.DialogPageModel; -import best.tigers.tynk_dialog.gui.model.DialogPageTableModel; import best.tigers.tynk_dialog.gui.view.DialogEditorView; - -import javax.swing.*; -import java.awt.event.*; +import best.tigers.tynk_dialog.gui.view.components.AutoResizingTable; + +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.KeyStroke; public class DialogController { private final DialogEditorView view; private final DialogModel model; - private final Runnable runner; - public DialogController(DialogModel model) { + private DialogController(DialogModel model) { this.model = model; - runner = new Runnable() { - public void run() { - saveTitle(); - } - }; - view = new DialogEditorView(model) - .addEditorAction(new EditAction(), "Edit page...") - .addEditorAction(new AddAction(), "Add page...") - .addEditorAction(new DeleteAction(), "Delete page") - .addEditorAction(new SwapUpAction(), "Move up") - .addEditorAction(new SwapDownAction(), "Move down") - .init(); - view.attachFocusListener(runner); - //JList list = view.getList(); - DialogPageTableModel list = view.getDptm(); - JTable dpt = view.getList(); - MouseListener doubleClickAdapter = new MouseAdapter() { + view = DialogEditorView.fromModel(model); + } + + public static DialogController fromModel(DialogModel model) { + var controller = new DialogController(model); + controller.initDialogController(); + return controller; + } + + public static DialogController newModel() { + return DialogController.fromModel(new DialogModel()); + } + + private void initDialogController() { + // Setup view and shortcuts + var ctrlN = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK, true); + var ctrlNKey = "Ctrl+N released"; + view.attachFunctionalKeyboardShortcut(ctrlN, ctrlNKey, this::addPage); + view.addEditorActions(new EditAction(), new AddAction(), new DeleteAction(), new SwapUpAction(), new SwapDownAction()); + view.attachFocusListener(this::saveTitle); + + var table = view.getTable(); + table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + var doubleClickAdapter = buildDoubleClickAdapter(); + table.addMouseListener(doubleClickAdapter); + var enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); + var enterMapKey = "Enter"; + table.attachFunctionalKeyboardShortcut(enterKey, enterMapKey, this::editPage); + } + + + MouseAdapter buildDoubleClickAdapter() { + return new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - int index = dpt.rowAtPoint(e.getPoint()); - if (index < 0) { - addPage(); - } else { - DialogPageController.editModel(model.getElementAt(index)); - } + // escape if this isn't a double click + if (e.getClickCount() != 2) { + return; + } + var table = view.getTable(); + int index = table.rowAtPoint(e.getPoint()); + // add a new page if the user clicked outside the rows + if (index < 0) { + addPage(); + return; } - } - }; - dpt.addMouseListener(doubleClickAdapter); - dpt.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); - dpt.getActionMap().put("Enter", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent ae) { editPage(); } - }); - dpt.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); - dpt.getColumnModel().getColumn(0).setPreferredWidth(20); - dpt.getTableHeader().setResizingAllowed(true); - dpt.getTableHeader().setReorderingAllowed(false); - view.getPanel().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK, true), "Ctrl+N released"); - view.getPanel().getActionMap().put("Ctrl+N released", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent ae) { - addPage(); - }}); + }; } public JPanel getPanel() { @@ -73,39 +84,78 @@ public DialogModel getModel() { } public void swapUp() { - DialogPageModel page = view.getSelectedPage(); + var page = view.getSelectedPage(); int pageIndex = model.getPageIndex(page); - if (pageIndex > 0) { - model.swapListItems(pageIndex, pageIndex - 1); + // escape if we're at the top or if no page is selected + if (pageIndex <= 0) { + return; } + model.swapListItems(pageIndex, pageIndex - 1); view.selectPage(pageIndex - 1); } public void swapDown() { - DialogPageModel page = view.getSelectedPage(); + var page = view.getSelectedPage(); int pageIndex = model.getPageIndex(page); - if (pageIndex < (model.getPageCount() - 1)) { - model.swapListItems(pageIndex, pageIndex + 1); + // escape if we're at the bottom or if no page is selected + if (pageIndex >= model.getPageCount() - 1 || pageIndex < 0) { + return; } + model.swapListItems(pageIndex, pageIndex + 1); view.selectPage(pageIndex + 1); } public void saveTitle() { - String newTitle = view.getTitle(); + var newTitle = view.getTitle(); model.setTitle(newTitle); } - public void addPage() { - DialogPageModel newModel = new DialogPageModel(); - model.addPage(DialogPageController.createModel()); - view.getList().revalidate(); + var newModel = new DialogPageModel(); + model.addPage(newModel); + var newController = DialogPageController.fromModel(newModel); + var newView = newController.getView(); + newView.attachContinueAction(() -> { + newController.saveAndExit(); + this.duplicateAndEditPage(newModel); + }); + revalidateTable(); + } + + public void duplicateAndEditPage(DialogPageModel oldModel) { + var newModel = new DialogPageModel(); + newModel.setSpeaker(oldModel.getSpeaker()); + newModel.setBlip(oldModel.getBlip()); + newModel.setBlipEnabled(oldModel.getBlipEnabled()); + newModel.setStyleEnabled(oldModel.getStyleEnabled()); + newModel.setTextBoxStyle(oldModel.getTextBoxStyle()); + model.addPage(newModel); + var oldIndex = model.getPageIndex(oldModel); + var newIndex = model.getPageIndex(newModel); + while (newIndex > oldIndex + 1) { + System.out.println(newIndex); + System.out.println(oldIndex); + model.swapListItems(newIndex--, newIndex); + } + var newController = DialogPageController.fromModelProceeding(newModel); + var newView = newController.getView(); + newView.attachContinueAction(() -> { + newController.saveAndExit(); + this.duplicateAndEditPage(newModel); + }); + newView.getContentField().requestFocus(); + revalidateTable(); } public void editPage() { - DialogPageModel selectedModel = view.getSelectedModel(); + var selectedModel = view.getSelectedModel(); if (selectedModel != null) { - DialogPageController.editModel(selectedModel); + var newController = DialogPageController.fromModel(selectedModel); + var newView = newController.getView(); + newView.attachContinueAction(() -> { + newController.saveAndExit(); + this.duplicateAndEditPage(selectedModel); + }); } else { java.awt.Toolkit.getDefaultToolkit().beep(); } @@ -117,19 +167,15 @@ public void deletePage() { } else { java.awt.Toolkit.getDefaultToolkit().beep(); } - view.getList().revalidate(); + revalidateTable(); } - class SaveAction extends AbstractAction { - public SaveAction() { - putValue(Action.NAME, "Save Changes"); - putValue(Action.SHORT_DESCRIPTION, "Save the changes made to this dialog file's title"); - } + private void revalidateTable() { + view.getTable().revalidate(); + } - @Override - public void actionPerformed(ActionEvent e) { - saveTitle(); - } + public String toString() { + return this.model.getTitle(); } class AddAction extends AbstractAction { @@ -174,7 +220,9 @@ public SwapUpAction() { putValue(Action.SHORT_DESCRIPTION, "Move the selected page up one spot"); } - public void actionPerformed(ActionEvent e) {swapUp();} + public void actionPerformed(ActionEvent e) { + swapUp(); + } } class SwapDownAction extends AbstractAction { @@ -183,10 +231,8 @@ public SwapDownAction() { putValue(Action.SHORT_DESCRIPTION, "Move the selected page down one spot"); } - public void actionPerformed(ActionEvent e) {swapDown();} - } - - public String toString() { - return this.model.getTitle(); + public void actionPerformed(ActionEvent e) { + swapDown(); + } } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogPageController.java b/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogPageController.java index ecbc691..ab28e91 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogPageController.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/controller/DialogPageController.java @@ -1,32 +1,111 @@ package best.tigers.tynk_dialog.gui.controller; import best.tigers.tynk_dialog.gui.model.DialogPageModel; +import best.tigers.tynk_dialog.gui.text.HarlowTMLEditorKit; import best.tigers.tynk_dialog.gui.view.DialogPageEditorView; -import javax.swing.*; -import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; +import java.security.Key; +import javax.swing.KeyStroke; + +import static java.awt.event.WindowEvent.WINDOW_CLOSING; public class DialogPageController { private final DialogPageEditorView view; - private DialogPageModel model; + private final DialogPageModel model; private DialogPageController(DialogPageModel model) { this.model = model; view = new DialogPageEditorView(model).init(); - view.getPanel().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) - .put(KeyStroke.getKeyStroke( - KeyEvent.VK_ENTER, - InputEvent.SHIFT_DOWN_MASK, - true), - "Shift+Enter released"); - view.getPanel().getActionMap().put("Shift+Enter released", new SaveAction()); - view.attachSaveFunction(new SaveAction()); + } + + private DialogPageController(DialogPageModel model, boolean proceeding) { + this.model = model; + view = DialogPageEditorView.fromModelProceeding(model).init(); + } + + public DialogPageEditorView getView() { + return view; + } + + private void setupViewShortcuts() { + var enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK, true); + var enterMapKey = "Shift+Enter released"; + + view.attachFunctionalKeyboardShortcut(enterKey, enterMapKey, this::saveAndExit); + view.attachSaveAction(this::saveAndExit); + + var oneKey = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.CTRL_DOWN_MASK, true); + var oneMapKey = "One+Enter released"; + view.attachKeyboardShortcut(oneKey, oneMapKey, HarlowTMLEditorKit.DELAY_ACTION_FIVE); + + var twoKey = KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.CTRL_DOWN_MASK, true); + var twoMapKey = "Two+Enter released"; + view.attachKeyboardShortcut(twoKey, twoMapKey, HarlowTMLEditorKit.DELAY_ACTION_FIFTEEN); + + var threeKey = KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.CTRL_DOWN_MASK, true); + var threeMapKey = "Three+Enter released"; + view.attachKeyboardShortcut(threeKey, threeMapKey, HarlowTMLEditorKit.DELAY_ACTION_SIXTY); + + view.getEditorKit().getColorActions().forEach(a -> { + var keyStroke = a.getShortcutKey(); + var keyMapName = a.getKeyMapName(); + view.attachKeyboardShortcut(keyStroke, keyMapName, a); + }); + + view.getEditorKit().getBehaviorActions().forEach(a -> { + var keystroke = a.getShortcutKey(); + var keyMapName = a.getKeyMapName(); + view.attachKeyboardShortcut(keystroke, keyMapName, a); + }); + } + + private void saveChanges() { + javax.swing.ToolTipManager.sharedInstance().setInitialDelay(1000); + String newSpeaker = view.getSpeaker(); + String newContent = view.getContent(); + String newBlip = view.getBlip(); + String newStyle = view.getStyle(); + boolean blipEnabled = view.getBlipEnabled(); + boolean styleEnabled = view.getStyleEnabled(); + if (!model.getSpeaker().equals(newSpeaker)) { + model.setSpeaker(newSpeaker); + } + if (!model.getContent().equals(newContent)) { + model.setContent(newContent); + } + if (model.getBlipEnabled() != blipEnabled) { + model.setBlipEnabled(blipEnabled); + } + if (model.getBlipEnabled()) { + model.setBlip(newBlip); + } + if (model.getStyleEnabled() != styleEnabled) { + model.setStyleEnabled(styleEnabled); + } + if (model.getStyleEnabled()) { + model.setTextBoxStyle(newStyle); + } + } + + public void saveAndExit() { + saveChanges(); + view.getPanel().dispatchEvent(new WindowEvent(view.getFrame(), WINDOW_CLOSING)); + view.getFrame().dispose(); } public static DialogPageController fromModel(DialogPageModel model) { - return new DialogPageController(model); + var controller = new DialogPageController(model); + controller.setupViewShortcuts(); + return controller; + } + + public static DialogPageController fromModelProceeding(DialogPageModel model) { + var controller = new DialogPageController(model, true); + controller.setupViewShortcuts(); + return controller; } public static DialogPageController fromNewModel() { @@ -42,35 +121,4 @@ public static DialogPageModel createModel() { DialogPageController.editModel(model); return model; } - - class SaveAction extends AbstractAction { - @Override - public void actionPerformed(ActionEvent e) { - javax.swing.ToolTipManager.sharedInstance().setInitialDelay(1000); - String newSpeaker = view.getSpeaker(); - String newContent = view.getContent(); - String newBlip = view.getBlip(); - String newStyle = view.getStyle(); - boolean blipEnabled = view.getBlipEnabled(); - boolean styleEnabled = view.getStyleEnabled(); - if (!model.getSpeaker().equals(newSpeaker)) { - model.setSpeaker(newSpeaker); - } - if (!model.getContent().equals(newContent)) { - model.setContent(newContent); - } - if (model.getBlipEnabled() != blipEnabled) { - model.setBlipEnabled(blipEnabled); - } - if (model.getBlipEnabled()) { - model.setBlip(newBlip); - } - if (model.getStyleEnabled() != styleEnabled) { - model.setStyleEnabled(styleEnabled); - } - if (model.getStyleEnabled()) { - model.setTextBoxStyle(newStyle); - } - } - } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/controller/NotSavedDialog.java b/src/main/java/best/tigers/tynk_dialog/gui/controller/NotSavedDialog.java index 9fde118..59d2b36 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/controller/NotSavedDialog.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/controller/NotSavedDialog.java @@ -1,20 +1,19 @@ package best.tigers.tynk_dialog.gui.controller; -import javax.swing.*; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; public class NotSavedDialog { private JDialog dialog; - public enum Decision { - SAVE_IN_PLACE, - SAVE_AS, - CONTINUE_WITHOUT_SAVING, - CANCEL_OPERATION - } public NotSavedDialog() { dialog = new JDialog(); dialog.setModal(true); - JLabel message = new JLabel("Your changes have not been saved to disk. What would you like to do?"); + JLabel message = + new JLabel("Your changes have not been saved to disk. What would you like to do?"); JButton cancelButton = new JButton("Cancel"); JButton saveButton = new JButton("Save"); JButton saveAsButton = new JButton("Save As"); @@ -36,4 +35,11 @@ public Decision show() { dialog.setVisible(true); return Decision.CANCEL_OPERATION; } + + public enum Decision { + SAVE_IN_PLACE, + SAVE_AS, + CONTINUE_WITHOUT_SAVING, + CANCEL_OPERATION + } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/controller/PrimaryListController.java b/src/main/java/best/tigers/tynk_dialog/gui/controller/PrimaryListController.java index cc3a473..ca966fa 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/controller/PrimaryListController.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/controller/PrimaryListController.java @@ -9,14 +9,13 @@ import best.tigers.tynk_dialog.gui.view.components.MenuBar; import best.tigers.tynk_dialog.util.DialogFile; import best.tigers.tynk_dialog.util.Log; - -import javax.swing.*; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.util.ArrayList; import java.util.prefs.Preferences; +import javax.swing.JFileChooser; public class PrimaryListController { private Preferences prefs = Preferences.userRoot().node(this.getClass().getName()); @@ -26,45 +25,51 @@ public class PrimaryListController { public PrimaryListController(ArrayList dialogFiles) { model = new PrimaryListModel(dialogFiles); - view = new PrimaryListView(model); + view = PrimaryListView.fromModel(model); fileHandle = new DialogFile(); - addMenuItem(e -> addDialog(), + addMenuItem( + e -> addDialog(), "Add DialogFile", "Adds a DialogFile to the list, which may be populated with individual Pages", - MenuBar.Menu.EDIT - ); - addMenuItem(e -> removeCurrentDialog(), + MenuBar.Menu.EDIT); + addMenuItem( + e -> removeCurrentDialog(), "Remove selected DialogFile", "Removes the DialogFile that is highlighted in the list on the left", - MenuBar.Menu.EDIT - ); - addMenuItem(e -> newFile(), + MenuBar.Menu.EDIT); + addMenuItem( + e -> newFile(), "New file", "Creates a new JSON dialog file for editing", MenuBar.Menu.FILE); - addMenuItem(e -> openFile(), + addMenuItem( + e -> openFile(), "Open file", "Open a JSON dialog file from disk for editing", MenuBar.Menu.FILE); - addMenuItem(e -> saveInPlace(), - "Save", - "Save the current file in place", - MenuBar.Menu.FILE); - addMenuItem(e -> saveAs(), + addMenuItem(e -> saveInPlace(), "Save", "Save the current file in place", MenuBar.Menu.FILE); + addMenuItem( + e -> saveAs(), "Save as...", "Select a new location and name for the current file", MenuBar.Menu.FILE); - view.attachWindowEvent(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - exitOperation(); - } - }); - } + view.attachWindowEvent( + new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + exitOperation(); + } + }); + } - public PrimaryListController() { + public PrimaryListController() { this(new ArrayList<>()); - } + } + + public static void launch() { + var primaryController = new PrimaryListController(); + return; + } public void exitOperation() { int response = view.prompt(); @@ -124,25 +129,24 @@ public void openFile() { view.update(); } - public void addMenuItem(ActionListener action, String shortText, String longText, MenuBar.Menu menu) { + public void addMenuItem( + ActionListener action, String shortText, String longText, MenuBar.Menu menu) { view.addMenuItem(action, shortText, longText, menu); } public void addDialog() { - DialogModel newDialog = new DialogModel(); + var newPanel = DialogController.newModel(); if (!view.getCurrentRoom().equals("")) { - newDialog.setTitle(view.getCurrentRoom()); + newPanel.getModel().setTitle(view.getCurrentRoom()); } - DialogController newPanel = new DialogController(newDialog); model.addDialog(newPanel); } public void removeCurrentDialog() { DialogController selected = view.currentSelection(); if (selected != null) { - DialogController currentSelection = selected; view.getDialogList().setSelectedValue(selected, false); - model.deleteDialog(currentSelection); + model.deleteDialog(selected); } } @@ -163,8 +167,7 @@ public void saveInPlace() { } catch (IOException e) { e.printStackTrace(); } - } - else { + } else { saveAs(); } } @@ -175,9 +178,4 @@ public void saveAs() { fileHandle.setPath(newPath); saveInPlace(); } - - public static void launch() { - var primaryController = new PrimaryListController(); - return; - } -} \ No newline at end of file +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/JSONFilter.java b/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/JSONFilter.java index c8bd5d3..741cc74 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/JSONFilter.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/JSONFilter.java @@ -1,7 +1,7 @@ package best.tigers.tynk_dialog.gui.controller.filters; -import javax.swing.filechooser.FileFilter; import java.io.File; +import javax.swing.filechooser.FileFilter; public class JSONFilter extends FileFilter { @Override diff --git a/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/TextFilter.java b/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/TextFilter.java index 8f1635a..83c7055 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/TextFilter.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/controller/filters/TextFilter.java @@ -1,7 +1,7 @@ package best.tigers.tynk_dialog.gui.controller.filters; -import javax.swing.filechooser.FileFilter; import java.io.File; +import javax.swing.filechooser.FileFilter; public class TextFilter extends FileFilter { @Override diff --git a/src/main/java/best/tigers/tynk_dialog/gui/model/AbstractModel.java b/src/main/java/best/tigers/tynk_dialog/gui/model/AbstractModel.java index 294b939..5e4c3ac 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/model/AbstractModel.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/model/AbstractModel.java @@ -1,27 +1,26 @@ package best.tigers.tynk_dialog.gui.model; -import best.tigers.tynk_dialog.gui.view.Observer; - +import best.tigers.tynk_dialog.gui.view.TObserver; import java.util.ArrayList; public abstract class AbstractModel { - private final ArrayList observers; + private final ArrayList TObservers; public AbstractModel() { - observers = new ArrayList<>(); + TObservers = new ArrayList<>(); } - public void attachSubscriber(Observer observer) { - observers.add(observer); + public void attachSubscriber(TObserver TObserver) { + TObservers.add(TObserver); } - public void detachSubscriber(Observer observer) { - observers.remove(observer); + public void detachSubscriber(TObserver TObserver) { + TObservers.remove(TObserver); } public void notifySubscribers() { - for (Observer observer : observers) { - observer.update(); + for (TObserver TObserver : TObservers) { + TObserver.update(); } } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/model/DialogModel.java b/src/main/java/best/tigers/tynk_dialog/gui/model/DialogModel.java index 6451d18..9bc968c 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/model/DialogModel.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/model/DialogModel.java @@ -2,18 +2,17 @@ import best.tigers.tynk_dialog.game.Dialog; import best.tigers.tynk_dialog.game.DialogPage; -import best.tigers.tynk_dialog.gui.view.Observer; - -import javax.swing.*; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; +import best.tigers.tynk_dialog.gui.view.TObserver; import java.util.ArrayList; import java.util.Collections; +import javax.swing.ListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; -public class DialogModel extends AbstractModel implements ListModel, Observer { +public class DialogModel extends AbstractModel implements ListModel, TObserver { private final ArrayList pages; - private DialogPageTableModel dptm; private final ArrayList listDataListeners; + private DialogPageTableModel dptm; private String title; public DialogModel() { @@ -61,7 +60,8 @@ public void addListDataListener(ListDataListener l) { } public void notifyListeners() { - ListDataEvent event = new ListDataEvent(pages, ListDataEvent.CONTENTS_CHANGED, 0, pages.size() - 1); + ListDataEvent event = + new ListDataEvent(pages, ListDataEvent.CONTENTS_CHANGED, 0, pages.size() - 1); for (ListDataListener listener : listDataListeners) { listener.contentsChanged(event); } @@ -93,8 +93,7 @@ public void setTitleSuppressed(String newTitle) { } public void swapListItems(int index1, int index2) { - if (index2 < pages.size() && index1 >= 0) - Collections.swap(pages, index1, index2); + if (index2 < pages.size() && index1 >= 0) Collections.swap(pages, index1, index2); notifyListeners(); } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageModel.java b/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageModel.java index a3fffb2..c4affce 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageModel.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageModel.java @@ -1,7 +1,6 @@ package best.tigers.tynk_dialog.gui.model; import best.tigers.tynk_dialog.game.DialogPage; - import javax.json.JsonObject; public class DialogPageModel extends AbstractModel { @@ -51,21 +50,23 @@ public void setBlip(String newBlip) { notifySubscribers(); } + public boolean getBlipEnabled() { + return blipEnabled; + } + public void setBlipEnabled(boolean newState) { blipEnabled = newState; dialogPage.setBlip(null); } - public boolean getBlipEnabled() { - return blipEnabled; + + public boolean getStyleEnabled() { + return styleEnabled; } public void setStyleEnabled(boolean newState) { styleEnabled = newState; dialogPage.setTextBoxStyle(null); } - public boolean getStyleEnabled() { - return styleEnabled; - } public String getTextBoxStyle() { return dialogPage.getTextBoxStyle(); diff --git a/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageTableModel.java b/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageTableModel.java index 9328668..45f1e67 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageTableModel.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/model/DialogPageTableModel.java @@ -1,86 +1,82 @@ package best.tigers.tynk_dialog.gui.model; -import javax.swing.table.AbstractTableModel; import java.util.ArrayList; import java.util.List; +import javax.swing.table.AbstractTableModel; public class DialogPageTableModel extends AbstractTableModel { - private List pages; + private List pages; - public DialogPageTableModel(List pages) { + public DialogPageTableModel(List pages) { - this.pages = new ArrayList(pages); - } + this.pages = new ArrayList(pages); + } - @Override - public int getRowCount() { - return pages.size(); - } + @Override + public int getRowCount() { + return pages.size(); + } - @Override - public int getColumnCount() { - return 2; - } + @Override + public int getColumnCount() { + return 2; + } - @Override - public String getColumnName(int columnIndex) { - switch(columnIndex) { - case 0: - return "Character"; - case 1: - return "Text"; - } - return "ERROR"; + @Override + public String getColumnName(int columnIndex) { + switch (columnIndex) { + case 0: + return "Character"; + case 1: + return "Text"; } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - - Object value = "??"; - DialogPageModel page = pages.get(rowIndex); - switch (columnIndex) { - case 0: - value = page.getSpeaker(); - break; - case 1: - value = page.getContent(); - break; - } - - return value; - + return "ERROR"; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + + Object value = "??"; + DialogPageModel page = pages.get(rowIndex); + switch (columnIndex) { + case 0: + value = page.getSpeaker(); + break; + case 1: + value = page.getContent(); + break; } - @Override - public Class getColumnClass(int columnIndex) { - return String.class; + return value; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } + + /* Override this if you want the values to be editable... + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + //.... + } + */ + + /* + * This will return the user at the specified row... + * @param row + * @return DialogPageModel + */ + public DialogPageModel getPageAt(int row) { + if (row >= 0 && row < pages.size()) return pages.get(row); + else { + return null; } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return false; - } - - /* Override this if you want the values to be editable... - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - //.... - } - */ - - /* - * This will return the user at the specified row... - * @param row - * @return DialogPageModel - */ - public DialogPageModel getPageAt(int row) { - if (row >= 0 && row < pages.size()) - return pages.get(row); - else { - return null; - } - } - + } } - diff --git a/src/main/java/best/tigers/tynk_dialog/gui/model/PrimaryListModel.java b/src/main/java/best/tigers/tynk_dialog/gui/model/PrimaryListModel.java index c463c9f..7dcff61 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/model/PrimaryListModel.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/model/PrimaryListModel.java @@ -2,18 +2,18 @@ import best.tigers.tynk_dialog.game.Dialog; import best.tigers.tynk_dialog.gui.controller.DialogController; -import best.tigers.tynk_dialog.gui.view.Observer; - -import javax.swing.*; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; +import best.tigers.tynk_dialog.gui.view.TObserver; import java.util.ArrayList; import java.util.Collections; +import javax.swing.ListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; -public class PrimaryListModel extends AbstractModel implements ListModel, Observer { +public class PrimaryListModel extends AbstractModel + implements ListModel, TObserver { + private static final String BLANK_PATH = "(New file)"; private final ArrayList dialogFiles; private final ArrayList listDataListeners; - final private static String BLANK_PATH = "(New file)"; private String title; private String path; private boolean modified; @@ -23,10 +23,20 @@ public PrimaryListModel() { } public PrimaryListModel(ArrayList dialogs) { - this (new ArrayList<>(), BLANK_PATH); + this(new ArrayList<>(), BLANK_PATH); modified = false; } + public PrimaryListModel(ArrayList dialogs, String path) { + this.path = path; + dialogFiles = new ArrayList<>(); + listDataListeners = new ArrayList<>(); + for (Dialog dialog : dialogs) { + DialogModel dialogModel = new DialogModel(dialog); + addDialog(DialogController.fromModel(dialogModel)); + } + } + public boolean isModified() { return modified; } @@ -35,22 +45,12 @@ public void setModified(boolean modified) { this.modified = modified; } - public void setPath(String newPath) { - this.path = newPath; - } - public String getPath() { return path; } - public PrimaryListModel(ArrayList dialogs, String path) { - this.path = path; - dialogFiles = new ArrayList<>(); - listDataListeners = new ArrayList<>(); - for (Dialog dialog : dialogs) { - DialogModel dialogModel = new DialogModel(dialog); - addDialog(new DialogController(dialogModel)); - } + public void setPath(String newPath) { + this.path = newPath; } public void addDialog(DialogController newDialog) { @@ -71,10 +71,8 @@ public int getSize() { @Override public DialogController getElementAt(int index) { - if (index >= 0 && index <= dialogFiles.size() - 1) - return dialogFiles.get(index); - else - return null; + if (index >= 0 && index <= dialogFiles.size() - 1) return dialogFiles.get(index); + else return null; } @Override @@ -84,7 +82,8 @@ public void addListDataListener(ListDataListener l) { public void notifyListeners() { modified = true; - ListDataEvent event = new ListDataEvent(dialogFiles, ListDataEvent.CONTENTS_CHANGED, 0, dialogFiles.size() - 1); + ListDataEvent event = + new ListDataEvent(dialogFiles, ListDataEvent.CONTENTS_CHANGED, 0, dialogFiles.size() - 1); for (ListDataListener listener : listDataListeners) { listener.contentsChanged(event); } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLAttributeMappings.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLAttributeMappings.java index fe7dd67..e886b6f 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLAttributeMappings.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLAttributeMappings.java @@ -1,23 +1,24 @@ package best.tigers.tynk_dialog.gui.text; -import java.awt.*; +import java.awt.Color; import java.util.HashMap; class HarlowTMLAttributeMappings { - private static HashMap colorHashMap = new HashMap<>(); - static { - colorHashMap.put("red", Color.red); - colorHashMap.put("yellow", Color.decode("FFCC02")); - colorHashMap.put("green", Color.green); - colorHashMap.put("blue", Color.blue); - } + private static HashMap colorHashMap = new HashMap<>(); + + static { + colorHashMap.put("red", Color.red); + colorHashMap.put("yellow", Color.decode("FFCC02")); + colorHashMap.put("green", Color.green); + colorHashMap.put("blue", Color.blue); + } - public static Color tynkColorFromString(String input) { - Color out = colorHashMap.get(input); - if (out == null) { - return Color.white; - } else { - return out; - } + public static Color tynkColorFromString(String input) { + Color out = colorHashMap.get(input); + if (out == null) { + return Color.white; + } else { + return out; } + } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLCustomGlyphView.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLCustomGlyphView.java index 377f113..296294f 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLCustomGlyphView.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLCustomGlyphView.java @@ -1,172 +1,182 @@ package best.tigers.tynk_dialog.gui.text; -import javax.swing.*; -import javax.swing.text.*; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import javax.swing.UIManager; +import javax.swing.text.Element; +import javax.swing.text.GlyphView; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; +import javax.swing.text.LayeredHighlighter; +import javax.swing.text.Segment; +import javax.swing.text.View; public class HarlowTMLCustomGlyphView extends GlyphView { - /** - * Constructs a new view wrapped on an element. - * - * @param elem the element - */ - private byte[] selections; - public HarlowTMLCustomGlyphView(Element elem) { - super(elem); - } + /** + * Constructs a new view wrapped on an element. + * + * @param elem the element + */ + private byte[] selections; - private void initSelections(int p0, int p1) { - int viewPosCount = p1 - p0 + 1; - if (selections == null || viewPosCount > selections.length) { - selections = new byte[viewPosCount]; - return; - } - for (int i = 0; i < viewPosCount; selections[i++] = 0); + public HarlowTMLCustomGlyphView(Element elem) { + super(elem); + } + + private void initSelections(int p0, int p1) { + int viewPosCount = p1 - p0 + 1; + if (selections == null || viewPosCount > selections.length) { + selections = new byte[viewPosCount]; + return; } - @Override - public void paint(Graphics g, Shape a) { - checkPainter(); + for (int i = 0; i < viewPosCount; selections[i++] = 0) + ; + } - boolean paintedText = false; - Component c = getContainer(); - int p0 = getStartOffset(); - int p1 = getEndOffset(); - Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds(); - Color bg = getBackground(); - Color fg = getForeground(); + @Override + public void paint(Graphics g, Shape a) { + checkPainter(); - if (c != null && ! c.isEnabled()) { - fg = (c instanceof JTextComponent ? - ((JTextComponent)c).getDisabledTextColor() : - UIManager.getColor("textInactiveText")); - } - if (bg != null) { - g.setColor(bg); - g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height); - } - if (c instanceof JTextComponent) { - JTextComponent tc = (JTextComponent) c; - Highlighter h = tc.getHighlighter(); - if (h instanceof LayeredHighlighter) { - ((LayeredHighlighter)h).paintLayeredHighlights - (g, p0, p1, a, tc, this); - } - } - - if(c instanceof JTextComponent) { - JTextComponent tc = (JTextComponent) c; - Color selFG = tc.getSelectedTextColor(); + boolean paintedText = false; + Component c = getContainer(); + int p0 = getStartOffset(); + int p1 = getEndOffset(); + Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); + Color bg = getBackground(); + Color fg = getForeground(); - if (// there's a highlighter (bug 4532590), and - (tc.getHighlighter() != null) && - // selected text color is different from regular foreground - (selFG != null) && !selFG.equals(fg)) { + if (c != null && !c.isEnabled()) { + fg = + (c instanceof JTextComponent + ? ((JTextComponent) c).getDisabledTextColor() + : UIManager.getColor("textInactiveText")); + } + if (bg != null) { + g.setColor(bg); + g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height); + } + if (c instanceof JTextComponent) { + JTextComponent tc = (JTextComponent) c; + Highlighter h = tc.getHighlighter(); + if (h instanceof LayeredHighlighter) { + ((LayeredHighlighter) h).paintLayeredHighlights(g, p0, p1, a, tc, this); + } + } - Highlighter.Highlight[] h = tc.getHighlighter().getHighlights(); - if(h.length != 0) { - boolean initialized = false; - int viewSelectionCount = 0; - for (int i = 0; i < h.length; i++) { - Highlighter.Highlight highlight = h[i]; - int hStart = highlight.getStartOffset(); - int hEnd = highlight.getEndOffset(); - if (hStart > p1 || hEnd < p0) { - // the selection is out of this view - continue; - } - if (hStart <= p0 && hEnd >= p1){ - // the whole view is selected - paintTextInColor(g, a, selFG, p0, p1); - paintedText = true; - break; - } - // the array is lazily created only when the view - // is partially selected - if (!initialized) { - initSelections(p0, p1); - initialized = true; - } - hStart = Math.max(p0, hStart); - hEnd = Math.min(p1, hEnd); - paintTextInColor(g, a, selFG, hStart, hEnd); - // the array represents view positions [0, p1-p0+1] - // later will iterate this array and sum its - // elements. Positions with sum == 0 are not selected. - selections[hStart-p0]++; - selections[hEnd-p0]--; + if (c instanceof JTextComponent) { + JTextComponent tc = (JTextComponent) c; + Color selFG = tc.getSelectedTextColor(); - viewSelectionCount++; - } + if ( // there's a highlighter (bug 4532590), and + (tc.getHighlighter() != null) + && + // selected text color is different from regular foreground + (selFG != null) + && !selFG.equals(fg)) { - if (!paintedText && viewSelectionCount > 0) { - // the view is partially selected - int curPos = -1; - int startPos = 0; - int viewLen = p1 - p0; - while (curPos++ < viewLen) { - // searching for the next selection start - while(curPos < viewLen && - selections[curPos] == 0) curPos++; - if (startPos != curPos) { - // paint unselected text - paintTextInColor(g, a, fg, - p0 + startPos, p0 + curPos); - } - int checkSum = 0; - // searching for next start position of unselected text - while (curPos < viewLen && - (checkSum += selections[curPos]) != 0) curPos++; - startPos = curPos; - } - paintedText = true; - } - } + Highlighter.Highlight[] h = tc.getHighlighter().getHighlights(); + if (h.length != 0) { + boolean initialized = false; + int viewSelectionCount = 0; + for (int i = 0; i < h.length; i++) { + Highlighter.Highlight highlight = h[i]; + int hStart = highlight.getStartOffset(); + int hEnd = highlight.getEndOffset(); + if (hStart > p1 || hEnd < p0) { + // the selection is out of this view + continue; } - } - if(!paintedText) - paintTextInColor(g, a, fg, p0, p1); - } - - final void paintTextInColor(Graphics g, Shape a, Color c, int startPosition, int endPosition) { - // render the glyphs - g.setColor(c); - var painter = super.getGlyphPainter(); - painter.paint(this, g, a, startPosition, endPosition); - - // render underline or strikethrough if set. - boolean underline = isUnderline(); - boolean strike = isStrikeThrough(); - if (underline || strike) { - // calculate x coordinates - Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds(); - View parent = getParent(); - if ((parent != null) && (parent.getEndOffset() == endPosition)) { - // strip whitespace on end - Segment segment = getText(startPosition, endPosition); - while (Character.isWhitespace(segment.last())) { - endPosition -= 1; - segment.count -= 1; - } + if (hStart <= p0 && hEnd >= p1) { + // the whole view is selected + paintTextInColor(g, a, selFG, p0, p1); + paintedText = true; + break; } - int x0 = alloc.x; - int p = getStartOffset(); - if (p != startPosition) { - x0 += (int) painter.getSpan(this, p, startPosition, getTabExpander(), x0); + // the array is lazily created only when the view + // is partially selected + if (!initialized) { + initSelections(p0, p1); + initialized = true; } - int x1 = x0 + (int) painter.getSpan(this, startPosition, endPosition, getTabExpander(), x0); + hStart = Math.max(p0, hStart); + hEnd = Math.min(p1, hEnd); + paintTextInColor(g, a, selFG, hStart, hEnd); + // the array represents view positions [0, p1-p0+1] + // later will iterate this array and sum its + // elements. Positions with sum == 0 are not selected. + selections[hStart - p0]++; + selections[hEnd - p0]--; - // calculate y coordinate - int y = alloc.y + (int)(painter.getHeight(this) - painter.getDescent(this)); - if (underline) { - int yTmp = y + 1; - g.drawLine(x0, yTmp, x1, yTmp); - } - if (strike) { - // move y coordinate above baseline - int yTmp = y - (int) (painter.getAscent(this) * 0.3f); - g.drawLine(x0, yTmp, x1, yTmp); + viewSelectionCount++; + } + + if (!paintedText && viewSelectionCount > 0) { + // the view is partially selected + int curPos = -1; + int startPos = 0; + int viewLen = p1 - p0; + while (curPos++ < viewLen) { + // searching for the next selection start + while (curPos < viewLen && selections[curPos] == 0) curPos++; + if (startPos != curPos) { + // paint unselected text + paintTextInColor(g, a, fg, p0 + startPos, p0 + curPos); + } + int checkSum = 0; + // searching for next start position of unselected text + while (curPos < viewLen && (checkSum += selections[curPos]) != 0) curPos++; + startPos = curPos; } + paintedText = true; + } + } + } + } + if (!paintedText) paintTextInColor(g, a, fg, p0, p1); + } + final void paintTextInColor(Graphics g, Shape a, Color c, int startPosition, int endPosition) { + // render the glyphs + g.setColor(c); + var painter = super.getGlyphPainter(); + painter.paint(this, g, a, startPosition, endPosition); + + // render underline or strikethrough if set. + boolean underline = isUnderline(); + boolean strike = isStrikeThrough(); + if (underline || strike) { + // calculate x coordinates + Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); + View parent = getParent(); + if ((parent != null) && (parent.getEndOffset() == endPosition)) { + // strip whitespace on end + Segment segment = getText(startPosition, endPosition); + while (Character.isWhitespace(segment.last())) { + endPosition -= 1; + segment.count -= 1; } + } + int x0 = alloc.x; + int p = getStartOffset(); + if (p != startPosition) { + x0 += (int) painter.getSpan(this, p, startPosition, getTabExpander(), x0); + } + int x1 = x0 + (int) painter.getSpan(this, startPosition, endPosition, getTabExpander(), x0); + + // calculate y coordinate + int y = alloc.y + (int) (painter.getHeight(this) - painter.getDescent(this)); + if (underline) { + int yTmp = y + 1; + g.drawLine(x0, yTmp, x1, yTmp); + } + if (strike) { + // move y coordinate above baseline + int yTmp = y - (int) (painter.getAscent(this) * 0.3f); + g.drawLine(x0, yTmp, x1, yTmp); + } } -} \ No newline at end of file + } +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLDocument.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLDocument.java index 7b27399..56cebce 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLDocument.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLDocument.java @@ -1,201 +1,227 @@ package best.tigers.tynk_dialog.gui.text; import best.tigers.tynk_dialog.game.Constants; - -import javax.imageio.ImageIO; -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.text.*; -import javax.swing.text.html.HTMLDocument; -import javax.swing.text.html.HTMLEditorKit; -import javax.swing.tree.TreeNode; -import java.awt.*; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; import java.awt.image.BufferedImage; -import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JOptionPane; +import javax.swing.text.AbstractDocument; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.BoxView; +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.Element; +import javax.swing.text.ParagraphView; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.tree.TreeNode; public class HarlowTMLDocument extends DefaultStyledDocument { - public static final String BEHAVIOR_ATTRIBUTE_NAME = "behavior"; - public static final String DELAY_ELEMENT_NAME = "TimeDelayElement"; - public static final String DELAY_MAGNITUDE_NAME = "TimeDelayMagnitude"; - private boolean lengthLock = true; - - public void insertTimeDelay(int offset, int timeDelayQuantity) { - lengthLock = false; - SimpleAttributeSet attrs = new SimpleAttributeSet(getCharacterElement(offset).getAttributes()); - StyleConstants.setForeground(attrs, Constants.TextColor.WHITE.toAWT()); - BufferedImage icon = null; - var classLoader = getClass().getClassLoader(); - try { - icon =ImageIO.read(classLoader.getResource("timer.png").openStream()); - } catch (IOException e) { - e.printStackTrace(); - } - attrs.addAttribute(DELAY_MAGNITUDE_NAME, timeDelayQuantity); - - StyleConstants.setIcon(attrs, new ImageIcon(icon)); - System.out.println(StyleConstants.getIcon(attrs)); - System.out.println(attrs.getAttribute(DELAY_MAGNITUDE_NAME)); - try { - insertString(offset, " ", attrs); - } catch (BadLocationException e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(null, "Can't insert delay!"); - } - lengthLock = true; - dump(System.out); + public static final String BEHAVIOR_ATTRIBUTE_NAME = "behavior"; + public static final String DELAY_ELEMENT_NAME = "TimeDelayElement"; + public static final String DELAY_MAGNITUDE_NAME = "TimeDelayMagnitude"; + private boolean lengthLock = true; + + public void insertTimeDelay(int offset, int timeDelayQuantity) { + if (timeDelayQuantity == 0) { + java.awt.Toolkit.getDefaultToolkit().beep(); + return; } - static class TimeDelayView extends BoxView { - public TimeDelayView(Element elem) { - super(elem, X_AXIS); - setSize(5, 5); - } + lengthLock = false; + SimpleAttributeSet attrs = new SimpleAttributeSet(getCharacterElement(offset).getAttributes()); + StyleConstants.setForeground(attrs, Constants.TextColor.WHITE.toAWT()); + BufferedImage icon = null; + var classLoader = getClass().getClassLoader(); + try { + icon = ImageIO.read(classLoader.getResource("timer.png").openStream()); + } catch (IOException e) { + e.printStackTrace(); + } + attrs.addAttribute(DELAY_MAGNITUDE_NAME, timeDelayQuantity); + + StyleConstants.setIcon(attrs, new ImageIcon(icon)); + System.out.println(StyleConstants.getIcon(attrs)); + System.out.println(attrs.getAttribute(DELAY_MAGNITUDE_NAME)); + try { + insertString(offset, " ", attrs); + } catch (BadLocationException e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(null, "Can't insert delay!"); + } + lengthLock = true; + dump(System.out); + } + + public void changeDelayMagnitude(Element e, int magnitude) { + var attribs = new SimpleAttributeSet(); + attribs.addAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME, magnitude); + setCharacterAttributes( + e.getStartOffset(), e.getEndOffset() - e.getStartOffset(), attribs, false); + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (!lengthLock) { + super.insertString(offs, str, a); + return; + } + try { + Element currentElement = getParagraphElement(offs); + Element[] rootElements = getRootElements(); + int paragraphCount = 0; + for (var el : rootElements) { + if (el.getName().equals("section")) { + paragraphCount = el.getElementCount(); + } + } + int timerCount = 0; + for (int i = 0; i < currentElement.getElementCount(); i++) { + if (currentElement.getElement(i).getName().equals("icon")) { + timerCount += 1; + } + } + var stringLines = str.split("\n"); + var strLongestLine = + Arrays.stream(stringLines) + .max( + (String line1, String line2) -> { + return line1.length() - line2.length(); + }); + if ((currentElement.getEndOffset() - currentElement.getStartOffset() < (45 + timerCount) + && (!(str.contains("\n")) + || (!(str.equals("\n")) + && stringLines.length <= (4 - paragraphCount) + && strLongestLine + .orElseGet( + () -> { + return ""; + }) + .length() + <= (45 + timerCount)))) + || (str.equals("\n") && paragraphCount <= 3)) { + super.insertString(offs, str, a); + } else { + return; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + public void setBehavior(int startOffset, int endOffset, Constants.Behavior behavior) { + SimpleAttributeSet attrs = new SimpleAttributeSet(); + attrs.addAttribute(BEHAVIOR_ATTRIBUTE_NAME, behavior); + setCharacterAttributes(startOffset, endOffset - startOffset, attrs, false); + } + + public void clearBehavior(int startOffset, int endOffset) { + for (int i = startOffset; i < endOffset; i++) { + var currentElement = getCharacterElement(i); + SimpleAttributeSet attrs = new SimpleAttributeSet(currentElement.getAttributes()); + attrs.removeAttribute(BEHAVIOR_ATTRIBUTE_NAME); + setCharacterAttributes(i, 1, attrs, true); + } + } - public void paint(Graphics g, Shape a) { - var boundaries = a.getBounds(); - Graphics2D g2 = (Graphics2D) g; - g2.clearRect(boundaries.x, boundaries.y, boundaries.width, boundaries.height); - g2.setStroke(new BasicStroke(5)); - g2.setColor(Color.red); - var halfHeight = boundaries.y; - g2.drawLine(boundaries.x, boundaries.y, boundaries.x, boundaries.y + halfHeight); - g2.drawLine(boundaries.x + 8, boundaries.y, boundaries.x + 8, boundaries.y + halfHeight); - g2.setStroke(new BasicStroke(2)); - g2.setColor(Color.black); - g2.drawLine(boundaries.x, boundaries.y + boundaries.height, boundaries.x + boundaries.width, boundaries.y + boundaries.height); - super.paint(g, a); - } + static class TimeDelayView extends BoxView { + public TimeDelayView(Element elem) { + super(elem, X_AXIS); + setSize(5, 5); + } + public void paint(Graphics g, Shape a) { + var boundaries = a.getBounds(); + Graphics2D g2 = (Graphics2D) g; + g2.clearRect(boundaries.x, boundaries.y, boundaries.width, boundaries.height); + g2.setStroke(new BasicStroke(5)); + g2.setColor(Color.red); + var halfHeight = boundaries.y; + g2.drawLine(boundaries.x, boundaries.y, boundaries.x, boundaries.y + halfHeight); + g2.drawLine(boundaries.x + 8, boundaries.y, boundaries.x + 8, boundaries.y + halfHeight); + g2.setStroke(new BasicStroke(2)); + g2.setColor(Color.black); + g2.drawLine( + boundaries.x, + boundaries.y + boundaries.height, + boundaries.x + boundaries.width, + boundaries.y + boundaries.height); + super.paint(g, a); } + } - public void changeDelayMagnitude(Element e, int magnitude) { - var attribs = new SimpleAttributeSet(); - attribs.addAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME, magnitude); - setCharacterAttributes(e.getStartOffset(), e.getEndOffset() - e.getStartOffset(), attribs, false); + static class LineView extends ParagraphView { + public LineView(Element element) { + super(element); + } + } + + class HarlowTMLEntityElement extends AbstractDocument.LeafElement { + /** + * Constructs an element that represents content within the document (has no children). + * + * @param parent The parent element + * @param a The element attributes + * @param offs0 The start offset >= 0 + * @param offs1 The end offset >= offs0 + * @since 1.4 + */ + public HarlowTMLEntityElement(Element parent, AttributeSet a, int offs0, int offs1) { + super(parent, a, offs0, offs1); } + /** + * Creates a new AbstractElement. + * + * @param parent the parent element + * @param a the attributes for the element + * @since 1.4 + */ @Override - public void insertString(int offs, - String str, - AttributeSet a) throws BadLocationException { - if (!lengthLock) { - super.insertString(offs, str, a); - return; - } - try { - Element currentElement = getParagraphElement(offs); - Element[] rootElements = getRootElements(); - int paragraphCount = 0; - for (var el : rootElements) { - if (el.getName().equals("section")) { - paragraphCount = el.getElementCount(); - } - } - int timerCount = 0; - for (int i = 0; i < currentElement.getElementCount(); i++) { - if (currentElement.getElement(i).getName().equals("icon")) { - timerCount += 1; - } - } - var stringLines = str.split("\n"); - var strLongestLine = Arrays.stream(stringLines).max((String line1, String line2) -> {return line1.length() - line2.length();}); - if ((currentElement.getEndOffset() - currentElement.getStartOffset() < (45 + timerCount) && (!(str.contains("\n")) || (!(str.equals("\n")) && stringLines.length <= (4 - paragraphCount) && strLongestLine.orElseGet(()->{return "";}).length() <= (45+timerCount)))) - || (str.equals("\n") && paragraphCount <= 3) - ) { - super.insertString(offs, str, a); - } else { - return; - } - } catch (BadLocationException e) { - e.printStackTrace(); - } + public int getStartOffset() { + return 0; } - static class LineView extends ParagraphView { - public LineView(Element element) { - super(element); - } + @Override + public int getEndOffset() { + return 0; } - public void setBehavior(int startOffset, int endOffset, Constants.Behavior behavior) { - SimpleAttributeSet attrs=new SimpleAttributeSet(); - attrs.addAttribute(BEHAVIOR_ATTRIBUTE_NAME, behavior); - setCharacterAttributes(startOffset, endOffset-startOffset, attrs, false); + @Override + public Element getElement(int index) { + return null; } - public void clearBehavior(int startOffset, int endOffset) { - for (int i =startOffset; i < endOffset; i ++) { - var currentElement = getCharacterElement(i); - SimpleAttributeSet attrs=new SimpleAttributeSet(currentElement.getAttributes()); - attrs.removeAttribute(BEHAVIOR_ATTRIBUTE_NAME); - setCharacterAttributes(i, 1, attrs, true); - } + @Override + public int getElementCount() { + return 0; } - class HarlowTMLEntityElement extends AbstractDocument.LeafElement { - /** - * Constructs an element that represents content within the - * document (has no children). - * - * @param parent The parent element - * @param a The element attributes - * @param offs0 The start offset >= 0 - * @param offs1 The end offset >= offs0 - * @since 1.4 - */ - public HarlowTMLEntityElement(Element parent, AttributeSet a, int offs0, int offs1) { - super(parent, a, offs0, offs1); - } - - /** - * Creates a new AbstractElement. - * - * @param parent the parent element - * @param a the attributes for the element - * @since 1.4 - */ - - @Override - public int getStartOffset() { - return 0; - } - - @Override - public int getEndOffset() { - return 0; - } - - @Override - public Element getElement(int index) { - return null; - } - - @Override - public int getElementCount() { - return 0; - } - - @Override - public int getElementIndex(int offset) { - return 0; - } + @Override + public int getElementIndex(int offset) { + return 0; + } - @Override - public boolean isLeaf() { - return true; - } + @Override + public boolean isLeaf() { + return true; + } - @Override - public boolean getAllowsChildren() { - return false; - } + @Override + public boolean getAllowsChildren() { + return false; + } - @Override - public Enumeration children() { - return null; - } + @Override + public Enumeration children() { + return null; } -} \ No newline at end of file + } +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEditorKit.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEditorKit.java index 0c1dba1..fd5d9a8 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEditorKit.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEditorKit.java @@ -1,27 +1,57 @@ package best.tigers.tynk_dialog.gui.text; -import javax.swing.*; -import javax.swing.event.CaretEvent; - import best.tigers.tynk_dialog.game.Constants; -import org.apache.commons.lang3.StringUtils; - -import javax.swing.text.*; -import java.awt.*; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; import java.awt.event.*; import java.io.IOException; import java.io.Reader; import java.io.Writer; -import java.util.ArrayList; import java.util.Arrays; import java.util.stream.Stream; +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.IconView; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; +import org.apache.commons.lang3.StringUtils; public class HarlowTMLEditorKit extends StyledEditorKit { + public static final String TYNK_RED_TEXT = "Red"; + public static final String TYNK_YELLOW_TEXT = "Yellow"; + public static final String TYNK_GREEN_TEXT = "Green"; + public static final String TYNK_BLUE_TEXT = "Blue"; + + public static final String TYNK_WHITE_TEXT = "White"; + + public static final String TYNK_GREY_TEXT = "Grey"; + public static final TynkDelayAction DELAY_ACTION_FIVE = new TynkDelayAction(5); + public static final TynkDelayAction DELAY_ACTION_FIFTEEN = new TynkDelayAction(15); + public static final TynkDelayAction DELAY_ACTION_SIXTY = new TynkDelayAction(60); + public static final Action[] defaultActions = { + new TynkColorAction(Constants.TextColor.RED, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, true)), + new TynkColorAction(Constants.TextColor.YELLOW, KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, true)), + new TynkColorAction(Constants.TextColor.GREEN, KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, true)), + new TynkColorAction(Constants.TextColor.GREY, KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, true)), + new TynkColorAction(Constants.TextColor.BLUE, KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, true)), + new TynkColorAction(Constants.TextColor.WHITE, KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK, true)), + new TynkBehaviorAction(Constants.Behavior.WAVE, KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK, true)), + new TynkBehaviorAction(Constants.Behavior.QUAKE, KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK, true)), + new ClearTynkBehaviorAction(), + DELAY_ACTION_FIVE, + DELAY_ACTION_FIFTEEN, + DELAY_ACTION_SIXTY, + }; private MouseMotionListener listener; private MouseListener clickListener; private Cursor oldCursor; private Boolean showInvisibles = true; - public HarlowTMLEditorKit() { listener=new MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { @@ -81,11 +111,62 @@ public ViewFactory getViewFactory() { return new HarlowTMLViewFactory(); } - public static final String TYNK_RED_TEXT = "Red"; - public static final String TYNK_YELLOW_TEXT = "Yellow"; - public static final String TYNK_GREEN_TEXT = "Green"; - public static final String TYNK_BLUE_TEXT = "Blue"; - public static final String TYNK_WHITE_TEXT = "White"; + + + public static void addTimeDelay(JTextComponent e, int delayMagnitude) { + if (e instanceof JEditorPane editor) { + var document = editor.getDocument(); + if (document instanceof HarlowTMLDocument doc) { + doc.insertTimeDelay(e.getSelectionStart(), delayMagnitude); + } + } + } + + public Stream getColorActions() { + return Arrays.stream(defaultActions).filter((action -> action instanceof TynkColorAction)).map(a -> (TynkColorAction) a); + } + + public Stream getBehaviorActions() { + return Arrays.stream(defaultActions).filter((action -> action instanceof TynkBehaviorAction)).map(a -> (TynkBehaviorAction) a); + } + + public Action getClearBehaviorAction() { + return new ClearTynkBehaviorAction(); + } + + @Override + public Action[] getActions() { + return StyledTextAction.augmentList(super.getActions(), defaultActions); + } + + public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { + var reader = new HarlowTMLReader(doc, pos, in); + reader.read(); + } + + public Object clone() { + return new HarlowTMLEditorKit(); + } + + public void write(Writer out, Document doc, int pos, int len) + throws IOException, BadLocationException { + var writer = new HarlowTMLWriter(); + writer.write(doc, pos, len, out); + } + + public void install(JEditorPane c) { + super.install(c); + c.addMouseMotionListener(listener); + c.addMouseListener(clickListener); + //c.addMouseMotionListener(lstMoveCollapse); + } + + public void deinstall(JEditorPane c) { + c.removeMouseMotionListener(listener); + //c.removeMouseMotionListener(lstMoveCollapse); + c.removeMouseListener(clickListener); + super.deinstall(c); + } static class TynkColorIcon implements Icon { private Constants.TextColor color; @@ -112,16 +193,28 @@ public int getIconHeight() { } } - static class TynkColorAction extends ForegroundAction { - public TynkColorAction(Constants.TextColor tynkColor) { + public static class TynkColorAction extends ForegroundAction { + private final KeyStroke shortcutKey; + private final String keyMapName; + public TynkColorAction(Constants.TextColor tynkColor, KeyStroke shortcutKey) { super(StringUtils.capitalize(tynkColor.getGameName()), tynkColor.toAWT()); + this.shortcutKey = shortcutKey; + this.keyMapName = tynkColor.getGameName() + "keyboardShortcut"; putValue(Action.SHORT_DESCRIPTION, "Make the selected text " + tynkColor.getGameName() + "."); putValue(Action.SMALL_ICON, new TynkColorIcon(new Dimension(16, 16), tynkColor)); - putValue(Action.LARGE_ICON_KEY, new TynkColorIcon(new Dimension(32, 32), tynkColor)); + putValue(Action.LARGE_ICON_KEY, new TynkColorIcon(new Dimension(32, 16), tynkColor)); + } + + public KeyStroke getShortcutKey() { + return shortcutKey; + } + + public String getKeyMapName() { + return keyMapName; } } - static class ClearTynkBehaviorAction extends StyledTextAction { + public static class ClearTynkBehaviorAction extends StyledTextAction { private Constants.Behavior tynkBehavior; public ClearTynkBehaviorAction() { super("Remove behaviors"); @@ -139,13 +232,25 @@ public void actionPerformed(ActionEvent e) { } } - static class TynkBehaviorAction extends StyledTextAction { + public static class TynkBehaviorAction extends StyledTextAction { private Constants.Behavior tynkBehavior; - public TynkBehaviorAction(Constants.Behavior tynkBehavior) { + private KeyStroke shortcutKey; + private String keyMapName; + public TynkBehaviorAction(Constants.Behavior tynkBehavior, KeyStroke shortcutKey) { super(tynkBehavior.getBehaviorName()); + this.shortcutKey = shortcutKey; + this.keyMapName = tynkBehavior.getBehaviorName() + "keyboardShortcut"; this.tynkBehavior = tynkBehavior; } + public KeyStroke getShortcutKey() { + return shortcutKey; + } + + public String getKeyMapName() { + return keyMapName; + } + @Override public void actionPerformed(ActionEvent e) { var textComponent = getTextComponent(e); @@ -158,69 +263,17 @@ public void actionPerformed(ActionEvent e) { } } - public void AddTimeDelay(JTextComponent e, int delayMagnitude) { - if (e instanceof JEditorPane editor) { - var document = editor.getDocument(); - if (document instanceof HarlowTMLDocument doc) { - doc.insertTimeDelay(e.getSelectionStart(), delayMagnitude); - } + public static class TynkDelayAction extends StyledTextAction { + private int delayMagnitude; + public TynkDelayAction(int delayMagnitude) { + super("Wait " + String.valueOf(delayMagnitude)); + this.delayMagnitude = delayMagnitude; } - } - - public Stream getColorActions() { - return Arrays.stream(defaultActions).filter((action -> action instanceof TynkColorAction)); - } - - public Stream getBehaviorActions() { - return Arrays.stream(defaultActions).filter((action -> action instanceof TynkBehaviorAction)); - } - - public Action getClearBehaviorAction() { - return new ClearTynkBehaviorAction(); - } - - public static final Action[] defaultActions = { - new TynkColorAction(Constants.TextColor.RED), - new TynkColorAction(Constants.TextColor.YELLOW), - new TynkColorAction(Constants.TextColor.GREEN), - new TynkColorAction(Constants.TextColor.BLUE), - new TynkColorAction(Constants.TextColor.WHITE), - new TynkBehaviorAction(Constants.Behavior.WAVE), - new TynkBehaviorAction(Constants.Behavior.QUAKE), - new ClearTynkBehaviorAction(), - }; - - public Action[] getActions() { - return StyledTextAction.augmentList(super.getActions(), defaultActions); - } - - - public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { - var reader = new HarlowTMLReader(doc, pos, in); - reader.read(); - } - public Object clone() { - return new HarlowTMLEditorKit(); - } - - public void write(Writer out, Document doc, int pos, int len) - throws IOException, BadLocationException { - var writer = new HarlowTMLWriter(); - writer.write(doc, pos, len, out); - } - - public void install(JEditorPane c) { - super.install(c); - c.addMouseMotionListener(listener); - c.addMouseListener(clickListener); - //c.addMouseMotionListener(lstMoveCollapse); - } - public void deinstall(JEditorPane c) { - c.removeMouseMotionListener(listener); - //c.removeMouseMotionListener(lstMoveCollapse); - c.removeMouseListener(clickListener); - super.deinstall(c); + @Override + public void actionPerformed(ActionEvent e) { + HarlowTMLEditorKit.addTimeDelay(getTextComponent(e), delayMagnitude); + } } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEntityView.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEntityView.java index c068f14..3d6427f 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEntityView.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLEntityView.java @@ -1,89 +1,87 @@ package best.tigers.tynk_dialog.gui.text; -import best.tigers.tynk_dialog.game.Constants; -import best.tigers.tynk_dialog.gui.Assets; - +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.text.BadLocationException; import javax.swing.text.Element; import javax.swing.text.Position; import javax.swing.text.View; -import javax.swing.text.html.ImageView; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; -import java.io.IOException; public class HarlowTMLEntityView extends View { - private ImageObserver imageObserver; - private View parent; - private Container container; - static BufferedImage image; - public HarlowTMLEntityView(Element elem) { - super(elem); - try { - image = ImageIO.read(getClass().getClassLoader().getResource("timer.png").openStream()); - } catch (IOException e) { - e.printStackTrace(); - } - imageObserver = new DummyObserver(); - } + static BufferedImage image; + private ImageObserver imageObserver; + private View parent; + private Container container; - class DummyObserver implements ImageObserver { - @Override - public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { - return false; - } + public HarlowTMLEntityView(Element elem) { + super(elem); + try { + image = ImageIO.read(getClass().getClassLoader().getResource("timer.png").openStream()); + } catch (IOException e) { + e.printStackTrace(); } + imageObserver = new DummyObserver(); + } - public void setParent(View parent) { - View oldParent = getParent(); - super.setParent(parent); - container = (parent != null) ? getContainer() : null; - } + public void setParent(View parent) { + View oldParent = getParent(); + super.setParent(parent); + container = (parent != null) ? getContainer() : null; + } - @Override - public float getPreferredSpan(int axis) { - if (axis == X_AXIS) { - //return image.getWidth(imageObserver); - return 10; - } - //return image.getHeight(imageObserver); - return 10; - } + @Override + public float getPreferredSpan(int axis) { + // return image.getWidth(imageObserver); + // return image.getHeight(imageObserver); + return 10; + } - @Override - public void paint(Graphics g, Shape allocation) { - var x = allocation.getBounds().x; - var width = 10; - var height = 10; - var y = allocation.getBounds().y - (height / 2); - g.drawImage(image, x, y, width, height, imageObserver); + @Override + public void paint(Graphics g, Shape allocation) { + var x = allocation.getBounds().x; + var width = 10; + var height = 10; + var y = allocation.getBounds().y - (height / 2); + g.drawImage(image, x, y, width, height, imageObserver); + } + + @Override + public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { + int p0 = getStartOffset(); + int p1 = getEndOffset(); + if ((pos >= p0) && (pos <= p1)) { + Rectangle r = a.getBounds(); + if (pos == p1) { + r.x += r.width; + } + r.width = 0; + return r; } + return null; + } - @Override - public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { - int p0 = getStartOffset(); - int p1 = getEndOffset(); - if ((pos >= p0) && (pos <= p1)) { - Rectangle r = a.getBounds(); - if (pos == p1) { - r.x += r.width; - } - r.width = 0; - return r; - } - return null; + @Override + public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) { + Rectangle alloc = (Rectangle) a; + if (x < alloc.x + alloc.width) { + bias[0] = Position.Bias.Forward; + return getStartOffset(); } + bias[0] = Position.Bias.Backward; + return getEndOffset(); + } + class DummyObserver implements ImageObserver { @Override - public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) { - Rectangle alloc = (Rectangle) a; - if (x < alloc.x + alloc.width) { - bias[0] = Position.Bias.Forward; - return getStartOffset(); - } - bias[0] = Position.Bias.Backward; - return getEndOffset(); + public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { + return false; } + } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLLabelView.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLLabelView.java index 8f731e9..48622c3 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLLabelView.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLLabelView.java @@ -2,55 +2,62 @@ import best.tigers.tynk_dialog.game.Constants; import best.tigers.tynk_dialog.gui.Assets; - -import javax.swing.*; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; import javax.swing.text.Element; import javax.swing.text.LabelView; -import javax.swing.text.View; -import java.awt.*; public class HarlowTMLLabelView extends LabelView { - public HarlowTMLLabelView(Element elem) { - super(elem); - } - - public void paint(Graphics g, Shape allocation) { - super.paint(g, allocation); - if (getAttributes().getAttribute(HarlowTMLDocument.ElementNameAttribute)!=null - && getAttributes().getAttribute(HarlowTMLDocument.ElementNameAttribute).equals(HarlowTMLDocument.DELAY_ELEMENT_NAME)) { - System.out.println("h"); - //paintDelayIndicator(g, allocation, (int) getAttributes().getAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME)); - } - if (getAttributes().getAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME)!=null) - paintBehaviorIndicator(g, allocation, (Constants.Behavior) getAttributes().getAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME)); - } - - public void paintDelayIndicator(Graphics g, Shape a, int delayMagnitude) { - int y = (int) (a.getBounds().getY() + a.getBounds().getHeight()); - int x1 = (int) a.getBounds().getX(); - int x2 = (int) a.getBounds().getX() + a.getBounds().width; - - Color old = g.getColor(); - var g2 = (Graphics2D) g; - g2.setColor(Constants.TextColor.YELLOW.toAWT()); - g2.drawImage(Assets.getInstance().getTimer(), x1, (int) a.getBounds().getY(), x2, y, null); - g.setColor(old); - } - - public void paintBehaviorIndicator(Graphics g, Shape a, Constants.Behavior tynkBehavior) { - int y = (int) (a.getBounds().getY() + a.getBounds().getHeight()); - int x1 = (int) a.getBounds().getX(); - int x2 = (int) (a.getBounds().getX() + a.getBounds().getWidth()); - - Color old = g.getColor(); - var g2 = (Graphics2D) g; - g2.setColor(Constants.TextColor.WHITE.toAWT()); - g2.setStroke(new BasicStroke(1)); - for (int i = x1; i <= x2; i += 6) { - g.drawArc(i + 3, y - 3, 3, 3, 0, 180); - g.drawArc(i + 6, y - 3, 3, 3, 180, 181); - } - g.setColor(old); - } - - } \ No newline at end of file + public HarlowTMLLabelView(Element elem) { + super(elem); + } + + public void paint(Graphics g, Shape allocation) { + super.paint(g, allocation); + if (getAttributes().getAttribute(HarlowTMLDocument.ElementNameAttribute) != null + && getAttributes() + .getAttribute(HarlowTMLDocument.ElementNameAttribute) + .equals(HarlowTMLDocument.DELAY_ELEMENT_NAME)) { + System.out.println("h"); + // paintDelayIndicator(g, allocation, (int) + // getAttributes().getAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME)); + } + if (getAttributes().getAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME) != null) + paintBehaviorIndicator( + g, + allocation, + (Constants.Behavior) + getAttributes().getAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME)); + } + + public void paintDelayIndicator(Graphics g, Shape a, int delayMagnitude) { + int y = (int) (a.getBounds().getY() + a.getBounds().getHeight()); + int x1 = (int) a.getBounds().getX(); + int x2 = (int) a.getBounds().getX() + a.getBounds().width; + + Color old = g.getColor(); + var g2 = (Graphics2D) g; + g2.setColor(Constants.TextColor.YELLOW.toAWT()); + g2.drawImage(Assets.getInstance().getTimer(), x1, (int) a.getBounds().getY(), x2, y, null); + g.setColor(old); + } + + public void paintBehaviorIndicator(Graphics g, Shape a, Constants.Behavior tynkBehavior) { + int y = (int) (a.getBounds().getY() + a.getBounds().getHeight()); + int x1 = (int) a.getBounds().getX(); + int x2 = (int) (a.getBounds().getX() + a.getBounds().getWidth()); + + Color old = g.getColor(); + var g2 = (Graphics2D) g; + g2.setColor(Constants.TextColor.WHITE.toAWT()); + g2.setStroke(new BasicStroke(1)); + for (int i = x1; i <= x2; i += 6) { + g.drawArc(i + 3, y - 3, 3, 3, 0, 180); + g.drawArc(i + 6, y - 3, 3, 3, 180, 181); + } + g.setColor(old); + } +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLReader.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLReader.java index 141ff9a..3ae1deb 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLReader.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLReader.java @@ -1,38 +1,37 @@ package best.tigers.tynk_dialog.gui.text; -import best.tigers.tynk_dialog.game.*; -import best.tigers.tynk_dialog.game.harlowtml.*; -import com.formdev.flatlaf.IntelliJTheme; - +import best.tigers.tynk_dialog.game.Constants; +import best.tigers.tynk_dialog.game.harlowtml.HarlowTMLCharacterToken; +import best.tigers.tynk_dialog.game.harlowtml.HarlowTMLTagToken; +import best.tigers.tynk_dialog.game.harlowtml.HarlowTMLToken; +import best.tigers.tynk_dialog.game.harlowtml.HarlowTMLTokenizer; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayDeque; +import java.util.ArrayList; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; -import javax.swing.text.rtf.RTFEditorKit; -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Stack; public class HarlowTMLReader { - private Stack tagStack = new Stack<>(); - private Reader rawInput; - private Document d; + private final ArrayDeque tagStack = new ArrayDeque<>(); + private final Reader rawInput; + private final Document document; private int position; - public HarlowTMLReader(Document d, int position, Reader rawInput) { - this.d = d; + public HarlowTMLReader(Document document, int position, Reader rawInput) { + this.document = document; this.position = position; this.rawInput = rawInput; } public void read() throws IOException, BadLocationException { - if (!(d instanceof HarlowTMLDocument)) { + if (!(document instanceof HarlowTMLDocument doc)) { return; } - HarlowTMLDocument doc = (HarlowTMLDocument) d; var tokenizer = new HarlowTMLTokenizer(rawInput); - ArrayList tokens = new ArrayList<>(); + ArrayList tokens; try { tokens = tokenizer.tokenize(); } catch (HarlowTMLTokenizer.TokenizerException e) { @@ -43,27 +42,26 @@ public void read() throws IOException, BadLocationException { StyleConstants.setForeground(tagStack.peek(), Constants.TextColor.WHITE.toAWT()); StyleConstants.setBackground(tagStack.peek(), Constants.TextColor.BACKGROUND.toAWT()); for (var token : tokens) { - if (token instanceof HarlowTMLTagToken && ((HarlowTMLTagToken) token).getType() != HarlowTMLTagToken.TagType.ENTITY) { - System.out.println(token.getName()); - System.out.println(((HarlowTMLTagToken) token).getTagName()); - System.out.println(((HarlowTMLTagToken) token).getTagValue()); - System.out.println(((HarlowTMLTagToken) token).getType()); - changeAttributesBasedOnTag((HarlowTMLTagToken) token); - } else if (token instanceof HarlowTMLCharacterToken characterToken) { - doc.insertString(position++, characterToken.getContent(), tagStack.peek()); - } else if (token instanceof HarlowTMLTagToken && ((HarlowTMLTagToken) token).getType() == HarlowTMLTagToken.TagType.ENTITY) { - insertEntityBasedOnTag((HarlowTMLTagToken) token); + if (token instanceof HarlowTMLTagToken tagToken) { + switch (tagToken.getType()) { + case OPEN, CLOSE -> {changeAttributesBasedOnTag(tagToken);} + case ENTITY -> {insertEntityBasedOnTag(tagToken);} + } + } else if (token instanceof HarlowTMLCharacterToken charToken) { + doc.insertString(position++, charToken.getContent(), tagStack.peek()); } } } private void insertEntityBasedOnTag(HarlowTMLTagToken entity) { - if (d instanceof HarlowTMLDocument doc) { + if (document instanceof HarlowTMLDocument doc) { switch (entity.getTagName().toLowerCase()) { case "t", "wait", "time" -> { System.out.println(Integer.valueOf(entity.getTagValue())); - doc.insertTimeDelay(position++, Integer.valueOf(entity.getTagValue())); + doc.insertTimeDelay(position++, Integer.parseInt(entity.getTagValue())); } + default -> throw new IllegalStateException( + "Unexpected value: " + entity.getTagName().toLowerCase()); } } } @@ -75,20 +73,19 @@ private void changeAttributesBasedOnTag(HarlowTMLTagToken tag) { } tagStack.push(new SimpleAttributeSet(tagStack.peek())); var value = tag.getTagValue(); - switch (tag.getTagName().toLowerCase()) { + var attribs = tagStack.peek(); + assert (attribs != null); + var tagName = tag.getTagName().toLowerCase(); + switch (tagName) { case "c", "color", "colour" -> { - StyleConstants.setForeground( - tagStack.peek(), - Constants.TextColor.fromString(value).toAWT() - ); + StyleConstants.setForeground(attribs, Constants.TextColor.fromString(value).toAWT()); } case "b", "behavior", "behaviour" -> { - tagStack.peek().addAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME, - Constants.Behavior.fromString(value)); + attribs.addAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME, Constants.Behavior.fromString(value)); } default -> { + throw new IllegalStateException("Invalid tag \"%s\" in document".formatted(tagName)); } } - return; } } \ No newline at end of file diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLTimerElement.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLTimerElement.java index 0f87c55..974bb03 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLTimerElement.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLTimerElement.java @@ -1,11 +1,3 @@ package best.tigers.tynk_dialog.gui.text; -import javax.swing.text.AbstractDocument; -import javax.swing.text.Element; -import javax.swing.text.IconView; -import javax.swing.text.html.HTMLEditorKit; -import javax.swing.tree.TreeNode; -import java.util.Enumeration; - -public class HarlowTMLTimerElement { -} \ No newline at end of file +public class HarlowTMLTimerElement {} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLViewFactory.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLViewFactory.java index e87f9f2..fefb40e 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLViewFactory.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLViewFactory.java @@ -1,33 +1,34 @@ package best.tigers.tynk_dialog.gui.text; -import javax.swing.text.*; -import javax.swing.text.html.ImageView; +import javax.swing.text.AbstractDocument; +import javax.swing.text.BoxView; +import javax.swing.text.ComponentView; +import javax.swing.text.Element; +import javax.swing.text.IconView; +import javax.swing.text.StyleConstants; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; public class HarlowTMLViewFactory implements ViewFactory { - public View create(Element elem) { - String kind = elem.getName(); - if (kind != null) { - if (kind.equals(AbstractDocument.ContentElementName)) { - return new HarlowTMLLabelView(elem); - } - else if (kind.equals(AbstractDocument.ParagraphElementName)) { - return new HarlowTMLDocument.LineView(elem); - } - else if (kind.equals(AbstractDocument.SectionElementName)) { - return new BoxView(elem, View.Y_AXIS); - } - else if (kind.equals(StyleConstants.ComponentElementName)) { - return new ComponentView(elem); - } - else if (kind.equals(StyleConstants.IconElementName)) { - return new IconView(elem); - } - else if (kind.equals(HarlowTMLDocument.DELAY_ELEMENT_NAME)) { - return new HarlowTMLEntityView(elem); - //return new HarlowTMLLabelView(elem); - } - } - // default to text display + public View create(Element elem) { + String kind = elem.getName(); + if (kind != null) { + if (kind.equals(AbstractDocument.ContentElementName)) { return new HarlowTMLLabelView(elem); + } else if (kind.equals(AbstractDocument.ParagraphElementName)) { + return new HarlowTMLDocument.LineView(elem); + } else if (kind.equals(AbstractDocument.SectionElementName)) { + return new BoxView(elem, View.Y_AXIS); + } else if (kind.equals(StyleConstants.ComponentElementName)) { + return new ComponentView(elem); + } else if (kind.equals(StyleConstants.IconElementName)) { + return new IconView(elem); + } else if (kind.equals(HarlowTMLDocument.DELAY_ELEMENT_NAME)) { + return new HarlowTMLEntityView(elem); + // return new HarlowTMLLabelView(elem); + } } + // default to text display + return new HarlowTMLLabelView(elem); + } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLWriter.java b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLWriter.java index 455cfc1..f549892 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLWriter.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/text/HarlowTMLWriter.java @@ -1,68 +1,76 @@ package best.tigers.tynk_dialog.gui.text; -import best.tigers.tynk_dialog.game.Constants; -import javax.swing.text.*; -import java.awt.*; +import best.tigers.tynk_dialog.game.Constants; import java.io.IOException; import java.io.Writer; import java.util.Arrays; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.StyleConstants; public class HarlowTMLWriter { - public static void write(Document doc, int start, int len, Writer out) throws IOException, BadLocationException { - Element root=doc.getDefaultRootElement(); - int iStart=root.getElementIndex(start); - int iEnd=root.getElementIndex(start+len); + public static void write(Document doc, int start, int len, Writer out) + throws IOException, BadLocationException { + Element root = doc.getDefaultRootElement(); + int iStart = root.getElementIndex(start); + int iEnd = root.getElementIndex(start + len); - for (int i=iStart; i<=iEnd; i++) { - Element par=root.getElement(i); - writePar(par, start, len, out); - } + for (int i = iStart; i <= iEnd; i++) { + Element par = root.getElement(i); + writePar(par, start, len, out); } + } - public static void writePar(Element par, int start, int len, Writer out) throws IOException, BadLocationException { - int iStart=par.getElementIndex(start); - int iEnd=par.getElementIndex(start+len); - for (int i=iStart; i<=iEnd; i++) { - Element text=par.getElement(i); - writeText(text, start, len, out); - } + public static void writePar(Element par, int start, int len, Writer out) + throws IOException, BadLocationException { + int iStart = par.getElementIndex(start); + int iEnd = par.getElementIndex(start + len); + for (int i = iStart; i <= iEnd; i++) { + Element text = par.getElement(i); + writeText(text, start, len, out); } + } - public static void writeText(Element text, int start, int len, Writer out) throws IOException, BadLocationException { - if (text.getAttributes().getAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME) != null && text.getName().equals("icon")) { - int delay_magnitude = (int) text.getAttributes().getAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME); - out.write(""); - return; - } - var color = StyleConstants.getForeground(text.getAttributes()); - var behavior = (Constants.Behavior) text.getAttributes().getAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME); - boolean specifiedColor = false; - boolean specifiedBehavior = false; - if (Arrays.stream(Constants.TextColor.values()) - .anyMatch((c) -> { - boolean isGameColor = c.toAWT().equals(color); - boolean isNotDefault = !(c.equals(Constants.TextColor.WHITE)); - return isGameColor && isNotDefault; - }) - ) { - out.write(Constants.TextColor.fromAWT(color).asTag()); - specifiedColor = true; - } - if (behavior != null) { - out.write(behavior.asTag()); - specifiedBehavior = true; - } - int textStart=Math.max(start, text.getStartOffset()); - int textEnd=Math.min(start+len, text.getEndOffset()); - String s=text.getDocument().getText(textStart, textEnd-textStart); - out.write(s); - if (specifiedBehavior) { - out.write(""); - } - if (specifiedColor) { - out.write(""); - } + public static void writeText(Element text, int start, int len, Writer out) + throws IOException, BadLocationException { + if (text.getAttributes().getAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME) != null + && text.getName().equals("icon")) { + int delay_magnitude = + (int) text.getAttributes().getAttribute(HarlowTMLDocument.DELAY_MAGNITUDE_NAME); + out.write(""); + return; + } + var color = StyleConstants.getForeground(text.getAttributes()); + var behavior = + (Constants.Behavior) + text.getAttributes().getAttribute(HarlowTMLDocument.BEHAVIOR_ATTRIBUTE_NAME); + boolean specifiedColor = false; + boolean specifiedBehavior = false; + if (Arrays.stream(Constants.TextColor.values()) + .anyMatch( + (c) -> { + boolean isGameColor = c.toAWT().equals(color); + boolean isNotDefault = !(c.equals(Constants.TextColor.WHITE)); + return isGameColor && isNotDefault; + })) { + out.write(Constants.TextColor.fromAWT(color).asTag()); + specifiedColor = true; + } + if (behavior != null) { + out.write(behavior.asTag()); + specifiedBehavior = true; } + int textStart = Math.max(start, text.getStartOffset()); + int textEnd = Math.min(start + len, text.getEndOffset()); + String s = text.getDocument().getText(textStart, textEnd - textStart); + out.write(s); + if (specifiedBehavior) { + out.write(""); + } + if (specifiedColor) { + out.write(""); + } + } } - diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogEditorView.java b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogEditorView.java index 7e99167..9efdbdf 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogEditorView.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogEditorView.java @@ -1,63 +1,78 @@ package best.tigers.tynk_dialog.gui.view; -import best.tigers.tynk_dialog.gui.Assets; import best.tigers.tynk_dialog.gui.model.DialogModel; import best.tigers.tynk_dialog.gui.model.DialogPageModel; import best.tigers.tynk_dialog.gui.model.DialogPageTableModel; import best.tigers.tynk_dialog.gui.view.components.AutoResizingTable; - -import javax.swing.*; -import java.awt.*; +import java.awt.BorderLayout; import java.awt.event.*; +import java.util.Arrays; +import javax.swing.*; -public class DialogEditorView implements DialogViewer, Observer { - private static final Dimension PREFERRED_SIZE = new Dimension(300, 300); - private static final Dimension MAXIMUM_SIZE = new Dimension(500, Short.MAX_VALUE); - +public class DialogEditorView implements ShortcutSupport, DialogViewer, TObserver { + private final JPanel panel; private final JToolBar editorToolBar; private final AutoResizingTable pageList; private final JTextField titleField; private final DialogModel model; - protected final JPanel panel; - public DialogEditorView(DialogModel model) { + private DialogEditorView(DialogModel model) { this.model = model; - this.pageList = new AutoResizingTable(); - pageList.setModel(model.getDptm()); + pageList = AutoResizingTable.fromDialogPageModel(model); panel = new JPanel(); - panel.setMinimumSize(new Dimension(0, 0)); - - JLabel titleLabel = new JLabel("Title"); titleField = new JTextField(); - titleField.setColumns(20); + editorToolBar = new JToolBar(); + } + + public static DialogEditorView fromModel(DialogModel model) { + var view = new DialogEditorView(model); + view.buildView(); + view.subscribeToModel(); + return view; + } - editorToolBar = new JToolBar("Editor Commands", SwingConstants.HORIZONTAL); - editorToolBar.setFloatable(false); - pageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - pageList.setDragEnabled(true); - pageList.setDropMode(DropMode.ON_OR_INSERT); - JPanel titleControls = new JPanel(); - JScrollPane pageScrollPane = new JScrollPane(pageList); - pageScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + private void buildView() { + setupToolBar(); + var titleControls = setupTitlePanel(); + var pageScrollPane = setupScrollPane(); panel.setLayout(new BorderLayout()); - titleControls.add(titleLabel); - titleControls.add(titleField); panel.add(titleControls, BorderLayout.NORTH); panel.add(editorToolBar, BorderLayout.SOUTH); panel.add(pageScrollPane, BorderLayout.CENTER); } + private JScrollPane setupScrollPane() { + var scrollPane = new JScrollPane(pageList); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + return scrollPane; + } + + private void setupToolBar() { + editorToolBar.setName("Editor Commands"); + editorToolBar.setOrientation(SwingConstants.HORIZONTAL); + editorToolBar.setFloatable(false); + } + + private JPanel setupTitlePanel() { + var titleControls = new JPanel(); + var titleLabel = new JLabel("Title"); + titleField.setColumns(20); + titleControls.add(titleLabel); + titleControls.add(titleField); + return titleControls; + } + public JPanel getPanel() { return panel; } - public DialogEditorView init() { + public void subscribeToModel() { model.attachSubscriber(this); update(); - return this; } - public JTable getList() { + + public AutoResizingTable getTable() { return pageList; } @@ -71,37 +86,41 @@ public void update() { pageList.validate(); } + @Override public String getTitle() { return titleField.getText(); } + @Override + public void setTitle(String newTitle) { + if (!newTitle.equals(titleField.getText())) { + titleField.setText(newTitle); + } + } + public void attachFocusListener(Runnable runner) { - titleField.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - SwingUtilities.invokeLater(runner); - super.focusLost(e); - } - }); - titleField.addMouseMotionListener(new MouseMotionAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - SwingUtilities.invokeLater(runner); - super.mouseMoved(e); - } - }); + titleField.addFocusListener( + new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + SwingUtilities.invokeLater(runner); + super.focusLost(e); + } + }); + titleField.addMouseMotionListener( + new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + SwingUtilities.invokeLater(runner); + super.mouseMoved(e); + } + }); } public DialogPageModel getSelectedPage() { return model.getDptm().getPageAt(pageList.getSelectedRow()); } - public void setTitle(String newTitle) { - if (!newTitle.equals(titleField.getText())) { - titleField.setText(newTitle); - } - } - public void selectPage(int index) { try { pageList.setRowSelectionInterval(index, index); @@ -118,10 +137,28 @@ public DialogPageTableModel getDptm() { return model.getDptm(); } - public DialogEditorView addEditorAction(Action action, String longName) { - editorToolBar.add(action); - return this; + public void addEditorActions(Action... actions) { + Arrays.stream(actions).forEach(editorToolBar::add); } + @Override + public void attachFunctionalKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, Runnable action) { + var inputMap = panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(keyStroke, actionMapKey); + var actionMap = panel.getActionMap(); + var actionInstance = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }; + actionMap.put(actionMapKey, actionInstance); + } + @Override + public void attachKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, AbstractAction action) { + var inputMap = panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(keyStroke, actionMapKey); + var actionMap = panel.getActionMap(); + actionMap.put(actionMapKey, action); + } } - diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageEditorView.java b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageEditorView.java index d79b55a..02de34b 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageEditorView.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageEditorView.java @@ -1,30 +1,27 @@ package best.tigers.tynk_dialog.gui.view; +import static java.awt.event.WindowEvent.WINDOW_CLOSING; + import best.tigers.tynk_dialog.game.Constants; import best.tigers.tynk_dialog.gui.Assets; +import best.tigers.tynk_dialog.gui.controller.DialogController; import best.tigers.tynk_dialog.gui.model.DialogPageModel; import best.tigers.tynk_dialog.gui.text.HarlowTMLEditorKit; +import best.tigers.tynk_dialog.gui.view.components.IntegerDialog; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Insets; +import java.awt.event.*; import javax.swing.*; import javax.swing.text.DefaultEditorKit; -import javax.swing.text.StyledEditorKit; -import javax.swing.text.TextAction; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import static java.awt.event.WindowEvent.WINDOW_CLOSING; -public class DialogPageEditorView implements Observer, DialogPageViewer { - //final private static Dimension PREFERRED_SIZE = new Dimension(300, 400); +public class DialogPageEditorView implements TObserver, DialogPageViewer, ShortcutSupport { private final DialogPageModel model; private final JPanel panel; private final JFrame frame; - private final JComboBox characterComboBox; private final JLabel characterLabel; private final JTextField characterField; @@ -33,6 +30,7 @@ public class DialogPageEditorView implements Observer, DialogPageViewer { private final JToolBar contentToolbar; private final JButton saveButton; + private final JButton createAnotherButton; private final JCheckBox blipCheck; @@ -51,7 +49,6 @@ public DialogPageEditorView(DialogPageModel model) { frame = new JFrame(); characterLabel = createLabel("Character"); - characterComboBox = new JComboBox(); characterField = createField(); contentLabel = new JLabel("Content"); @@ -67,12 +64,18 @@ public DialogPageEditorView(DialogPageModel model) { styleCheck = new JCheckBox(); saveButton = new JButton("Save Changes (Shift + Enter)"); - saveButton.addActionListener(e -> frame.dispatchEvent(new WindowEvent(frame, WINDOW_CLOSING))); + createAnotherButton = new JButton("Make Next Textbox (Ctrl + Enter)"); panel.setLayout(setupLayout()); frame.setJMenuBar(createContentMenubar()); frame.add(panel); } + public static DialogPageEditorView fromModelProceeding(DialogPageModel model) { + var newView = new DialogPageEditorView(model); + newView.getContentField().requestFocus(); + return newView; + } + private GroupLayout setupLayout() { GroupLayout layout = new GroupLayout(panel); layout.setAutoCreateGaps(true); @@ -95,7 +98,8 @@ private GroupLayout setupLayout() { .addComponent(blipCheck) .addComponent(styleCheck))) .addGroup(layout.createSequentialGroup() - .addComponent(saveButton))); + .addComponent(saveButton) + .addComponent(createAnotherButton))); layout.setVerticalGroup( layout.createSequentialGroup() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) @@ -114,7 +118,10 @@ private GroupLayout setupLayout() { .addComponent(styleCheck) .addComponent(styleLabel) .addComponent(styleField, styleField.getPreferredSize().height, styleField.getPreferredSize().height, styleField.getPreferredSize().height)) - .addComponent(saveButton) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(saveButton) + .addComponent(createAnotherButton) + ) ); return layout; } @@ -128,13 +135,9 @@ public void windowClosing(WindowEvent e) { super.windowClosing(e); } }); - blipCheck.addActionListener(e -> { - blipField.setEnabled(blipCheck.isSelected()); - }); - styleCheck.addActionListener(e -> { - styleField.setEnabled(styleCheck.isSelected()); - }); - frame.setTitle("DialogPage Editor (" + model.getSpeaker() + ")"); + blipCheck.addActionListener(e -> blipField.setEnabled(blipCheck.isSelected())); + styleCheck.addActionListener(e -> styleField.setEnabled(styleCheck.isSelected())); + frame.setTitle("DialogPage Editor (" + model.getSpeaker() + ')'); frame.setLocationRelativeTo(null); frame.setVisible(true); frame.pack(); @@ -164,10 +167,6 @@ public void update() { } - public void attachSaveFunction(ActionListener al) { - saveButton.addActionListener(al); - } - public void attachBlipCheckFunction(ActionListener al) { blipCheck.addActionListener(al); } @@ -197,13 +196,13 @@ public void setContent(String newContent) { } @Override - public void setBlip(String newBlip) { - blipField.setText(newBlip); + public String getBlip() { + return blipField.getText(); } @Override - public String getBlip() { - return blipField.getText(); + public void setBlip(String newBlip) { + blipField.setText(newBlip); } public boolean getBlipEnabled() { @@ -211,33 +210,39 @@ public boolean getBlipEnabled() { } @Override - public void setStyle(String newStyle) { - styleField.setText(newStyle); + public String getStyle() { + return styleField.getText(); } @Override - public String getStyle() { - return styleField.getText(); + public void setStyle(String newStyle) { + styleField.setText(newStyle); } public boolean getStyleEnabled() { return styleCheck.isSelected(); } - protected JEditorPane createContentField() { + private JEditorPane createContentField() { var field = new JEditorPane(); field.setMargin(new Insets(0, 0, 0, 0)); field.setFont(font); + field.setForeground(Constants.TextColor.WHITE.toAWT()); field.setBackground(Constants.TextColor.BACKGROUND.toAWT()); field.setContentType("text/harlowtml"); field.setPreferredSize(new Dimension(500, 100)); return field; } - protected JEditorPane getContentField() { + public JEditorPane getContentField() { return contentField; } + public HarlowTMLEditorKit getEditorKit() { + var kit = contentField.getEditorKit(); + return (HarlowTMLEditorKit) kit; + } + protected JToolBar createContentToolbar() { var toolbar = new JToolBar(); var tb = getContentField(); @@ -245,7 +250,11 @@ protected JToolBar createContentToolbar() { toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.TYNK_YELLOW_TEXT)); toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.TYNK_BLUE_TEXT)); toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.TYNK_GREEN_TEXT)); + toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.TYNK_GREY_TEXT)); toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.TYNK_WHITE_TEXT)); + toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.DELAY_ACTION_FIVE)); + toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.DELAY_ACTION_FIFTEEN)); + toolbar.add(tb.getActionMap().get(HarlowTMLEditorKit.DELAY_ACTION_SIXTY)); toolbar.setFloatable(false); return toolbar; } @@ -258,20 +267,22 @@ protected JMenuBar createContentMenubar() { var behaviorMenu = new JMenu("Behaviors"); if (tb.getEditorKit() instanceof HarlowTMLEditorKit kit) { - kit.getColorActions().forEach(action -> colorMenu.add(action)); - kit.getBehaviorActions().forEach(action -> behaviorMenu.add(action)); + kit.getColorActions().forEach(colorMenu::add); + kit.getBehaviorActions().forEach(behaviorMenu::add); behaviorMenu.add(kit.getClearBehaviorAction()); var delay = new JMenuItem(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { - var magnitude = Integer.valueOf(JOptionPane.showInputDialog(frame, "Please enter a delay amount")); - kit.AddTimeDelay(tb, magnitude); + int magnitude = IntegerDialog.promptForInteger(); + HarlowTMLEditorKit.addTimeDelay(tb, magnitude); } }); delay.setText("Delay..."); editMenu.add(delay); } + + var cut = new DefaultEditorKit.CutAction(); cut.putValue(Action.NAME, "Cut"); editMenu.add(cut); @@ -302,4 +313,46 @@ protected JLabel createLabel(String text) { return label; } + @Override + public void attachFunctionalKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, Runnable action) { + var inputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + inputMap.put(keyStroke, actionMapKey); + var actionMap = panel.getActionMap(); + var actionInstance = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }; + actionMap.put(actionMapKey, actionInstance); + } + + @Override + public void attachKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, AbstractAction action) { + var inputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + inputMap.put(keyStroke, actionMapKey); + var actionMap = panel.getActionMap(); + actionMap.put(actionMapKey, action); + } + + public void attachSaveAction(Runnable action) { + var actionInstance = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }; + saveButton.addActionListener(actionInstance); + } + + public void attachContinueAction(Runnable action) { + var actionInstance = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }; + createAnotherButton.addActionListener(actionInstance); + attachKeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK, true), "Ctrl+Enter released", actionInstance); + } } \ No newline at end of file diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageViewer.java b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageViewer.java index 6f07643..03060ca 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageViewer.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogPageViewer.java @@ -9,8 +9,11 @@ public interface DialogPageViewer { public void setContent(String newContent); - public void setBlip(String newBlip); public String getBlip(); - public void setStyle(String newStyle); + + public void setBlip(String newBlip); + public String getStyle(); + + public void setStyle(String newStyle); } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogViewer.java b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogViewer.java index 1ac93ad..dd298eb 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/DialogViewer.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/DialogViewer.java @@ -1,7 +1,7 @@ package best.tigers.tynk_dialog.gui.view; public interface DialogViewer { - public String getTitle(); + String getTitle(); - public void setTitle(String newTitle); + void setTitle(String newTitle); } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/PrimaryListView.java b/src/main/java/best/tigers/tynk_dialog/gui/view/PrimaryListView.java index aaa8eb9..9402dc6 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/PrimaryListView.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/PrimaryListView.java @@ -6,51 +6,76 @@ import best.tigers.tynk_dialog.gui.view.components.DialogCellRenderer; import best.tigers.tynk_dialog.gui.view.components.MenuBar; -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextField; +import javax.swing.JToolBar; +import javax.swing.WindowConstants; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; -public class PrimaryListView implements Observer { - final private JFrame frame; +public class PrimaryListView implements TObserver { + private static final Dimension PREFERRED_SIZE = new Dimension(600, 400); + private final JFrame frame; + private final JSplitPane splitPane; + private final JList dialogList; + private final MenuBar menuBar; + private final JToolBar toolBar; + private final JTextField currentRoom; + private final JPanel panel; private PrimaryListModel model; - final private JSplitPane splitPane; - final private JList dialogList; - final private MenuBar menuBar; - final private JToolBar toolBar; - final private JTextField currentRoom; - - final public static Dimension PREFERRED_SIZE = new Dimension(600, 400); - public PrimaryListView(PrimaryListModel model) { - Assets.runIntegrations(); - frame = new JFrame(); - frame.setTitle("Tynk Dialog Editor - " + model.getPath()); + private PrimaryListView(PrimaryListModel model) { this.model = model; - subscribe(this.model); - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); + frame = new JFrame(); menuBar = new MenuBar(frame); dialogList = new JList<>(this.model); - JScrollPane listPanel = new JScrollPane(dialogList); + toolBar = new JToolBar(); + currentRoom = new JTextField(); + panel = new JPanel(); + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panel, new JPanel()); + subscribe(this.model); + } + + public static PrimaryListView fromModel(PrimaryListModel model) { + var view = new PrimaryListView(model); + view.setupView(); + return view; + } + + private void setupView() { + panel.setLayout(new BorderLayout()); dialogList.setCellRenderer(new DialogCellRenderer()); + + var listPanel = new JScrollPane(dialogList); listPanel.setMinimumSize(new Dimension(200, 200)); - toolBar = new JToolBar(); - toolBar.setFloatable(false); - toolBar.setMaximumSize(new Dimension(Short.MAX_VALUE, 150)); panel.add(listPanel, BorderLayout.CENTER); + setupSelectionListener(); - var roomSubPanel = new JPanel(); - roomSubPanel.setLayout(new BorderLayout()); - roomSubPanel.add(new JLabel(" Room: "), BorderLayout.WEST); - currentRoom = new JTextField(); - roomSubPanel.add(currentRoom, BorderLayout.CENTER); - panel.add(roomSubPanel, BorderLayout.NORTH); + buildToolbar(); panel.add(toolBar, BorderLayout.SOUTH); - splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panel, new JPanel()); + + var roomSubPanel = buildRoomSubPanel(); + panel.add(roomSubPanel, BorderLayout.NORTH); + splitPane.setEnabled(false); + splitPane.revalidate(); + setupFrame(); + } + + private void setupFrame() { + frame.setTitle("Tynk Dialog Editor - " + model.getPath()); frame.add(splitPane); frame.setPreferredSize(PREFERRED_SIZE); frame.setMinimumSize(PREFERRED_SIZE); @@ -58,16 +83,29 @@ public PrimaryListView(PrimaryListModel model) { frame.setLocationRelativeTo(null); frame.setVisible(true); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - splitPane.revalidate(); + } + private void buildToolbar() { + toolBar.setFloatable(false); + toolBar.setMaximumSize(new Dimension(Short.MAX_VALUE, 150)); + } + private JPanel buildRoomSubPanel() { + var roomSubPanel = new JPanel(); + roomSubPanel.setLayout(new BorderLayout()); + roomSubPanel.add(new JLabel(" Room: "), BorderLayout.WEST); + roomSubPanel.add(currentRoom, BorderLayout.CENTER); + return roomSubPanel; + } - dialogList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - update(); - } - }); + private void setupSelectionListener() { + dialogList.addListSelectionListener( + new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + update(); + } + }); } public void swapModel(PrimaryListModel model) { @@ -82,14 +120,15 @@ public DialogController currentSelection() { return dialogList.getSelectedValue(); } - public void addMenuItem(ActionListener action, String shortText, String longText, MenuBar.Menu menu) { - JMenuItem newItem = new JMenuItem(); + public void addMenuItem( + ActionListener action, String shortText, String longText, MenuBar.Menu menu) { + var newItem = new JMenuItem(); newItem.addActionListener(action); newItem.setText(shortText); newItem.setToolTipText(longText); menuBar.addItem(menu, newItem); if (menu == MenuBar.Menu.EDIT) { - JButton toolButton = new JButton(); + var toolButton = new JButton(); toolButton.addActionListener(action); toolButton.setText(shortText.split(" ")[0]); toolBar.add(toolButton); @@ -123,7 +162,12 @@ public void attachWindowEvent(WindowAdapter adapter) { public int prompt() { if (model.isModified()) { - return JOptionPane.showConfirmDialog(null, "You haven't saved this file since the last changes were made. Would you like to save before continuing?", "Hold on--", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); + return JOptionPane.showConfirmDialog( + null, + "You haven't saved this file since the last changes were made. Would you like to save before continuing?", + "Hold on--", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.WARNING_MESSAGE); } else { return 1; } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/ShortcutSupport.java b/src/main/java/best/tigers/tynk_dialog/gui/view/ShortcutSupport.java new file mode 100644 index 0000000..d3b1c9b --- /dev/null +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/ShortcutSupport.java @@ -0,0 +1,8 @@ +package best.tigers.tynk_dialog.gui.view; + +import javax.swing.*; + +public interface ShortcutSupport { + void attachFunctionalKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, Runnable action); + void attachKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, AbstractAction action); +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/Observer.java b/src/main/java/best/tigers/tynk_dialog/gui/view/TObserver.java similarity index 91% rename from src/main/java/best/tigers/tynk_dialog/gui/view/Observer.java rename to src/main/java/best/tigers/tynk_dialog/gui/view/TObserver.java index 7726d4c..43536d9 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/Observer.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/TObserver.java @@ -2,7 +2,7 @@ import best.tigers.tynk_dialog.gui.model.AbstractModel; -public interface Observer { +public interface TObserver { void update(); default void subscribe(AbstractModel model) { diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/components/AutoResizingTable.java b/src/main/java/best/tigers/tynk_dialog/gui/view/components/AutoResizingTable.java index 15a4732..4d5fbc9 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/components/AutoResizingTable.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/components/AutoResizingTable.java @@ -1,44 +1,92 @@ package best.tigers.tynk_dialog.gui.view.components; +import best.tigers.tynk_dialog.gui.model.DialogModel; +import best.tigers.tynk_dialog.gui.view.ShortcutSupport; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.HierarchyBoundsAdapter; +import java.awt.event.HierarchyEvent; import javax.swing.*; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; -import java.awt.*; -import java.awt.event.HierarchyBoundsAdapter; -import java.awt.event.HierarchyEvent; +import javax.swing.table.TableModel; -public class AutoResizingTable extends JTable { - public AutoResizingTable() { - super(); - addHierarchyBoundsListener(new HierarchyBoundsAdapter() { - @Override - public void ancestorResized(HierarchyEvent e) { +public class AutoResizingTable extends JTable implements ShortcutSupport { + public AutoResizingTable(TableModel model) { + super(); + setModel(model); + addHierarchyBoundsListener( + new HierarchyBoundsAdapter() { + @Override + public void ancestorResized(HierarchyEvent e) { super.ancestorResized(e); - resizeColumnWidth(); - } - }); - setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - } + if (getParent() != null) { + resizeColumnWidth(); + } + } + }); + } + + public static AutoResizingTable fromDialogPageModel(DialogModel model) { + var table = new AutoResizingTable(model.getDptm()); + table.setupView(); + return table; + } + + private void setupView() { + setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + setDragEnabled(true); + setDropMode(DropMode.ON_OR_INSERT); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + var columnModel = getColumnModel(); + columnModel.getColumn(0).setPreferredWidth(20); + var tableHeader = getTableHeader(); + tableHeader.setResizingAllowed(true); + tableHeader.setReorderingAllowed(false); + } - public void resizeColumnWidth() { - int cumulativeActual = 0; - int padding = 15; - for (int columnIndex = 0; columnIndex < getColumnCount(); columnIndex++) { - int width = 50; // Min width - TableColumn column = columnModel.getColumn(columnIndex); - for (int row = 0; row < getRowCount(); row++) { - TableCellRenderer renderer = getCellRenderer(row, columnIndex); - Component comp = prepareRenderer(renderer, row, columnIndex); - width = Math.max(comp.getPreferredSize().width + padding, width); - } - if (columnIndex < getColumnCount() - 1) { - column.setPreferredWidth(width); - cumulativeActual += column.getWidth(); - } else { //LAST COLUMN - //Use the parent's (viewPort) width and subtract the previous columbs actual widths. - column.setPreferredWidth((int) getParent().getSize().getWidth() - cumulativeActual); - } - } + public void resizeColumnWidth() { + int cumulativeActual = 0; + int padding = 15; + for (int columnIndex = 0; columnIndex < getColumnCount(); columnIndex++) { + int width = 50; // Min width + TableColumn column = columnModel.getColumn(columnIndex); + for (int row = 0; row < getRowCount(); row++) { + TableCellRenderer renderer = getCellRenderer(row, columnIndex); + Component comp = prepareRenderer(renderer, row, columnIndex); + width = Math.max(comp.getPreferredSize().width + padding, width); + } + if (columnIndex < getColumnCount() - 1) { + column.setPreferredWidth(width); + cumulativeActual += column.getWidth(); + } else { // LAST COLUMN + // Use the parent's (viewPort) width and subtract the previous columbs actual widths. + column.setPreferredWidth((int) getParent().getSize().getWidth() - cumulativeActual); + } } + } + + @Override + public void attachFunctionalKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, Runnable action) { + var inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(keyStroke, actionMapKey); + var actionMap = getActionMap(); + var actionInstance = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + action.run(); + } + }; + actionMap.put(actionMapKey, actionInstance); + } + + @Override + public void attachKeyboardShortcut(KeyStroke keyStroke, String actionMapKey, AbstractAction action) { + var inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(keyStroke, actionMapKey); + var actionMap = getActionMap(); + actionMap.put(actionMapKey, action); + } } diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/components/DialogCellRenderer.java b/src/main/java/best/tigers/tynk_dialog/gui/view/components/DialogCellRenderer.java index 180af27..7a287b7 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/components/DialogCellRenderer.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/components/DialogCellRenderer.java @@ -1,26 +1,31 @@ package best.tigers.tynk_dialog.gui.view.components; import best.tigers.tynk_dialog.gui.controller.DialogController; - -import javax.swing.*; +import java.awt.Color; +import java.awt.Component; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; import javax.swing.border.EmptyBorder; -import java.awt.*; public class DialogCellRenderer extends JLabel implements ListCellRenderer { @Override - public Component getListCellRendererComponent(JList list, DialogController value, int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent( + JList list, + DialogController value, + int index, + boolean isSelected, + boolean cellHasFocus) { setText(value.getModel().getTitle()); Color background; Color foreground; - setBorder(new EmptyBorder(5,5,5,5)); + setBorder(new EmptyBorder(5, 5, 5, 5)); // check if this cell represents the current DnD drop location setOpaque(true); JList.DropLocation dropLocation = list.getDropLocation(); - if (dropLocation != null - && !dropLocation.isInsert() - && dropLocation.getIndex() == index) { + if (dropLocation != null && !dropLocation.isInsert() && dropLocation.getIndex() == index) { background = Color.BLUE; foreground = Color.WHITE; diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/components/IntegerDialog.java b/src/main/java/best/tigers/tynk_dialog/gui/view/components/IntegerDialog.java new file mode 100644 index 0000000..d522b4c --- /dev/null +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/components/IntegerDialog.java @@ -0,0 +1,162 @@ +package best.tigers.tynk_dialog.gui.view.components; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.text.AbstractDocument; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DocumentFilter; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; +import java.security.Key; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class IntegerDialog { + private final JDialog dialog; + private int value; + private final JTextField intField; + private final JButton okayButton; + + public IntegerDialog() { + value = 0; + intField = new JTextField(); + dialog = new JDialog(); + dialog.setModal(true); + okayButton = new JButton("OK (Enter)"); + } + + public static int promptForInteger() { + var prompt = new IntegerDialog(); + prompt.init(); + return prompt.getValue(); + } + + public int getValue() { + return value; + } + + public void setValue(int newValue) { + value = newValue; + } + + private void init() { + setupIntegerField(); + // apply layout + setupInnerPanel(); + var panel = (JPanel) dialog.getContentPane(); + var validateAndExitAction = createValidateAndExitAction(); + + // setup keyboard shortcuts + var enterMapKey = "EnterKey"; + var enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); + var inputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + var actionMap = panel.getActionMap(); + + inputMap.put(enterKey, enterMapKey); + actionMap.put(enterMapKey, validateAndExitAction); + + okayButton.addActionListener(validateAndExitAction); + dialog.setVisible(true); + focusInput(); + } + + private void focusInput() { + intField.requestFocus(); + } + + private void setupInnerPanel() { + var inner = new JPanel(); + var layout = new GroupLayout(inner); + + layout.setAutoCreateGaps(true); + layout.setAutoCreateContainerGaps(true); + + var promptLabel = new JLabel("Enter a number for the delay"); + var inputIcon = new JLabel(UIManager.getIcon("OptionPane.questionIcon")); + + inner.setBorder(new EmptyBorder(4, 4, 4, 4)); + inner.setLayout(layout); + + var spacer = new JPanel(); + layout.setHorizontalGroup( + layout + .createParallelGroup(GroupLayout.Alignment.CENTER) + .addGroup( + layout + .createSequentialGroup() + .addComponent(inputIcon, 60, 60, 60) + .addGroup( + layout + .createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(promptLabel) + .addComponent(intField)) + .addComponent(spacer, 30, 30, 30)) + .addComponent(okayButton)); + layout.setVerticalGroup( + layout + .createSequentialGroup() + .addGroup(layout.createSequentialGroup().addComponent(promptLabel)) + .addGroup( + layout + .createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(inputIcon, 60, 60, 60) + .addComponent( + intField, + intField.getPreferredSize().height, + intField.getPreferredSize().height, + intField.getPreferredSize().height) + .addComponent(spacer, 30, 30, 30)) + .addComponent(okayButton)); + + inner.setSize(new Dimension(400, 240)); + dialog.setLayout(new BorderLayout()); + dialog.add(inner, BorderLayout.CENTER); + dialog.pack(); + dialog.setLocationRelativeTo(dialog.getParent()); + } + + private AbstractAction createValidateAndExitAction() { + return new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + var valueString = intField.getText(); + if (valueString != null && !valueString.equals("") && Integer.parseInt(valueString) > 0) { + setValue(Integer.parseInt(valueString)); + closeDialog(); + } else { + java.awt.Toolkit.getDefaultToolkit().beep(); + focusInput(); + } + } + }; + } + + private void closeDialog() { + dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING)); + } + + private void setupIntegerField() { + ((AbstractDocument) intField.getDocument()) + .setDocumentFilter( + new DocumentFilter() { + final Pattern regEx = Pattern.compile("\\d*"); + + @Override + public void replace( + FilterBypass fb, int offset, int length, String text, AttributeSet attrs) { + Matcher matcher = regEx.matcher(text); + if (!matcher.matches()) { + return; + } + try { + super.replace(fb, offset, length, text, attrs); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + }); + } +} diff --git a/src/main/java/best/tigers/tynk_dialog/gui/view/components/MenuBar.java b/src/main/java/best/tigers/tynk_dialog/gui/view/components/MenuBar.java index 2f18b91..228a218 100644 --- a/src/main/java/best/tigers/tynk_dialog/gui/view/components/MenuBar.java +++ b/src/main/java/best/tigers/tynk_dialog/gui/view/components/MenuBar.java @@ -1,17 +1,15 @@ package best.tigers.tynk_dialog.gui.view.components; -import javax.swing.*; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; public class MenuBar { private final JMenuBar menuBar; private final JMenu fileMenu; private final JMenu editMenu; private final JMenu helpMenu; - public enum Menu { - FILE, - EDIT, - HELP - } public MenuBar(JFrame frame) { menuBar = new JMenuBar(); @@ -20,7 +18,7 @@ public MenuBar(JFrame frame) { helpMenu = new JMenu("Help"); menuBar.add(fileMenu); menuBar.add(editMenu); - //menuBar.add(helpMenu); + // menuBar.add(helpMenu); frame.setJMenuBar(menuBar); } @@ -49,4 +47,10 @@ public void addEditItem(JMenuItem item) { public void addHelpItem(JMenuItem item) { helpMenu.add(item); } + + public enum Menu { + FILE, + EDIT, + HELP + } } diff --git a/src/main/java/best/tigers/tynk_dialog/util/DialogBuilder.java b/src/main/java/best/tigers/tynk_dialog/util/DialogBuilder.java index 694dc1e..43ff596 100644 --- a/src/main/java/best/tigers/tynk_dialog/util/DialogBuilder.java +++ b/src/main/java/best/tigers/tynk_dialog/util/DialogBuilder.java @@ -3,17 +3,15 @@ import best.tigers.tynk_dialog.exceptions.DialogParseException; import best.tigers.tynk_dialog.game.Dialog; import best.tigers.tynk_dialog.game.DialogPage; - +import java.util.ArrayList; import javax.json.JsonObject; import javax.json.JsonValue; -import java.util.ArrayList; public class DialogBuilder { private String title; private ArrayList contents; - public DialogBuilder() { - } + public DialogBuilder() {} void ParseJSON(JsonObject dialogData) throws DialogParseException { title = dialogData.getString("title"); @@ -21,8 +19,12 @@ void ParseJSON(JsonObject dialogData) throws DialogParseException { for (JsonValue currentPage : dialogData.getJsonArray("contents")) { DialogPageBuilder pageBuilder = new DialogPageBuilder(); if (currentPage.getValueType() != JsonValue.ValueType.OBJECT) { - throw new DialogParseException("Received an unexpected type while processing " - + "dialog \"" + title + "\": " + currentPage.getValueType()); + throw new DialogParseException( + "Received an unexpected type while processing " + + "dialog \"" + + title + + "\": " + + currentPage.getValueType()); } pageBuilder.ParseJSON(currentPage.asJsonObject()); contents.add(pageBuilder.build()); @@ -41,8 +43,7 @@ class DialogPageBuilder { private String blip; private boolean canSkip; - public DialogPageBuilder() { - } + public DialogPageBuilder() {} public boolean verify() { return content != null && speaker != null; diff --git a/src/main/java/best/tigers/tynk_dialog/util/DialogFile.java b/src/main/java/best/tigers/tynk_dialog/util/DialogFile.java index f08b569..2c51c57 100644 --- a/src/main/java/best/tigers/tynk_dialog/util/DialogFile.java +++ b/src/main/java/best/tigers/tynk_dialog/util/DialogFile.java @@ -3,22 +3,26 @@ import best.tigers.tynk_dialog.exceptions.DialogFileIOException; import best.tigers.tynk_dialog.exceptions.DialogParseException; import best.tigers.tynk_dialog.game.Dialog; - -import javax.json.*; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonReader; +import javax.json.JsonStructure; +import javax.json.JsonValue; +import javax.json.JsonWriter; public class DialogFile { - final private static String SEP = System.getProperty("file.separator"); - final private static String DEFAULT_PATH = System.getProperty("user.home") + SEP + "dialog.json"; - + private static final String SEP = System.getProperty("file.separator"); + private static final String DEFAULT_PATH = System.getProperty("user.home") + SEP + "dialog.json"; + private final LinkedList errors; private String path; private boolean customized = true; - private final LinkedList errors; public DialogFile(String path) { errors = new LinkedList<>(); @@ -45,8 +49,10 @@ public ArrayList readFile() throws DialogFileIOException { } JsonStructure jsonData = x.read(); if (jsonData.getValueType() != JsonValue.ValueType.ARRAY) { - throw new DialogFileIOException("The JSON file's data must be presented as an array, " + - "but this looks like " + jsonData.getValueType()); + throw new DialogFileIOException( + "The JSON file's data must be presented as an array, " + + "but this looks like " + + jsonData.getValueType()); } ArrayList dialog = new ArrayList(); for (JsonValue item : jsonData.asJsonArray()) { @@ -73,7 +79,8 @@ public void writeFile(ArrayList dialogData) throws DialogFileIOException writer = Json.createWriter(new FileWriter(path)); } catch (IOException ioe) { System.err.println(ioe.getLocalizedMessage()); - Log.error("(FATAL) IOException encountered while trying to save file " + ioe.getLocalizedMessage()); + Log.error( + "(FATAL) IOException encountered while trying to save file " + ioe.getLocalizedMessage()); System.exit(1); } Log.info("Successfully opened file, writing data..."); diff --git a/src/main/java/best/tigers/tynk_dialog/util/Log.java b/src/main/java/best/tigers/tynk_dialog/util/Log.java index eee48f8..6a77bff 100644 --- a/src/main/java/best/tigers/tynk_dialog/util/Log.java +++ b/src/main/java/best/tigers/tynk_dialog/util/Log.java @@ -3,7 +3,8 @@ import java.util.logging.Logger; public class Log { - final private static Logger logger = java.util.logging.Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + private static final Logger logger = + java.util.logging.Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); public static void info(String logMessage) { logger.info(logMessage); diff --git a/src/main/java/best/tigers/tynk_dialog/util/ParseUtils.java b/src/main/java/best/tigers/tynk_dialog/util/ParseUtils.java index af54c95..2e7714a 100644 --- a/src/main/java/best/tigers/tynk_dialog/util/ParseUtils.java +++ b/src/main/java/best/tigers/tynk_dialog/util/ParseUtils.java @@ -1,8 +1,8 @@ package best.tigers.tynk_dialog.util; +import java.util.Optional; import javax.json.JsonString; import javax.json.JsonValue; -import java.util.Optional; public class ParseUtils { public static Optional getNullableTynkValue(JsonValue val) { @@ -12,5 +12,4 @@ public static Optional getNullableTynkValue(JsonValue val) { } return Optional.empty(); } - } diff --git a/src/test/java/best/tigers/tynk_dialog/BlipTest.java b/src/test/java/best/tigers/tynk_dialog/BlipTest.java index 6d5d6b3..0699a61 100644 --- a/src/test/java/best/tigers/tynk_dialog/BlipTest.java +++ b/src/test/java/best/tigers/tynk_dialog/BlipTest.java @@ -10,6 +10,5 @@ void testToString() { } @Test - void serialize() { - } -} \ No newline at end of file + void serialize() {} +} diff --git a/src/test/java/best/tigers/tynk_dialog/CharacterTest.java b/src/test/java/best/tigers/tynk_dialog/CharacterTest.java index f6fe5fd..556326e 100644 --- a/src/test/java/best/tigers/tynk_dialog/CharacterTest.java +++ b/src/test/java/best/tigers/tynk_dialog/CharacterTest.java @@ -5,6 +5,5 @@ class CharacterTest { @Test - void testToString() { - } -} \ No newline at end of file + void testToString() {} +} diff --git a/src/test/java/best/tigers/tynk_dialog/DialogPageTest.java b/src/test/java/best/tigers/tynk_dialog/DialogPageTest.java index 6e480d4..30a1d57 100644 --- a/src/test/java/best/tigers/tynk_dialog/DialogPageTest.java +++ b/src/test/java/best/tigers/tynk_dialog/DialogPageTest.java @@ -3,10 +3,8 @@ class DialogPageTest { @org.junit.jupiter.api.Test - void testToString() { - } + void testToString() {} @org.junit.jupiter.api.Test - void serialize() { - } -} \ No newline at end of file + void serialize() {} +} diff --git a/src/test/java/best/tigers/tynk_dialog/DialogTest.java b/src/test/java/best/tigers/tynk_dialog/DialogTest.java index 69f1304..014c8fd 100644 --- a/src/test/java/best/tigers/tynk_dialog/DialogTest.java +++ b/src/test/java/best/tigers/tynk_dialog/DialogTest.java @@ -1,5 +1,3 @@ package best.tigers.tynk_dialog; -class DialogTest { - -} \ No newline at end of file +class DialogTest {} diff --git a/src/test/java/best/tigers/tynk_dialog/FormattedTextTest.java b/src/test/java/best/tigers/tynk_dialog/FormattedTextTest.java index 04ac23a..ac14c97 100644 --- a/src/test/java/best/tigers/tynk_dialog/FormattedTextTest.java +++ b/src/test/java/best/tigers/tynk_dialog/FormattedTextTest.java @@ -5,6 +5,5 @@ class FormattedTextTest { @Test - void testToString() { - } -} \ No newline at end of file + void testToString() {} +} diff --git a/src/test/java/best/tigers/tynk_dialog/StyleTest.java b/src/test/java/best/tigers/tynk_dialog/StyleTest.java index 17d3dbe..3506e53 100644 --- a/src/test/java/best/tigers/tynk_dialog/StyleTest.java +++ b/src/test/java/best/tigers/tynk_dialog/StyleTest.java @@ -5,6 +5,5 @@ class StyleTest { @Test - void serialize() { - } -} \ No newline at end of file + void serialize() {} +}