From 0bade39c90c00cb033ee26296a86553f15dd6352 Mon Sep 17 00:00:00 2001 From: Disturbo Date: Wed, 29 Apr 2020 21:49:21 +0200 Subject: [PATCH] Initial commit Code release commit --- .idea/.gitignore | 3 + .idea/.name | 1 + .idea/artifacts/Decomp_Trainer_Editor_jar.xml | 8 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/uiDesigner.xml | 124 ++++ .idea/vcs.xml | 6 + Decomp Trainer Editor.iml | 11 + src/main/MainActivity.java | 31 + src/main/Utils.java | 25 + src/types/PartyMember.java | 88 +++ src/types/Trainer.java | 197 +++++++ src/types/TrainerClass.java | 7 + src/ui/ComboBoxFiltered.java | 100 ++++ src/ui/ImagePanel.java | 25 + src/ui/MemberSelector.java | 225 ++++++++ src/ui/PartyMemberInput.java | 162 ++++++ src/ui/Screen.java | 538 ++++++++++++++++++ src/ui/SpeciesRenderer.java | 29 + src/ui/TextFieldLimiter.java | 37 ++ src/utils/DataManager.java | 509 +++++++++++++++++ src/utils/DirectoryChooser.java | 21 + 22 files changed, 2161 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/artifacts/Decomp_Trainer_Editor_jar.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/vcs.xml create mode 100644 Decomp Trainer Editor.iml create mode 100644 src/main/MainActivity.java create mode 100644 src/main/Utils.java create mode 100644 src/types/PartyMember.java create mode 100644 src/types/Trainer.java create mode 100644 src/types/TrainerClass.java create mode 100644 src/ui/ComboBoxFiltered.java create mode 100644 src/ui/ImagePanel.java create mode 100644 src/ui/MemberSelector.java create mode 100644 src/ui/PartyMemberInput.java create mode 100644 src/ui/Screen.java create mode 100644 src/ui/SpeciesRenderer.java create mode 100644 src/ui/TextFieldLimiter.java create mode 100644 src/utils/DataManager.java create mode 100644 src/utils/DirectoryChooser.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..11669b7 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Decomp Trainer Editor \ No newline at end of file diff --git a/.idea/artifacts/Decomp_Trainer_Editor_jar.xml b/.idea/artifacts/Decomp_Trainer_Editor_jar.xml new file mode 100644 index 0000000..205763a --- /dev/null +++ b/.idea/artifacts/Decomp_Trainer_Editor_jar.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/out/artifacts/Decomp_Trainer_Editor_jar + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0548357 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4e99bf9 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Decomp Trainer Editor.iml b/Decomp Trainer Editor.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/Decomp Trainer Editor.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/MainActivity.java b/src/main/MainActivity.java new file mode 100644 index 0000000..6b32f05 --- /dev/null +++ b/src/main/MainActivity.java @@ -0,0 +1,31 @@ +package main; + +import types.Trainer; +import types.TrainerClass; +import ui.Screen; + +import java.io.File; +import java.util.LinkedHashMap; +import java.util.LinkedList; + +public class MainActivity { + public static Screen screen; + public static File projectDirectory = null; + + public static String currentTrainer = null; + public static LinkedHashMap trainerIndexes; + public static LinkedHashMap partyIndexes; + public static LinkedHashMap trainerClasses; + public static LinkedList items; + public static LinkedHashMap moves; + public static LinkedHashMap species; + public static LinkedList music; + public static LinkedList aiFlags; + public static LinkedList picList; + public static LinkedHashMap picPaths; + public static LinkedHashMap loadedTrainers = new LinkedHashMap<>(); + + public static void main(String[] args){ + screen = new Screen(); + } +} diff --git a/src/main/Utils.java b/src/main/Utils.java new file mode 100644 index 0000000..bf8ce90 --- /dev/null +++ b/src/main/Utils.java @@ -0,0 +1,25 @@ +package main; + +import java.util.List; + +public class Utils { + public static boolean isNumeric(String text){ + if (text == null) return false; + try { + double d = Double.parseDouble(text); + } + catch (NumberFormatException exception) { + return false; + } + return true; + } + + public static String getLongestString(List list){ + String longest = list.get(0); + for(String element : list){ + if(element != null) + if(element.length() > longest.length()) longest = element; + } + return longest; + } +} diff --git a/src/types/PartyMember.java b/src/types/PartyMember.java new file mode 100644 index 0000000..3d41a8f --- /dev/null +++ b/src/types/PartyMember.java @@ -0,0 +1,88 @@ +package types; + +import main.MainActivity; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; + +public class PartyMember { + public static final String[] fields = {"iv", "lvl", "species", "heldItem", "moves"}; + + public String iv; + public String level; + public String species; + public String heldItem; + public ArrayList moves; + + public PartyMember(){ + iv = "0"; + level = "0"; + LinkedList keys = new LinkedList<>(MainActivity.species.keySet()); + species = keys.get(0); + heldItem = MainActivity.items.get(0); + moves = new ArrayList<>(); + } + + public PartyMember(HashMap values){ + iv = values.get("iv"); + level = values.get("lvl"); + species = values.get("species"); + heldItem = values.get("heldItem"); + moves = extractMoves(values.get("moves")); + } + + public static HashMap templateValues(){ + HashMap template = new HashMap<>(); + for(String field: fields){ + template.put(field, ""); + } + return template; + } + + public static ArrayList extractMoves(String moves){ + if(moves.length() == 0) return new ArrayList<>(); + return new ArrayList<>(Arrays.asList(moves.substring(1, moves.length() - 1).split(","))); + } + + private String buildMoves(){ + String moves = ""; + for (int index = 0; index < this.moves.size(); index++) { + moves += this.moves.get(index); + if (index != this.moves.size() - 1) { + moves += ", "; + } + } + return "{" + moves + "}"; + } + + public boolean hasCustomMoves(){ + boolean hasCustomMoves = false; + LinkedList keys = new LinkedList<>(MainActivity.moves.keySet()); + for (int index = 0; index < this.moves.size(); index++) { + if(!moves.get(index).equals(keys.get(0))) hasCustomMoves = true; + } + return hasCustomMoves; + } + + public String buildMemberStruct(boolean partyHasCustomItems, boolean partyHasCustomMoves){ + String struct = " {" + System.lineSeparator(); + struct += " .iv = " + iv + "," + System.lineSeparator(); + struct += " .lvl = " + level + "," + System.lineSeparator(); + String speciesBuild = " .species = " + this.species; + String heldItemBuild = " .heldItem = " + this.heldItem; + String movesBuild = " .moves = " + buildMoves(); + struct += speciesBuild + "," + System.lineSeparator(); + if(partyHasCustomItems) { + if (!partyHasCustomMoves) struct += heldItemBuild + System.lineSeparator(); + else{ + struct += heldItemBuild + "," + System.lineSeparator(); + struct += movesBuild + System.lineSeparator(); + } + } + else if (partyHasCustomMoves) struct += movesBuild + System.lineSeparator(); + struct += " }"; + return struct; + } +} diff --git a/src/types/Trainer.java b/src/types/Trainer.java new file mode 100644 index 0000000..9acb622 --- /dev/null +++ b/src/types/Trainer.java @@ -0,0 +1,197 @@ +package types; + +import main.MainActivity; +import utils.DataManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; + +public class Trainer { + public static final String[] fields = {"partyFlags", "trainerClass", "encounterMusic_gender", "trainerPic", "trainerName" + , "items", "doubleBattle", "aiFlags", "partySize", "party"}; + + + public String key; + public String partyFlags; + public String trainerClass; + public String music; + public String gender; + public String trainerPic; + public String trainerName; + public ArrayList items; + public boolean doubleBattle; + public ArrayList aiFlags; + public String partySize; + public String partyName; + public LinkedList party; + + public Trainer(String key, HashMap values){ + this.key = key; + partyFlags = values.get("partyFlags"); + trainerClass = values.get("trainerClass"); + music = extractMusic(values.get("encounterMusic_gender")); + gender = extractGender(values.get("encounterMusic_gender")); + trainerPic = values.get("trainerPic"); + trainerName = extractTrainerName(values.get("trainerName")); + items = extractItems(values.get("items")); + doubleBattle = Boolean.parseBoolean(values.get("doubleBattle")); + aiFlags = extractAiFlags(values.get("aiFlags")); + partySize = values.get("partySize"); + partyName = extractPartyName(values.get("party")); + party = DataManager.loadParty(partyName); + } + + public static HashMap templateValues(){ + HashMap template = new HashMap<>(); + for(String field: fields){ + template.put(field, ""); + } + return template; + } + + private String extractTrainerName(String name){ + return name.replace("\"", "").replace("_(", "").replace(")", ""); + } + + private String buildTrainerName(){ + return "_(\"" + trainerName + "\")"; + } + + private String extractMusic(String music){ + if(music.contains("|")) return music.split("\\|")[1]; + else return music; + } + + private String extractGender(String music){ + if(music.contains("|")) return music.split("\\|")[0]; + else return ""; + } + + private String buildMusicGender(){ + String musicGender = ""; + if(!gender.equals("")) musicGender += gender + " | "; + return musicGender + music; + } + + private ArrayList extractItems(String items){ + if(items.equals("{}")) return new ArrayList<>(); + items = items.replace("{", "").replace("}", "").replaceAll(" ", ""); + return new ArrayList<>(Arrays.asList(items.split(","))); + } + + private String buildTrainerItems(){ + String items = ""; + boolean areAllItemsNone = true; + for (int index = 0; index < this.items.size(); index++) { + String item = this.items.get(index); + if(!item.equals(MainActivity.items.get(0))) areAllItemsNone = false; + items += item; + if (index != this.items.size() - 1) { + items += ", "; + } + } + if(areAllItemsNone) items = ""; + return "{" + items + "}"; + } + + private String buildDoubleBattle(){ + if(doubleBattle) return "TRUE"; + else return "FALSE"; + } + + private ArrayList extractAiFlags(String flags){ + return new ArrayList<>(Arrays.asList(flags.split("\\|"))); + } + private String buildAiFlags(){ + String flags = ""; + for(int index = 0; index < aiFlags.size(); index++){ + flags += aiFlags.get(index); + if(index != aiFlags.size() - 1){ + flags += " | "; + } + } + if(flags.equals("")) flags = "0"; + return flags; + } + + private String extractPartyName(String name){ + return name.split("=")[1].replace("}", ""); + } + + private String buildPartyName(){ + return "{." + getPartyType().substring("TrainerMon".length()) + " = " + partyName + "}"; + } + + public String getPartyType(){ + String partyType = "TrainerMon"; + if(!partyHasCustomItems()) partyType += "No"; + partyType += "Item"; + if(!partyHasCustomMoves()) partyType += "Default"; + else partyType += "Custom"; + partyType += "Moves"; + return partyType; + } + + public String getPartyFlags(){ + String partyType = "0"; + if(partyHasCustomItems()) partyType = "F_TRAINER_PARTY_HELD_ITEM"; + if(partyHasCustomMoves()){ + if(partyType.equals("0")) partyType = "F_TRAINER_PARTY_CUSTOM_MOVESET"; + else partyType += " | F_TRAINER_PARTY_CUSTOM_MOVESET"; + } + partyType += ""; + return partyType; + } + + public boolean partyHasCustomMoves(){ + boolean hasCustomMoves = false; + for(PartyMember member : party){ + if(member.hasCustomMoves()){ + hasCustomMoves = true; + break; + } + } + return hasCustomMoves; + } + + public boolean partyHasCustomItems(){ + boolean hasCustomItems = false; + for(PartyMember member : party){ + if(member.heldItem != MainActivity.items.get(0)){ + hasCustomItems = true; + break; + } + } + return hasCustomItems; + } + + public String buildTrainerStruct(){ + String struct = " [" + key + "] =" + System.lineSeparator(); + struct += " {" + System.lineSeparator(); + struct += " .partyFlags = " + getPartyFlags() + "," + System.lineSeparator(); + struct += " .trainerClass = " + trainerClass + "," + System.lineSeparator(); + struct += " .encounterMusic_gender = " + buildMusicGender() + "," + System.lineSeparator(); + struct += " .trainerPic = " + trainerPic + "," + System.lineSeparator(); + struct += " .trainerName = " + buildTrainerName() + "," + System.lineSeparator(); + struct += " .items = " + buildTrainerItems() + "," + System.lineSeparator(); + struct += " .doubleBattle = " + buildDoubleBattle() + "," + System.lineSeparator(); + struct += " .aiFlags = " + buildAiFlags() + "," + System.lineSeparator(); + struct += " .partySize = " + partySize + "," + System.lineSeparator(); + struct += " .party = " + buildPartyName() + "," + System.lineSeparator(); + struct += " }," + System.lineSeparator() + System.lineSeparator(); + return struct; + } + + public String buildPartyStruct(){ + String struct = "static const struct " + getPartyType() + " " + partyName + "[] = {" + System.lineSeparator(); + for(int index = 0; index < party.size(); index++){ + struct += party.get(index).buildMemberStruct(partyHasCustomItems(), partyHasCustomMoves()); + if(index < party.size() - 1) struct += ","; + struct += System.lineSeparator(); + } + struct += "};" + System.lineSeparator(); + return struct; + } +} diff --git a/src/types/TrainerClass.java b/src/types/TrainerClass.java new file mode 100644 index 0000000..c016ffa --- /dev/null +++ b/src/types/TrainerClass.java @@ -0,0 +1,7 @@ +package types; + +public class TrainerClass { + public TrainerClass(String name, String money){ + + } +} diff --git a/src/ui/ComboBoxFiltered.java b/src/ui/ComboBoxFiltered.java new file mode 100644 index 0000000..aedc034 --- /dev/null +++ b/src/ui/ComboBoxFiltered.java @@ -0,0 +1,100 @@ +package ui; + +import main.MainActivity; +import main.Utils; + +import javax.swing.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.LinkedList; + +public class ComboBoxFiltered extends JComboBox{ + private LinkedList elements; + private String showAll = ""; + + public ComboBoxFiltered(LinkedList elements, String showAll){ + super(elements.toArray()); + setSelectedIndex(0); + setPrototypeDisplayValue(Utils.getLongestString(elements)); + this.elements = elements; + this.showAll = showAll.toLowerCase(); + setEditable(true); + configFocus(); + listFilter(); + pressEnter(); + } + + private void configFocus(){ + JTextField field = (JTextField) getEditor().getEditorComponent(); + field.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + String text = field.getText(); + Object[] filtered = getFilteredElements(text); + if(showAll.equals("")) filtered = elements.toArray(); + setModel(new DefaultComboBoxModel(filtered)); + field.setText(text); + setPopupVisible(true); + } + + @Override + public void focusLost(FocusEvent e) { + autoComplete(field); + } + }); + } + + private void listFilter(){ + JTextField field = (JTextField) getEditor().getEditorComponent(); + field.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent event) { + String previousText, text; + previousText = text = field.getText(); + if(String.valueOf(event.getKeyChar()).matches("[a-zA-Z]") || String.valueOf(event.getKeyChar()).equals("_")) text += event.getKeyChar(); + Object[] filtered = getFilteredElements(text); + if(showAll.equals("")) filtered = elements.toArray(); + if(filtered.length == 0) SwingUtilities.invokeLater(() -> field.setText(previousText)); + else{ + setModel(new DefaultComboBoxModel(filtered)); + field.setText(previousText); + } + setPopupVisible(true); + } + + @Override + public void keyPressed(KeyEvent e) {} + + @Override + public void keyReleased(KeyEvent e) {} + }); + } + + public void pressEnter(){ + JTextField field = (JTextField) getEditor().getEditorComponent(); + field.addActionListener(event ->{ + autoComplete(field); + }); + } + + public void autoComplete(JTextField field){ + String text = field.getText(); + Object[] filtered = getFilteredElements(text); + if(filtered.length == 0) filtered = elements.toArray(); + setModel(new DefaultComboBoxModel(filtered)); + setSelectedIndex(0); + } + + private Object[] getFilteredElements(String text){ + LinkedList elements = new LinkedList<>(); + text = text.toLowerCase(); + for(String element : this.elements){ + if(element.toLowerCase().contains(text) || text.equals(showAll)){ + elements.add(element); + } + } + return elements.toArray(); + } +} diff --git a/src/ui/ImagePanel.java b/src/ui/ImagePanel.java new file mode 100644 index 0000000..bbd05bc --- /dev/null +++ b/src/ui/ImagePanel.java @@ -0,0 +1,25 @@ +package ui; + +import main.MainActivity; + +import javax.swing.*; +import java.awt.*; +import java.io.File; + +public class ImagePanel extends JPanel { + public String imagePath = ""; + + public ImagePanel(){ + super(); + add(Box.createRigidArea(new Dimension(64, 64))); + } + + @Override + public void paintComponent(Graphics graphics){ + super.paintComponent(graphics); + if(!imagePath.equals("")){ + ImageIcon image = new ImageIcon(MainActivity.projectDirectory.getPath() + File.separator + imagePath); + graphics.drawImage(image.getImage(), getWidth() / 3, 0, this); + } + } +} diff --git a/src/ui/MemberSelector.java b/src/ui/MemberSelector.java new file mode 100644 index 0000000..edd1f0d --- /dev/null +++ b/src/ui/MemberSelector.java @@ -0,0 +1,225 @@ +package ui; + +import main.MainActivity; +import main.Utils; +import types.PartyMember; + +import javax.swing.*; +import java.awt.*; +import java.util.LinkedList; + +public class MemberSelector extends JPanel { + private int maxAssociations; + private boolean fillAssociations; + private JList associationList; + private JPanel associationPanel; + public LinkedList associations = new LinkedList<>(); + + public MemberSelector(int maxAssociations, boolean fillAssociations){ + this.maxAssociations = maxAssociations; + this.fillAssociations = fillAssociations; + setBackground(Color.WHITE); + setLayout(new FlowLayout(FlowLayout.LEFT)); + createListPanel(); + add(Box.createHorizontalStrut(5)); + associationPanel = new JPanel(); + associationPanel.setBackground(Color.WHITE); + add(associationPanel); + } + + public void createListPanel(){ + JPanel listPanel = new JPanel(); + listPanel.setBackground(Color.WHITE); + listPanel.setLayout(new GridBagLayout()); + GridBagConstraints cons = new GridBagConstraints(); + + cons.gridx = 0; + cons.gridy = 0; + cons.fill = GridBagConstraints.BOTH; + createList(listPanel, cons); + createAddButton(listPanel, cons); + createRemoveButton(listPanel, cons); + createMoveButtons(listPanel, cons); + add(listPanel); + } + + public void createList(JPanel pane, GridBagConstraints cons){ + pane.add(Box.createRigidArea(new Dimension(100, 10)), cons); + cons.gridy++; + associationList = new JList(); + associationList.setCellRenderer(new SpeciesRenderer()); + associationList.setPrototypeCellValue(Utils.getLongestString(new LinkedList<>(MainActivity.species.values()))); + associationList.setBorder(BorderFactory.createLineBorder(Color.GRAY)); + associationList.addListSelectionListener(event -> { + if(!event.getValueIsAdjusting() && getSelectedIndex() != -1){ + if(!associationList.getSelectedValue().toString().equals(" ")) { + associationPanel.removeAll(); + associationPanel.add(associations.get(getSelectedIndex())); + MainActivity.screen.repaint(); + } + } + }); + pane.add(associationList, cons); + } + + public void createAddButton(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + cons.gridy++; + JButton add = new JButton("Add"); + add.addActionListener(event ->{ + associationPanel.removeAll(); + MainActivity.screen.loadPartyData(new PartyMember()); + setSelectedIndex(associations.size() - 1); + }); + pane.add(add, cons); + } + + public void createRemoveButton(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + cons.gridy++; + JButton remove = new JButton("Remove"); + remove.addActionListener(event ->{ + if(associations.size() - 1 != 0){ + associationPanel.removeAll(); + int index = getSelectedIndex() != -1 ? getSelectedIndex() : associations.size() - 1; + removeAssociation(index); + int substractFromIndex = index != 0 ? 1 : 0; + setSelectedIndex(index - substractFromIndex); + revalidate(); + } + }); + pane.add(remove, cons); + } + + public void createMoveButtons(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + cons.gridy++; + JPanel move = new JPanel(); + move.setBackground(Color.WHITE); + move.setLayout(new GridBagLayout()); + GridBagConstraints moveCons = new GridBagConstraints(); + moveCons.gridx = 0; + moveCons.gridy = 0; + moveCons.fill = GridBagConstraints.BOTH; + createMoveUpButton(move, moveCons); + createMoveDownButton(move, moveCons); + pane.add(move, cons); + cons.gridy++; + pane.add(Box.createVerticalStrut(10), cons); + } + + public void createMoveUpButton(JPanel pane, GridBagConstraints cons){ + JButton moveUp = new JButton("Move up"); + moveUp.addActionListener(event ->{ + int index = getSelectedIndex(); + if(index > 0 && associations.size() > 1){ + insertAssociation(removeAssociation(index), index - 1); + setSelectedIndex(index - 1); + } + }); + pane.add(moveUp, cons); + cons.gridx++; + pane.add(Box.createHorizontalStrut(5), cons); + } + + public void createMoveDownButton(JPanel pane, GridBagConstraints cons){ + cons.gridx++; + JButton moveDown = new JButton("Move down"); + moveDown.addActionListener(event ->{ + int index = getSelectedIndex(); + if(index >= 0 && index < associations.size() - 1 && associations.size() > 1){ + if(index == associations.size() - 2) addAssociation(removeAssociation(index)); + else insertAssociation(removeAssociation(index), index + 1); + setSelectedIndex(index + 1); + } + }); + pane.add(moveDown, cons); + } + + public void setSelectedIndex(int index){ + associationList.setSelectedIndex(index); + } + + public int getSelectedIndex(){ + return associationList.getSelectedIndex(); + } + + public void addAssociation(PartyMemberInput associated){ + if(associations.size() < maxAssociations){ + DefaultListModel newModel = new DefaultListModel(); + ListModel model = associationList.getModel(); + for(int index = 0; index < model.getSize(); index++){ + if(!model.getElementAt(index).equals(" ")) newModel.addElement(model.getElementAt(index)); + } + newModel.addElement(associated.species.getSelectedItem()); + while(newModel.getSize() < maxAssociations && fillAssociations){ + newModel.addElement(" "); + } + associationList.setModel(newModel); + associations.add(associated); + } + } + + public void insertAssociation(PartyMemberInput associated, int index){ + if(associations.size() < maxAssociations){ + DefaultListModel newModel = new DefaultListModel(); + LinkedList newAssociations = new LinkedList<>(); + ListModel model = associationList.getModel(); + int modelIndex = 0; + for(int insertionIndex = 0; insertionIndex <= associations.size(); insertionIndex++){ + if(!model.getElementAt(index).equals(" ") && insertionIndex != index){ + newModel.addElement(model.getElementAt(modelIndex)); + newAssociations.add(associations.get(modelIndex)); + modelIndex++; + } + else if(insertionIndex == index){ + newModel.addElement(associated.species.getSelectedItem()); + newAssociations.add(associated); + } + } + while(newModel.getSize() < maxAssociations && fillAssociations){ + newModel.addElement(" "); + } + associationList.setModel(newModel); + associations = newAssociations; + } + } + + public PartyMemberInput removeAssociation(int associationIndex){ + if(associationIndex < associations.size()) { + DefaultListModel newModel = new DefaultListModel(); + ListModel model = associationList.getModel(); + for (int index = 0; index < model.getSize(); index++) { + if (!model.getElementAt(index).equals(" ") && associationIndex != index) + newModel.addElement(model.getElementAt(index)); + } + while (newModel.getSize() < maxAssociations && fillAssociations) { + newModel.addElement(" "); + } + associationList.setModel(newModel); + return associations.remove(associationIndex); + } + return null; + } + + public void updateListAssociations(){ + DefaultListModel newModel = new DefaultListModel(); + ListModel model = associationList.getModel(); + for(int index = 0; index < model.getSize(); index++){ + if(!model.getElementAt(index).equals(" ")) newModel.addElement(associations.get(index).species.getSelectedItem()); + } + while(newModel.getSize() < maxAssociations && fillAssociations){ + newModel.addElement(" "); + } + associationList.setModel(newModel); + } + + public void clearAssociations(){ + associationList.setModel(new DefaultListModel()); + associationPanel.removeAll(); + associations = new LinkedList<>(); + } +} \ No newline at end of file diff --git a/src/ui/PartyMemberInput.java b/src/ui/PartyMemberInput.java new file mode 100644 index 0000000..bd113b2 --- /dev/null +++ b/src/ui/PartyMemberInput.java @@ -0,0 +1,162 @@ +package ui; + +import main.MainActivity; +import main.Utils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.ArrayList; +import java.util.LinkedList; + +public class PartyMemberInput extends JPanel{ + public JTextField iv; + public JTextField level; + public ComboBoxFiltered species; + public ComboBoxFiltered heldItem; + public ArrayList moves = new ArrayList<>(); + + public PartyMemberInput(){ + setBackground(Color.WHITE); + setLayout(new FlowLayout(FlowLayout.LEFT)); + + JPanel general = new JPanel(); + general.setBackground(Color.WHITE); + general.setLayout(new GridBagLayout()); + GridBagConstraints cons = new GridBagConstraints(); + + cons.gridx = 0; + cons.gridy = 0; + cons.fill = GridBagConstraints.BOTH; + cons.anchor = GridBagConstraints.LINE_START; + general.add(Box.createVerticalStrut(5), cons); + + createIv(general, cons); + createLevel(general, cons); + createSpecies(general, cons); + createHeldItem(general, cons); + + cons.gridx++; + cons.gridy = 0; + general.add(Box.createRigidArea(new Dimension(20, 5)), cons); + + + JPanel moves = new JPanel(); + moves.setBackground(Color.WHITE); + moves.setLayout(new GridBagLayout()); + cons.gridx = 0; + moves.add(Box.createVerticalStrut(5), cons); + createMoves(moves, cons); + + cons.gridx++; + cons.gridy = 0; + moves.add(Box.createRigidArea(new Dimension(10, 5)), cons); + + add(general); add(moves); + } + + private void createIv(JPanel panel, GridBagConstraints cons){ + cons.gridy++; + JLabel ivLabel = new JLabel("IVs: "); + ivLabel.setHorizontalAlignment(JLabel.LEFT); + panel.add(ivLabel, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + iv = new JTextField(); + iv.setDocument(new TextFieldLimiter(-1, 256)); + panel.add(iv, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(10), cons); + } + + private void createLevel(JPanel panel, GridBagConstraints cons){ + cons.gridy++; + JLabel levelLabel = new JLabel("Level: "); + levelLabel.setHorizontalAlignment(JLabel.LEFT); + panel.add(levelLabel, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + level = new JTextField(); + level.setDocument(new TextFieldLimiter(-1, 255)); + panel.add(level, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(10), cons); + } + + private void createSpecies(JPanel panel, GridBagConstraints cons){ + cons.gridy++; + JLabel speciesLabel = new JLabel("Species: "); + speciesLabel.setHorizontalAlignment(JLabel.LEFT); + panel.add(speciesLabel, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(5), cons); + + LinkedList keys = new LinkedList<>(MainActivity.species.keySet()); + species = new ComboBoxFiltered(keys, keys.get(0)); + species.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) {} + + @Override + public void focusLost(FocusEvent event) { + MainActivity.screen.memberSelector.updateListAssociations(); + } + }); + species.addActionListener(e -> { + MainActivity.screen.memberSelector.updateListAssociations(); + }); + panel.add(species, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(10), cons); + } + + private void createHeldItem(JPanel panel, GridBagConstraints cons){ + cons.gridy++; + JLabel itemLabel = new JLabel("Held item: "); + itemLabel.setHorizontalAlignment(JLabel.LEFT); + panel.add(itemLabel, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(5), cons); + + heldItem = new ComboBoxFiltered(MainActivity.items, MainActivity.items.get(0)); + heldItem.setPrototypeDisplayValue(Utils.getLongestString(MainActivity.items)); + panel.add(heldItem, cons); + + cons.gridy++; + panel.add(Box.createVerticalStrut(10), cons); + } + + private void createMoves(JPanel panel, GridBagConstraints cons){ + cons.gridy++; + JLabel movesLabel = new JLabel("Moves"); + movesLabel.setHorizontalAlignment(JLabel.LEFT); + panel.add(movesLabel, cons); + + for(int index = 0; index < 4; index++){ + cons.gridy++; + panel.add(Box.createVerticalStrut(10), cons); + + cons.gridy++; + LinkedList values = new LinkedList<>(MainActivity.moves.values()); + ComboBoxFiltered move = new ComboBoxFiltered(values, values.get(0)); + move.setPrototypeDisplayValue(Utils.getLongestString(values)); + panel.add(move, cons); + moves.add(move); + } + + cons.gridy++; + panel.add(Box.createVerticalStrut(10), cons); + } +} diff --git a/src/ui/Screen.java b/src/ui/Screen.java new file mode 100644 index 0000000..c701c16 --- /dev/null +++ b/src/ui/Screen.java @@ -0,0 +1,538 @@ +package ui; + +import main.MainActivity; +import main.Utils; +import types.PartyMember; +import types.Trainer; +import utils.DataManager; +import utils.DirectoryChooser; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedList; + +public class Screen extends JFrame { + public MemberSelector memberSelector; + + private JTextField nameInput; + private ComboBoxFiltered classInput; + private JCheckBox doubleBattleCheck; + private LinkedList itemsInput = new LinkedList<>(); + private JRadioButton maleButton; + private JRadioButton femaleButton; + private ComboBoxFiltered musicInput; + private ImagePanel picDisplay; + private ComboBoxFiltered picInput; + private LinkedHashMap aiFlags = new LinkedHashMap<>(); + + public Screen(){ + setTitle("Decomp Trainer Editor"); + setSize(850, 550); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + initUIStyle(); + initStartup(); + setVisible(true); + } + + private void initUIStyle(){ + try{ + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch(ClassNotFoundException + | InstantiationException + | IllegalAccessException + | UnsupportedLookAndFeelException exception){ + exception.printStackTrace(); + } + } + + public void initStartup(){ + //Content pane of the frame + JPanel contentPane = new JPanel(); + contentPane.setLayout(new BorderLayout()); + createMenu(contentPane); + setContentPane(contentPane); + revalidate(); + } + + public void initLoadProject(){ + JPanel contentPane = (JPanel) getContentPane(); + MainActivity.trainerIndexes = DataManager.indexTrainers(); + MainActivity.partyIndexes = DataManager.indexParties(); + MainActivity.trainerClasses = DataManager.loadTrainerClasses(); + MainActivity.items = DataManager.loadItems(); + MainActivity.moves = DataManager.loadMoves(); + MainActivity.species = DataManager.loadSpecies(); + MainActivity.music = DataManager.loadMusic(); + MainActivity.aiFlags = DataManager.loadAiFlags(); + MainActivity.picList = DataManager.loadTrainerPicsList(); + MainActivity.picPaths = DataManager.loadTrainerPicsPaths(); + createMenu(contentPane); + createEditor(contentPane); + loadTrainerData(MainActivity.currentTrainer); + setContentPane(contentPane); + } + + public void createMenu(JPanel panel){ + JMenuBar menu = new JMenuBar(); + JMenu project = new JMenu("Project"); + JMenuItem open = new JMenuItem("Open directory"); + open.addActionListener(event -> new DirectoryChooser()); + JMenuItem save = new JMenuItem("Save"); + save.addActionListener(event -> { + if(MainActivity.currentTrainer != null){ + MainActivity.screen.saveTrainerData(MainActivity.currentTrainer); + for(Trainer trainer : MainActivity.loadedTrainers.values()){ + DataManager.saveTrainer(trainer); + } + } + }); + JMenuItem exit = new JMenuItem("Exit"); + project.add(open); project.add(save); project.add(new JSeparator()); project.add(exit); + menu.add(project); + panel.add(menu, BorderLayout.NORTH); + } + + public void createEditor(JPanel panel){ + JPanel editor = new JPanel(); + editor.setLayout(new BorderLayout()); + createTrainerScrollable(editor); + createEditorTabs(editor); + panel.add(editor, BorderLayout.CENTER); + } + + public void createTrainerScrollable(JPanel panel){ + JPanel general = new JPanel(); + general.setLayout(new BorderLayout()); + JPanel search = new JPanel(); + search.setLayout(new GridBagLayout()); + GridBagConstraints cons = new GridBagConstraints(); + cons.gridx = 0; + cons.gridy = 0; + cons.weighty = 0.1; + cons.fill = GridBagConstraints.BOTH; + JList trainers = new JList(); + createTrainerList(trainers); + JScrollPane trainersScrollable = new JScrollPane(trainers); + search.add(trainersScrollable, cons); + createTrainerSearchBar(search, trainers, cons); + general.add(Box.createVerticalStrut(10), BorderLayout.NORTH); + general.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); + general.add(Box.createHorizontalStrut(10), BorderLayout.WEST); + general.add(Box.createHorizontalStrut(10), BorderLayout.EAST); + general.add(search, BorderLayout.CENTER); + panel.add(general, BorderLayout.WEST); + } + + public void createTrainerList(JList list){ + LinkedList keys = new LinkedList<>(MainActivity.trainerIndexes.keySet()); + list.setPrototypeCellValue(Utils.getLongestString(keys)); + list.setListData(keys.toArray()); + list.setSelectedIndex(0); + MainActivity.currentTrainer = list.getSelectedValue().toString(); + MainActivity.loadedTrainers.put(MainActivity.currentTrainer, DataManager.loadTrainer(MainActivity.currentTrainer)); + list.addListSelectionListener(event -> { + if(!event.getValueIsAdjusting() && list.getSelectedIndex() != -1) { + saveTrainerData(MainActivity.currentTrainer); + MainActivity.currentTrainer = list.getSelectedValue().toString(); + if(!MainActivity.loadedTrainers.containsKey(MainActivity.currentTrainer)) + MainActivity.loadedTrainers.put(MainActivity.currentTrainer, DataManager.loadTrainer(MainActivity.currentTrainer)); + loadTrainerData(MainActivity.currentTrainer); + revalidate(); + } + }); + } + + private void createTrainerSearchBar(JPanel pane, JList list, GridBagConstraints cons){ + cons.gridy++; + cons.weighty = 0; + pane.add(Box.createVerticalStrut(5), cons); + cons.gridy++; + JTextField field = new JTextField(); + field.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent event) { + String previousText, text; + previousText = text = field.getText(); + if(String.valueOf(event.getKeyChar()).matches("[a-zA-Z]") || String.valueOf(event.getKeyChar()).equals("_")) text += event.getKeyChar(); + Object[] filtered = getFilteredTrainers(text); + if(filtered.length == 0) SwingUtilities.invokeLater(() -> field.setText(previousText)); + else{ + list.setModel(new DefaultComboBoxModel(filtered)); + field.setText(previousText); + } + } + + @Override + public void keyPressed(KeyEvent e) {} + + @Override + public void keyReleased(KeyEvent e) {} + }); + pane.add(field, cons); + } + + public void createEditorTabs(JPanel pane){ + JPanel editorBorders = new JPanel(); + editorBorders.setLayout(new BorderLayout()); + JTabbedPane tabbedEditor = new JTabbedPane(); + tabbedEditor.setBackground(Color.WHITE); + createGeneralTab(tabbedEditor); + createAITab(tabbedEditor); + createPartyTab(tabbedEditor); + editorBorders.add(Box.createHorizontalStrut(10), BorderLayout.WEST); + editorBorders.add(Box.createHorizontalStrut(10), BorderLayout.EAST); + editorBorders.add(Box.createVerticalStrut(5), BorderLayout.NORTH); + editorBorders.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); + editorBorders.add(tabbedEditor, BorderLayout.CENTER); + pane.add(editorBorders, BorderLayout.CENTER); + } + + public void createGeneralTab(JTabbedPane pane){ + JPanel general = new JPanel(); + general.setBackground(Color.WHITE); + general.setLayout(new FlowLayout(FlowLayout.LEFT)); + general.add(Box.createHorizontalStrut(5)); + createGeneralLeftColumn(general); + general.add(Box.createHorizontalStrut(30)); + createGeneralRightColumn(general); + pane.add("General", general); + } + + public void createGeneralLeftColumn(JPanel pane){ + JPanel column = new JPanel(); + column.setBackground(Color.WHITE); + column.setLayout(new GridBagLayout()); + GridBagConstraints cons = new GridBagConstraints(); + cons.gridx = 0; + cons.gridy = 0; + cons.fill = GridBagConstraints.BOTH; + cons.anchor = GridBagConstraints.LINE_START; + createNameInput(column, cons); + createTrainerClassInput(column, cons); + createDoubleBattleInput(column, cons); + createItemsInput(column, cons); + pane.add(column); + } + + public void createGeneralRightColumn(JPanel pane){ + JPanel column = new JPanel(); + column.setBackground(Color.WHITE); + column.setLayout(new GridBagLayout()); + GridBagConstraints cons = new GridBagConstraints(); + cons.gridx = 0; + cons.gridy = 0; + cons.fill = GridBagConstraints.BOTH; + cons.anchor = GridBagConstraints.LINE_START; + createTrainerPicInput(column, cons); + createGenderInput(column, cons); + createMusicInput(column, cons); + pane.add(column); + } + + public void createNameInput(JPanel pane, GridBagConstraints cons){ + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JLabel nameLabel = new JLabel("Name: "); + nameLabel.setHorizontalAlignment(JLabel.LEFT); + pane.add(nameLabel, cons); + + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + cons.fill = GridBagConstraints.NONE; + nameInput = new JTextField(11); + nameInput.setDocument(new TextFieldLimiter(11, -1)); + pane.add(nameInput, cons); + } + + public void createTrainerClassInput(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + cons.fill = GridBagConstraints.BOTH; + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JLabel classLabel = new JLabel("Trainer class: "); + classLabel.setHorizontalAlignment(JLabel.LEFT); + pane.add(classLabel, cons); + + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + LinkedList values = new LinkedList<>(MainActivity.trainerClasses.keySet()); + classInput = new ComboBoxFiltered(values, ""); + classInput.setPrototypeDisplayValue(Utils.getLongestString(new ArrayList<>(MainActivity.trainerClasses.keySet()))); + pane.add(classInput, cons); + } + + public void createDoubleBattleInput(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JPanel doubleBattlePanel = new JPanel(); + doubleBattlePanel.setBackground(Color.WHITE); + doubleBattlePanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + doubleBattleCheck = new JCheckBox(); + doubleBattleCheck.setBackground(Color.WHITE); + JLabel doubleBattleLabel = new JLabel("Double battle"); + doubleBattleLabel.setHorizontalAlignment(JLabel.LEFT); + doubleBattlePanel.add(doubleBattleCheck); doubleBattlePanel.add(doubleBattleLabel); + pane.add(doubleBattlePanel, cons); + } + + public void createItemsInput(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JLabel itemsLabel = new JLabel("Items: "); + itemsLabel.setHorizontalAlignment(JLabel.LEFT); + pane.add(itemsLabel, cons); + for(int index = 0; index < 4; index++){ + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + cons.fill = GridBagConstraints.NONE; + ComboBoxFiltered itemInput = new ComboBoxFiltered(MainActivity.items, MainActivity.items.get(0)); + itemInput.setPrototypeDisplayValue(Utils.getLongestString(MainActivity.items)); + pane.add(itemInput, cons); + itemsInput.add(itemInput); + } + cons.gridy++; + pane.add(Box.createVerticalStrut(10), cons); + } + + public void createTrainerPicInput(JPanel pane, GridBagConstraints cons){ + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JLabel picLabel = new JLabel("Trainer pic: "); + picLabel.setHorizontalAlignment(JLabel.LEFT); + pane.add(picLabel, cons); + + cons.gridy++; + pane.add(Box.createVerticalStrut(10), cons); + + cons.gridy++; + picDisplay = new ImagePanel(); + picDisplay.setBackground(Color.WHITE); + pane.add(picDisplay, cons); + + cons.gridy++; + pane.add(Box.createVerticalStrut(10), cons); + + cons.gridy++; + picInput = new ComboBoxFiltered(MainActivity.picList, ""); + picInput.setPrototypeDisplayValue(Utils.getLongestString(MainActivity.picList)); + picInput.addActionListener(e -> { + picDisplay.imagePath = MainActivity.picPaths.get(picInput.getSelectedItem()); + picDisplay.repaint(); + }); + pane.add(picInput, cons); + } + + public void createGenderInput(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JLabel genderLabel = new JLabel("Gender: "); + genderLabel.setHorizontalAlignment(JLabel.LEFT); + pane.add(genderLabel, cons); + + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + maleButton = new JRadioButton("Male"); + maleButton.setBackground(Color.WHITE); + maleButton.addActionListener(event -> { + femaleButton.setSelected(false); + }); + pane.add(maleButton, cons); + + cons.gridy++; + femaleButton = new JRadioButton("Female"); + femaleButton.setBackground(Color.WHITE); + femaleButton.addActionListener(event -> { + maleButton.setSelected(false); + }); + pane.add(femaleButton, cons); + } + + public void createMusicInput(JPanel pane, GridBagConstraints cons){ + cons.gridy++; + pane.add(Box.createVerticalStrut(30), cons); + cons.gridy++; + JLabel musicLabel = new JLabel("Encounter music: "); + musicLabel.setHorizontalAlignment(JLabel.LEFT); + pane.add(musicLabel, cons); + + cons.gridy++; + pane.add(Box.createVerticalStrut(5), cons); + + cons.gridy++; + musicInput = new ComboBoxFiltered(MainActivity.music, ""); + musicInput.setPrototypeDisplayValue(Utils.getLongestString(MainActivity.music)); + pane.add(musicInput, cons); + cons.gridy++; + pane.add(Box.createVerticalStrut(30), cons); + } + + public void createAITab(JTabbedPane pane){ + JPanel general = new JPanel(); + general.setBackground(Color.WHITE); + general.setLayout(new FlowLayout(FlowLayout.LEFT)); + general.add(Box.createHorizontalStrut(5)); + JScrollPane scroll = new JScrollPane(general); + scroll.setBorder(null); + JPanel aiList = new JPanel(); + aiList.setBackground(Color.WHITE); + aiList.setLayout(new GridBagLayout()); + GridBagConstraints cons = new GridBagConstraints(); + cons.gridx = 0; + cons.gridy = 0; + cons.fill = GridBagConstraints.BOTH; + aiList.add(Box.createVerticalStrut(5), cons); + for(int index = 0; index < MainActivity.aiFlags.size(); index++){ + String ai = MainActivity.aiFlags.get(index); + JPanel aiPanel = new JPanel(); + aiPanel.setBackground(Color.WHITE); + aiPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + JCheckBox aiCheck = new JCheckBox(); + aiCheck.setBackground(Color.WHITE); + + JLabel aiLabel = new JLabel(ai); + aiLabel.setHorizontalAlignment(JLabel.LEFT); + aiPanel.add(aiCheck); aiPanel.add(aiLabel); + cons.gridy++; + aiList.add(aiPanel, cons); + aiFlags.put(ai, aiCheck); + } + cons.gridy++; + aiList.add(Box.createVerticalStrut(10), cons); + general.add(aiList, BorderLayout.CENTER); + pane.add("AI", scroll); + } + + public void createPartyTab(JTabbedPane pane){ + JPanel general = new JPanel(); + general.setBackground(Color.WHITE); + general.setLayout(new FlowLayout(FlowLayout.LEFT)); + general.add(Box.createHorizontalStrut(10)); + JPanel spacer = new JPanel(); + spacer.setLayout(new BoxLayout(spacer, BoxLayout.PAGE_AXIS)); + spacer.setAlignmentX(Component.LEFT_ALIGNMENT); + memberSelector = new MemberSelector(6, true); + spacer.add(memberSelector); + general.add(spacer); + pane.add("Party", general); + } + + public Object[] getFilteredTrainers(String text){ + LinkedList elements = new LinkedList<>(); + LinkedList keys = new LinkedList<>(MainActivity.trainerIndexes.keySet()); + text = text.toLowerCase(); + for(String element : keys){ + if(element.toLowerCase().contains(text)){ + elements.add(element); + } + } + return elements.toArray(); + } + + public void loadTrainerData(String name){ + Trainer trainer = MainActivity.loadedTrainers.get(name); + nameInput.setText(trainer.trainerName); + classInput.setSelectedItem(trainer.trainerClass); + doubleBattleCheck.setSelected(trainer.doubleBattle); + picDisplay.imagePath = MainActivity.picPaths.get(trainer.trainerPic); + picInput.setSelectedItem(trainer.trainerPic); + musicInput.setSelectedItem(trainer.music); + boolean male = trainer.gender.equals(""); + maleButton.setSelected(male); + femaleButton.setSelected(!male); + for(int index = 0; index < 4; index++){ + String item = MainActivity.items.get(0); + if(trainer.items.size() > 0){ + item = trainer.items.get(index); + } + itemsInput.get(index).setSelectedItem(item); + } + for(int index = 0; index < MainActivity.aiFlags.size(); index++){ + String flag = MainActivity.aiFlags.get(index); + aiFlags.get(flag).setSelected(trainer.aiFlags.contains(flag)); + } + memberSelector.clearAssociations(); + for(int index = 0; index < trainer.party.size(); index++){ + loadPartyData(trainer.party.get(index)); + } + memberSelector.setSelectedIndex(0); + } + + public void loadPartyData(PartyMember member){ + PartyMemberInput memberInputs = new PartyMemberInput(); + memberInputs.iv.setText(member.iv); + memberInputs.level.setText(member.level); + memberInputs.species.setSelectedItem(member.species); + if(!member.heldItem.equals("")) memberInputs.heldItem.setSelectedItem(member.heldItem); + for(int subindex = 0; subindex < member.moves.size(); subindex++){ + memberInputs.moves.get(subindex).setSelectedItem(MainActivity.moves.get(member.moves.get(subindex))); + } + memberSelector.addAssociation(memberInputs); + } + + public void saveTrainerData(String name){ + Trainer trainer = MainActivity.loadedTrainers.get(name); + trainer.trainerName = nameInput.getText(); + trainer.trainerClass = classInput.getSelectedItem().toString(); + trainer.doubleBattle = doubleBattleCheck.isSelected(); + trainer.trainerPic = picInput.getSelectedItem().toString(); + trainer.music = musicInput.getSelectedItem().toString(); + String gender = ""; + if(femaleButton.isSelected()) gender += "F_TRAINER_FEMALE"; + trainer.gender = gender; + ArrayList aiFlags = new ArrayList<>(); + for(int index = 0; index < MainActivity.aiFlags.size(); index++){ + String flag = MainActivity.aiFlags.get(index); + if(this.aiFlags.get(flag ).isSelected()) aiFlags.add(flag); + } + trainer.aiFlags = aiFlags; + ArrayList items = new ArrayList<>(); + boolean areAllItemsNone = true; + for(ComboBoxFiltered item : itemsInput){ + JTextField field = (JTextField) item.getEditor().getEditorComponent(); + if(!field.getText().equals(MainActivity.items.get(0))) areAllItemsNone = false; + items.add(field.getText()); + } + if(areAllItemsNone) items = new ArrayList<>(); + trainer.items = items; + savePartyData(trainer); + MainActivity.loadedTrainers.put(name, trainer); + } + + public void savePartyData(Trainer trainer){ + LinkedList party = new LinkedList<>(); + for(int index = 0; index < memberSelector.associations.size(); index++){ + PartyMemberInput memberInputs = memberSelector.associations.get(index); + PartyMember member = new PartyMember(); + member.iv = memberInputs.iv.getText(); + member.level = memberInputs.level.getText(); + String species = memberInputs.species.getSelectedItem().toString(); + member.species = species; + member.heldItem = memberInputs.heldItem.getSelectedItem().toString(); + LinkedList keys = new LinkedList<>(MainActivity.moves.keySet()); + LinkedList values = new LinkedList<>(MainActivity.moves.values()); + for(int subindex = 0; subindex < memberInputs.moves.size(); subindex++){ + String move = memberInputs.moves.get(subindex).getSelectedItem().toString(); + int indexOfMove = values.indexOf(move); + member.moves.add(keys.get(indexOfMove)); + } + party.add(member); + } + trainer.party = party; + } +} diff --git a/src/ui/SpeciesRenderer.java b/src/ui/SpeciesRenderer.java new file mode 100644 index 0000000..fec002d --- /dev/null +++ b/src/ui/SpeciesRenderer.java @@ -0,0 +1,29 @@ +package ui; + +import main.MainActivity; + +import javax.swing.*; +import java.awt.*; +import java.util.LinkedList; + +public class SpeciesRenderer extends JLabel implements ListCellRenderer{ + + @Override + public Component getListCellRendererComponent(JList list, String value, int index, boolean isSelected, boolean cellHasFocus) { + setOpaque(true); + String species = MainActivity.species.get(value); + String text = species == null ? value : " " + species; + setText(text); + + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + return this; + } +} diff --git a/src/ui/TextFieldLimiter.java b/src/ui/TextFieldLimiter.java new file mode 100644 index 0000000..66de4c2 --- /dev/null +++ b/src/ui/TextFieldLimiter.java @@ -0,0 +1,37 @@ +package ui; + +import main.Utils; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +public class TextFieldLimiter extends PlainDocument { + private int maxLength; + private int maxValue; + + public TextFieldLimiter(int maxLength, int maxValue) { + super(); + this.maxLength = maxLength; + this.maxValue = maxValue; + } + + @Override + public void insertString(int offset, String str, AttributeSet attr){ + if (str == null) + return; + + try { + StringBuilder sb = new StringBuilder(); + sb.append(getText(0, getLength())); + sb.insert(offset, str); + + if ((sb.toString().length() <= maxLength || maxLength < 0) + && (maxValue < 0 || (Utils.isNumeric(sb.toString()) && Integer.parseInt(sb.toString()) < maxValue))) + super.insertString(offset, str, attr); + } + catch (BadLocationException exception) { + exception.printStackTrace(); + } + } +} diff --git a/src/utils/DataManager.java b/src/utils/DataManager.java new file mode 100644 index 0000000..d6e18ef --- /dev/null +++ b/src/utils/DataManager.java @@ -0,0 +1,509 @@ +package utils; + +import main.MainActivity; +import types.PartyMember; +import types.Trainer; +import types.TrainerClass; + +import java.io.*; +import java.nio.file.Files; +import java.util.*; + +public class DataManager { + public static String readFile(File file){ + String data = ""; + try { + FileReader fr = new FileReader(file); + BufferedReader br = new BufferedReader(fr); + String line; + while((line = br.readLine())!=null) { + data += line + System.lineSeparator(); + } + fr.close(); + } + catch(IOException exception) { + exception.printStackTrace(); + } + return data; + } + + public static LinkedHashMap loadTrainerClasses(){ + File file = new File(MainActivity.projectDirectory + File.separator + "src" + + File.separator + "data" + File.separator + "text" + File.separator + "trainer_class_names.h"); + LinkedHashMap trainerClasses = new LinkedHashMap<>(); + try { + FileReader fr = new FileReader(file); + BufferedReader br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("[TRAINER_")){ + line = line.replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + String declaration = line.substring(1, line.indexOf("]")); + String name = line.substring(line.indexOf("_(\""), line.indexOf("\")")); + trainerClasses.put(declaration, new TrainerClass(name, "0")); + } + } + fr.close(); + } + catch(IOException exception) { + exception.printStackTrace(); + } + + return trainerClasses; + } + + public static LinkedList loadItems(){ + File file = new File(MainActivity.projectDirectory + + File.separator + "include" + File.separator + "constants" + File.separator + "items.h"); + LinkedList items = new LinkedList<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + boolean reachedCount = false; + while((line = br.readLine()) != null && !reachedCount) { + if(line.contains("ITEMS_COUNT")) reachedCount = true; + else if(line.contains("ITEM_")) items.add(line.split(" ")[1]); + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return items; + } + + public static LinkedHashMap loadMoves(){ + File file = new File(MainActivity.projectDirectory + File.separator + "src" + + File.separator + "data" + File.separator + "text" + File.separator + "move_names.h"); + LinkedHashMap moves = new LinkedHashMap<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("[MOVE_") && !line.contains("[MOVE_NAME_LENGTH")) { + line = line.replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + String declaration = line.substring(1, line.indexOf("]")); + String name = line.substring(line.indexOf("_(\"") + 3, line.indexOf("\")")); + moves.put(declaration, name); + } + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return moves; + } + + public static LinkedHashMap loadSpecies(){ + File file = new File(MainActivity.projectDirectory + File.separator + "src" + + File.separator + "data" + File.separator + "text" + File.separator + "species_names.h"); + LinkedHashMap species = new LinkedHashMap<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("[SPECIES_")){ + line = line.replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + String declaration = line.substring(1, line.indexOf("]")); + String name = line.substring(line.indexOf("_(\"") + 3, line.indexOf("\")")); + species.put(declaration, name); + } + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return species; + } + + public static LinkedList loadMusic(){ + File file = new File(MainActivity.projectDirectory + File.separator + "include" + + File.separator + "constants" + File.separator + "trainers.h"); + LinkedList music = new LinkedList<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("TRAINER_ENCOUNTER_MUSIC_")) music.add(line.split(" ")[1]); + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return music; + } + + public static LinkedList loadAiFlags(){ + File file = new File(MainActivity.projectDirectory + File.separator + "include" + + File.separator + "constants" + File.separator + "battle_ai.h"); + LinkedList aiFlags = new LinkedList<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("AI_SCRIPT_")) aiFlags.add(line.split(" ")[1]); + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return aiFlags; + } + + public static LinkedList loadTrainerPicsList(){ + File file = new File(MainActivity.projectDirectory + File.separator + "include" + + File.separator + "constants" + File.separator + "trainers.h"); + LinkedList picList = new LinkedList<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("TRAINER_PIC_")) picList.add(line.split(" ")[1]); + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return picList; + } + + public static LinkedHashMap loadTrainerPicsPaths(){ + File file = new File(MainActivity.projectDirectory + File.separator + "src" + + File.separator + "data" + File.separator + "graphics" + File.separator + "trainers.h"); + LinkedHashMap picAssociations = loadTrainerPicsAssociation(); + LinkedHashMap picPaths = new LinkedHashMap<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + line = line.replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + if(line.contains("constu32gTrainerFrontPic_")){ + String [] frontPic = line.substring("constu32".length()).split("="); + String picDeclaration = frontPic[0].replace("[]", ""); + String picPath = frontPic[1].substring("INCBIN_U32(.".length(), frontPic[1].length() - ".4bpp.lz.);".length()) + ".png"; + picPaths.put(picAssociations.get(picDeclaration), picPath); + } + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return picPaths; + } + + public static LinkedHashMap loadTrainerPicsAssociation(){ + File file = new File(MainActivity.projectDirectory + File.separator + "src" + + File.separator + "data" + File.separator + "trainer_graphics" + File.separator + "front_pic_tables.h"); + LinkedHashMap picAssociations = new LinkedHashMap<>(); + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("TRAINER_SPRITE")){ + line = line.replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + String[] association = line.substring("TRAINER_SPRITE(".length(), line.length() - 2).split(","); + picAssociations.put(association[1], "TRAINER_PIC_" + association[0]); + } + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return picAssociations; + } + + public static LinkedHashMap indexTrainers(){ + File file = new File(MainActivity.projectDirectory + + File.separator + "src" + File.separator + "data" + File.separator + "trainers.h"); + LinkedHashMap trainerIndexes = new LinkedHashMap<>(); + int currentIndex = 0; + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine()) != null) { + if(line.contains("[TRAINER_") && !line.contains("[TRAINER_NONE]")){ + String trainerName = line.substring(line.indexOf("[") + 1, line.indexOf("]")); + trainerIndexes.put(trainerName, currentIndex); + } + currentIndex += line.length() + System.lineSeparator().length(); + } + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return trainerIndexes; + } + + public static Trainer loadTrainer(String name){ + String trainers = DataManager.readFile(new File(MainActivity.projectDirectory + + File.separator + "src" + File.separator + "data" + File.separator + "trainers.h")); + + LinkedList keys = new LinkedList<>(MainActivity.trainerIndexes.keySet()); + int trainerIndex = MainActivity.trainerIndexes.get(name); + int nextTrainerIndex = keys.indexOf(name) + 1 == keys.size() + ? trainers.length() + : MainActivity.trainerIndexes.get(keys.get(keys.indexOf(name) + 1)); + trainers = trainers.substring(trainerIndex, nextTrainerIndex).replace("};", ""); + trainers = trainers.replaceAll(System.lineSeparator(), ""); + trainers = trainers.replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + trainers = trainers.substring(("[" + name + "]={.").length(), trainers.length() - 3); + + HashMap values = Trainer.templateValues(); + String[] trainer = trainers.split(",\\."); + + for(String field : trainer){ + String key = field.substring(0, field.indexOf("=")); + String value = field.substring(field.indexOf("=") + 1); + values.put(key, value); + } + return new Trainer(name, values); + } + + public static void saveTrainer(Trainer trainer){ + File file = new File(MainActivity.projectDirectory + + File.separator + "src" + File.separator + "data" + File.separator + "trainers.h"); + String trainers = DataManager.readFile(file); + + LinkedList keys = new LinkedList<>(MainActivity.trainerIndexes.keySet()); + int trainerIndex = MainActivity.trainerIndexes.get(trainer.key); + int nextTrainerIndex = keys.indexOf(trainer.key) + 1 == keys.size() + ? trainers.length() + : MainActivity.trainerIndexes.get(keys.get(keys.indexOf(trainer.key) + 1)); + boolean isLast = nextTrainerIndex == trainers.length(); + String trainerStruct = trainer.buildTrainerStruct(); + if(isLast) trainerStruct += "};"; + String[] lines = (trainers.substring(0, trainerIndex) + trainerStruct + trainers.substring(nextTrainerIndex)) + .split(System.lineSeparator(), -1); + try { + Files.write(file.toPath(), Arrays.asList(lines)); + } + catch (IOException exception) { + exception.printStackTrace(); + } + MainActivity.trainerIndexes = DataManager.indexTrainers(); + saveParty(trainer); + } + + public static LinkedHashMap indexParties(){ + File file = new File(MainActivity.projectDirectory + + File.separator + "src" + File.separator + "data" + File.separator + "trainer_parties.h"); + LinkedHashMap partyIndexes = new LinkedHashMap<>(); + int currentIndex = 0; + FileReader fr = null; + BufferedReader br = null; + try { + fr = new FileReader(file); + br = new BufferedReader(fr); + String line; + while((line = br.readLine())!=null) { + if(line.contains("static")){ + String partyName = line.substring(line.indexOf("sParty"), line.indexOf("[")).replace(" ", ""); + partyIndexes.put(partyName, currentIndex); + } + currentIndex += line.length() + System.lineSeparator().length(); + } + fr.close(); + } + catch(IOException exception) { + exception.printStackTrace(); + } + finally { + try { + fr.close(); + br.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + return partyIndexes; + } + + public static LinkedList loadParty(String name){ + String parties = DataManager.readFile(new File(MainActivity.projectDirectory + + File.separator + "src" + File.separator + "data" + File.separator + "trainer_parties.h")); + + LinkedList keys = new LinkedList<>(MainActivity.partyIndexes.keySet()); + int partyIndex = MainActivity.partyIndexes.get(name); + int nextPartyIndex = keys.indexOf(name) + 1 == keys.size() + ? parties.length() + : MainActivity.partyIndexes.get(keys.get(keys.indexOf(name) + 1)); + parties = parties.substring(partyIndex, nextPartyIndex); + String partyType = parties.substring(parties.indexOf("TrainerMon"), parties.indexOf("Moves") + "Moves".length()); + String partyDeclaration = "staticconststruct" + partyType + name + "[]={{"; + parties = parties.replaceAll(System.lineSeparator(), "").replaceAll("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", ""); + parties = parties.substring(partyDeclaration.length(), parties.length() - 3); + + String[] party = parties.split("},\\{"); + LinkedList members = new LinkedList<>(); + for(String member : party){ + HashMap values = PartyMember.templateValues(); + int commaIndex = member.endsWith(",") ? 1 : 0; + member = member.substring(1, member.length() - commaIndex); //Remove first "." and last "," + String[] memberData = member.split(",\\."); + for(String field : memberData){ + String key = field.substring(0, field.indexOf("=")); + String value = field.substring(field.indexOf("=") + 1); + values.put(key, value); + } + members.add(new PartyMember(values)); + } + return members; + } + + public static void saveParty(Trainer trainer){ + File file = new File(MainActivity.projectDirectory + + File.separator + "src" + File.separator + "data" + File.separator + "trainer_parties.h"); + String parties = DataManager.readFile(file); + + LinkedList keys = new LinkedList<>(MainActivity.partyIndexes.keySet()); + int partyIndex = MainActivity.partyIndexes.get(trainer.partyName); + int nextPartyIndex = keys.indexOf(trainer.partyName) + 1 == keys.size() + ? parties.length() + : MainActivity.partyIndexes.get(keys.get(keys.indexOf(trainer.partyName) + 1)); + String partyStruct = trainer.buildPartyStruct(); + String[] lines = (parties.substring(0, partyIndex) + partyStruct + parties.substring(nextPartyIndex)) + .split(System.lineSeparator(), -1); + try { + Files.write(file.toPath(), Arrays.asList(lines)); + } + catch (IOException exception) { + exception.printStackTrace(); + } + MainActivity.partyIndexes = DataManager.indexParties(); + } + + /*public static void write(File file, String data){ + FileWriter fr = null; + BufferedWriter br = null; + try{ + fr = new FileWriter(file); + br = new BufferedWriter(fr); + br.write(data); + } catch (IOException exception) { + exception.printStackTrace(); + } + finally{ + try { + br.close(); + fr.close(); + } + catch (IOException exception) { + exception.printStackTrace(); + } + } + + + + try(FileWriter writer = new FileWriter(file)) { + writer.write(""); + } catch (IOException e) {e.printStackTrace();} + }*/ +} diff --git a/src/utils/DirectoryChooser.java b/src/utils/DirectoryChooser.java new file mode 100644 index 0000000..055f6f3 --- /dev/null +++ b/src/utils/DirectoryChooser.java @@ -0,0 +1,21 @@ +package utils; + +import main.MainActivity; +import ui.Screen; + +import javax.swing.*; +import java.io.File; + +public class DirectoryChooser { + public DirectoryChooser(){ + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(".")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if(chooser.showOpenDialog(MainActivity.screen) == JFileChooser.APPROVE_OPTION){ + MainActivity.projectDirectory = chooser.getSelectedFile(); + MainActivity.screen.getContentPane().removeAll(); + MainActivity.screen.initLoadProject(); + } + } +}