diff --git a/Controller/ArrayField.java b/Controller/ArrayField.java index b96d58f..eb3f10b 100644 --- a/Controller/ArrayField.java +++ b/Controller/ArrayField.java @@ -7,6 +7,8 @@ */ public enum ArrayField { // ITEM + weaponID1, weaponID2, weaponInventorySlot, weaponGem1Value, weaponGem2Value, weaponGem3Value, weaponGem1Index, weaponGem2Index, weaponGem3Index, weaponNumGemSlots, // weapons + // gemID1 -> gemID for name, gemID2 -> gemID for description gemID1, gemUnk1, gemInventorySlot, gemUnk2, gemValue, gemRank, gemUnk3, gemID2, // gems diff --git a/Controller/SaveField.java b/Controller/SaveField.java index 9c91793..42d1dcf 100644 --- a/Controller/SaveField.java +++ b/Controller/SaveField.java @@ -39,6 +39,7 @@ public enum SaveField { // ITEM money, + weaponArray, gemArray, // WTHR diff --git a/Controller/SaveFileController.java b/Controller/SaveFileController.java index a2e2237..2f3e3b5 100644 --- a/Controller/SaveFileController.java +++ b/Controller/SaveFileController.java @@ -55,7 +55,6 @@ public void viewEventOccurred(ViewEvent e) { loadArrayValue(e.getSaveField(), e.getIndex(), e.getArrayField()); this.gettingArrayData = false; break; - // TODO: may be able to combine SET_DATA and SET_ARRAY_DATA case SET_DATA: // sends value of field in gui to save in model SaveField saveField = e.getSaveField(); Data data = (Data) SaveFile.DataMap.get(saveField); @@ -97,13 +96,14 @@ public void viewEventOccurred(ViewEvent e) { try { saveFile.setData(data, convertedValue); + if (arrName == SaveField.weaponArray) handleWeaponTable(colName, index, value); } catch (IllegalArgumentException e1) { e1.printStackTrace(); } catch (NullPointerException e2) { System.out.print("Reloading saved value: "); } - + // Determine whether to set/clear StaticElements boolean isIndexNull = saveFile.isArrayIndexNull(arr, index); if (isIndexNull) { // clear StaticElements @@ -119,6 +119,71 @@ public void viewEventOccurred(ViewEvent e) { viewEventOccurred(new ViewEvent(this, ViewEvent.EventType.GET_ARRAY_DATA, null, arrName, colName, index, null)); break; + case SET_COPY_ARRAY_DATA: + // copy origin -> dest, and reload dest to show in View + SaveField originArrName = e.getSaveField(), destArrName = e.getDestSaveField(); + Array originArr = (Array) SaveFile.DataMap.get(originArrName), destArr = (Array) SaveFile.DataMap.get(destArrName);; + ArrayField originCol = e.getArrayField(), destCol = e.getDestArrayField(); + int originIndex = e.getIndex(), destIndex = e.getDestIndex(); + + // Get Data obj for both arrays + Data originData = originArr.get(originIndex, originCol); + Data destData = destArr.get(destIndex, destCol); + + saveFile.copyBytes(originData, destData); + + // reload destination element to show in View + viewEventOccurred(new ViewEvent(this, ViewEvent.EventType.GET_ARRAY_DATA, null, destArrName, destCol, destIndex, null)); + + break; + } + } + + // Handles the quirky behavior of the weapon table, from the side affect of hiding weaponGemxValue from View + private void handleWeaponTable(ArrayField colName, int index, String value) throws NumberFormatException { + switch (colName) { + // When weaponGemIndex updates -> update weaponGemValue to gem at new index + case weaponGem1Index: + if (Integer.parseInt(value) < gui.ITEMPanel.getGemTableNumRows()) viewEventOccurred(new ViewEvent(this, SaveField.gemArray, ArrayField.gemUnk2, Integer.parseInt(value), SaveField.weaponArray, ArrayField.weaponGem1Value, index)); + else viewEventOccurred(new ViewEvent(this, ViewEvent.EventType.SET_ARRAY_DATA, null, SaveField.weaponArray, ArrayField.weaponGem1Value, index, "0")); // If the index into the gemArray is out-of-bounds + break; + case weaponGem2Index: + if (Integer.parseInt(value) < gui.ITEMPanel.getGemTableNumRows()) viewEventOccurred(new ViewEvent(this, SaveField.gemArray, ArrayField.gemUnk2, Integer.parseInt(value), SaveField.weaponArray, ArrayField.weaponGem2Value, index)); + else viewEventOccurred(new ViewEvent(this, ViewEvent.EventType.SET_ARRAY_DATA, null, SaveField.weaponArray, ArrayField.weaponGem2Value, index, "0")); // If the index into the gemArray is out-of-bounds + break; + case weaponGem3Index: + if (Integer.parseInt(value) < gui.ITEMPanel.getGemTableNumRows()) viewEventOccurred(new ViewEvent(this, SaveField.gemArray, ArrayField.gemUnk2, Integer.parseInt(value), SaveField.weaponArray, ArrayField.weaponGem3Value, index)); + else viewEventOccurred(new ViewEvent(this, ViewEvent.EventType.SET_ARRAY_DATA, null, SaveField.weaponArray, ArrayField.weaponGem3Value, index, "0")); // If the index into the gemArray is out-of-bounds + break; + + // When gemUnk2/gemValue/gemRank/gemUnk3/gemID2 updates -> if any weapons have the same index, update weaponGemValue + case gemUnk2: + case gemValue: + case gemRank: + case gemUnk3: + case gemID2: + for (int i = 0; i < gui.ITEMPanel.getWeaponTableNumRows(); i++) { + if (saveFile.isArrayIndexNull(SaveField.weaponArray, i)) continue; // ignore null weapon rows + + int gemIndexFromWeapon = (int) saveFile.getArrayAt(SaveField.weaponArray, i, ArrayField.weaponGem1Index); + if (gemIndexFromWeapon == index) viewEventOccurred(new ViewEvent(this, SaveField.gemArray, ArrayField.gemUnk2, index, SaveField.weaponArray, ArrayField.weaponGem1Value, i)); + + gemIndexFromWeapon = (int) saveFile.getArrayAt(SaveField.weaponArray, i, ArrayField.weaponGem2Index); + if (gemIndexFromWeapon == index) viewEventOccurred(new ViewEvent(this, SaveField.gemArray, ArrayField.gemUnk2, index, SaveField.weaponArray, ArrayField.weaponGem2Value, i)); + + gemIndexFromWeapon = (int) saveFile.getArrayAt(SaveField.weaponArray, i, ArrayField.weaponGem3Index); + if (gemIndexFromWeapon == index) viewEventOccurred(new ViewEvent(this, SaveField.gemArray, ArrayField.gemUnk2, index, SaveField.weaponArray, ArrayField.weaponGem3Value, i)); + } + break; + + default: + } + + // Make index of weaponArray fully 'null' if all visible fields are 0 + if (saveFile.isArrayIndexNullPartial(SaveField.weaponArray, index, new ArrayField[] {ArrayField.weaponGem1Value, ArrayField.weaponGem2Value, ArrayField.weaponGem3Value})) { + saveFile.setArrayData(SaveField.weaponArray, index, ArrayField.weaponGem1Value, 0); + saveFile.setArrayData(SaveField.weaponArray, index, ArrayField.weaponGem2Value, 0); + saveFile.setArrayData(SaveField.weaponArray, index, ArrayField.weaponGem3Value, 0); } } diff --git a/Model/Array.java b/Model/Array.java index dbe2e3e..18cbc88 100644 --- a/Model/Array.java +++ b/Model/Array.java @@ -94,9 +94,10 @@ private int getColNameIndex(ArrayField name) { * Gets a Data object for the nth index and the specified column index * @param n the index in the Array * @param colIndex the column index in the Array - * @return a Data object at the specified location + * @return a Data object at the specified location; null if n is out of bounds */ public Data get(int n, int colIndex) { + if (n >= this.numEntries) return null; int start = this.start + (entrySize*n); // calculate number of bits from start of index to colIndex diff --git a/Model/SaveFile.java b/Model/SaveFile.java index 323535c..d5a641d 100644 --- a/Model/SaveFile.java +++ b/Model/SaveFile.java @@ -4,6 +4,8 @@ import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.util.HashMap; +import java.util.Set; + import com.google.common.collect.HashBiMap; import Controller.ArrayField; @@ -118,6 +120,27 @@ public class SaveFile { // ITEM put(SaveField.money, new Data(0x24048, 0x2404C, DataType.Int)); + put(SaveField.weaponArray, new Array(0x1C4EC, 0x1E364, new Element[] { + new Element(ArrayField.weaponID1, 12, DataType.Int), + new StaticElement(4, 2), + new Element(ArrayField.weaponID2, 11, DataType.Int), + new StaticElement(5, 0), + new StaticElement(8, 0), + new Element(ArrayField.weaponInventorySlot, 8, DataType.Int), + new StaticElement(8, 1), + new StaticElement(8, 0), + new Element(ArrayField.weaponGem1Value, 64, DataType.Int), + new Element(ArrayField.weaponGem2Value, 64, DataType.Int), + new Element(ArrayField.weaponGem3Value, 64, DataType.Int), + new StaticElement(64, 0), + new Element(ArrayField.weaponGem1Index, 16, DataType.Int), + new Element(ArrayField.weaponGem2Index, 16, DataType.Int), + new Element(ArrayField.weaponGem3Index, 16, DataType.Int), + new StaticElement(16, 0xFFFF), + new Element(ArrayField.weaponNumGemSlots, 8, DataType.Int), + new StaticElement(8, 6), + new StaticElement(16, 0), + })); put(SaveField.gemArray, new Array(0x206D8, 0x21998, new Element[] { new StaticElement(16, 0xEA33), // Item ID from ITM_itemlist that doesn't affect gem attributes (just needs to be a gem type item) new Element(ArrayField.gemID1, 11, DataType.Int), @@ -337,6 +360,30 @@ public boolean isArrayIndexNull(Array arr, int index) { } return true; } + public boolean isArrayIndexNull(SaveField arr, int index) { + return isArrayIndexNull((Array) SaveFile.DataMap.get(arr), index); + } + + /** + * Checks if the given index of an Array is all 0's, ignoring specified columns + * Used to determine whether to clear ArrayField's not exposed to the View + * @param arr Array object to check + * @param index the index to check + * @param exclude array of columns (ArrayFields) to ignore/exclude + * @return true if all Elements, excluding the specificed columns, of arr are 0, otherwise false + */ + public boolean isArrayIndexNullPartial(Array arr, int index, ArrayField[] exclude) { + Set excludeSet = Set.of(exclude); + + for (ArrayField internalColName : arr.getColNames()) { + if (excludeSet.contains(internalColName)) continue; + if (!this.getData(arr.get(index, internalColName)).equals(0)) return false; + } + return true; + } + public boolean isArrayIndexNullPartial(SaveField arr, int index, ArrayField[] exclude) { + return isArrayIndexNullPartial((Array) SaveFile.DataMap.get(arr), index, exclude); + } /** * Sets a Data object to the specified value, throwing an exception if the specified value is not the correct type @@ -486,6 +533,17 @@ private void setBytesAt(int x, byte[] b, byte startMask, byte endMask) { if (b.length > 1) this.setByteAt(x+b.length-1, b[b.length-1], endMask); // set last byte, if there is more than 1 byte } + /** + * Copies bytes from origin to destination Data objects + * The number of bytes copied is determined by destination size + * @param origin Data object to copy from, may use bytes after this object if the destination Data obj is larger in size + * @param dest Data object to copy to, ensured that all bytes in this object are modified + */ + public void copyBytes(Data origin, Data dest) { + byte[] bytesToCopy = getBytesAt(origin.start, origin.start + dest.size()); + setBytesAt(dest.start, bytesToCopy); + } + /** * Reads from the actual file, and saves into saveFile * Fixes any checksum errors encountered upon load diff --git a/View/.gitignore b/View/.gitignore index 5a07826..5811d0d 100644 --- a/View/.gitignore +++ b/View/.gitignore @@ -39,3 +39,4 @@ /GUI$12.class /ViewEvent$Types.class /ViewEvent$EventType.class +/ITEMView$1.class diff --git a/View/GUI.java b/View/GUI.java index 0a57aa9..33cde27 100644 --- a/View/GUI.java +++ b/View/GUI.java @@ -64,7 +64,7 @@ public class GUI extends JFrame { private TIMEView TIMEPanel; private PCPMView PCPMPanel; private CAMDView CAMDPanel; - private ITEMView ITEMPanel; + public ITEMView ITEMPanel; private WTHRView WTHRPanel; //private SNDSView SNDSPanel; private MINEView MINEPanel; @@ -388,7 +388,7 @@ public void actionPerformed(ActionEvent e) { }); } - else { + else { // adds default JComboBox action listener cb.addActionListener(new ActionListener() { @@ -460,6 +460,8 @@ public void setArray(SaveField arrName, ArrayField[] columnMaps, JTable jc) { // map column names for (int i = 0; i < columnMaps.length; i++) { + if (columnMaps[i] == null) continue; // If column is not mapped to an ArrayField, continue + HashBiMap map; if (columnMap.containsKey(arrName)) { // add to existing HashBiMap map = columnMap.get(arrName); @@ -472,17 +474,17 @@ public void setArray(SaveField arrName, ArrayField[] columnMaps, JTable jc) { } jc.getModel().addTableModelListener(new TableModelListener() { - @Override public void tableChanged(TableModelEvent e) { int row = e.getFirstRow(); - int col = e.getColumn(); + int col = e.getColumn(); + + if (columnMaps[col] == null) return; // ignore columns not mapped to ArrayField // column number determines the dataName, row number determines the index - if (jc.getModel().getValueAt(row, col) == null) return; + if (jc.getModel().getValueAt(row, col) == null) return; // TODO: why is this here? fireViewEvent(ViewEvent.EventType.SET_ARRAY_DATA, arrName, columnMaps[col], row, jc.getModel().getValueAt(row, col).toString()); } - }); } diff --git a/View/ITEMView.java b/View/ITEMView.java index 545b276..4180a36 100644 --- a/View/ITEMView.java +++ b/View/ITEMView.java @@ -20,7 +20,109 @@ public class ITEMView extends JPanel { GUI gui; private JTextField ITEMMoney; - private JTable gemTable; + private JTable gemTable, weaponTable; + + private final String[] gemNames = { + "None", + "Strength Up", + "Chill Defence", + "Sleep Resist", + "Slow Resist", + "Bind Resist", + "Buff Time Plus", + "Weapon Power", + "Strength Down", + "Blaze Plus", + "Blaze Attack", + "Spike", + "Revival HP Up", + "Initial Tension", + "Aggro Up", + "EXP Up", + "Weaken", // Unused + "HP Up", + "Poison Defence", + "Spike Defence", + "Paralysis Resist", + "Debuff Resist", + "Recovery Up", + "Aura Heal", + "Damage Heal", + "Arts Heal", + "HP Steal", + "Unbeatable", + "AP Up", + "Aquatic Cloak", + "Auto-Heal Up", + "Terrain Defence", + "HP Weaken", // Unused + "Ether Up", + "Double Attack", + "Daze Resist", + "Pierce Resist", + "Daze Plus", + "Phys Def Down", + "Paralysis", + "Lightning Attack", + "Electric Plus", + "Back Atk Plus", + "First Attack Plus", + "Daze Up", + "Cast Quicken", // Unused + "Tension Swing", + "Daze Tension", + "Ether Weaken", // Unused + "Ether Def Up", + "Blaze Defence", + "Lock-On Resist", + "Confuse Resist", + "Critical Resist", // Unused + "Ether Protect", + "Slow", + "Bind", + "Ether Def Down", + "Chill Plus", + "Chill Attack", + "Auto-Atk Stealth", + "Arts Stealth", + "Talent Boost", + "Heat Sink", + "Ether Smash", // Unused + "Agility Up", + "Topple Resist", + "Good Footing", + "Arts Seal Resist", + "Accuracy Up", // Unused + "Haste", + "Topple Plus", + "Bleed Attack", + "Bleed Plus", + "Topple Up", + "Agility Down", + "Break", + "Quick Step", + "Fall Defence", + "Aerial Cloak", + "Agility Weaken", // Unused + "Muscle Up", + "Attack Stability", + "Attack Plus", + "Critical Up", + "Bleed Defence", + "Divine Protect", + "Physical Protect", + "Night Vision", + "Debuff Plus", + "Armour Power", // Unused + "Ether Down", + "Poison Plus", + "Poison Attack", + "Aggro Down", + "Earth Cloak", + "Muscle Waste", // Unused + "Unbeatable", + "Impurity" // Unused + }; public ITEMView(GUI gui) { this.gui = gui; @@ -37,169 +139,140 @@ public ITEMView(GUI gui) { ITEMMoney.setColumns(10); gui.setTextField(SaveField.money, ITEMMoney, gui.int32); - String[] gemColumnNames = new String[] {"Gem ID (Name)", "Gem ID (Description)", "Rank", "Value", "Inventory Slot", "Unknown 1", "Unknown 2", "Unknown 3"}; + // weapon array + String[] weaponColumnNames = {"Weapon ID", "Weapon ID (Name)", "Number of Gem Slots", "Gem 1 Index", "Gem 2 Index", "Gem 3 Index", "Inventory Slot"}; + weaponTable = new JTable(); + weaponTable.setModel(new DefaultTableModel(weaponColumnNames, 150)); + + // set weaponID1 to uint12 + TableColumn weaponID1Column = weaponTable.getColumnModel().getColumn(0); + JTextField weaponID1TextField = new JTextField(); + AbstractDocument doc = (AbstractDocument) weaponID1TextField.getDocument(); + doc.setDocumentFilter(gui.uint12); + weaponID1Column.setCellEditor(new DefaultCellEditor(weaponID1TextField)); + + // set weaponID2 to uint11 + TableColumn weaponID2Column = weaponTable.getColumnModel().getColumn(1); + JTextField weaponID2TextField = new JTextField(); + doc = (AbstractDocument) weaponID2TextField.getDocument(); + doc.setDocumentFilter(gui.uint11); + weaponID2Column.setCellEditor(new DefaultCellEditor(weaponID2TextField)); + + // set weaponNumGemSlots to uint8 + TableColumn weaponNumGemSlotsColumn = weaponTable.getColumnModel().getColumn(2); + JTextField weaponNumGemSlotsTextField = new JTextField(); + doc = (AbstractDocument) weaponNumGemSlotsTextField.getDocument(); + doc.setDocumentFilter(gui.uint8); + weaponNumGemSlotsColumn.setCellEditor(new DefaultCellEditor(weaponNumGemSlotsTextField)); + + // set weaponGem1Index to uint16 + TableColumn weaponGem1IndexColumn = weaponTable.getColumnModel().getColumn(3); + JTextField weaponGem1IndexTextField = new JTextField(); + doc = (AbstractDocument) weaponGem1IndexTextField.getDocument(); + doc.setDocumentFilter(gui.uint16); + weaponGem1IndexColumn.setCellEditor(new DefaultCellEditor(weaponGem1IndexTextField)); + + // set weaponGem2Index to uint16 + TableColumn weaponGem2IndexColumn = weaponTable.getColumnModel().getColumn(4); + JTextField weaponGem2IndexTextField = new JTextField(); + doc = (AbstractDocument) weaponGem2IndexTextField.getDocument(); + doc.setDocumentFilter(gui.uint16); + weaponGem2IndexColumn.setCellEditor(new DefaultCellEditor(weaponGem2IndexTextField)); + + // set weaponGem3Index to uint16 + TableColumn weaponGem3IndexColumn = weaponTable.getColumnModel().getColumn(5); + JTextField weaponGem3IndexTextField = new JTextField(); + doc = (AbstractDocument) weaponGem3IndexTextField.getDocument(); + doc.setDocumentFilter(gui.uint16); + weaponGem3IndexColumn.setCellEditor(new DefaultCellEditor(weaponGem3IndexTextField)); + + // set weaponInventorySlot to uint8 + TableColumn weaponInventorySlotColumn = weaponTable.getColumnModel().getColumn(6); + JTextField weaponInventorySlotTextField = new JTextField(); + doc = (AbstractDocument) weaponInventorySlotTextField.getDocument(); + doc.setDocumentFilter(gui.uint8); + weaponInventorySlotColumn.setCellEditor(new DefaultCellEditor(weaponInventorySlotTextField)); + + gui.setArray(SaveField.weaponArray, new ArrayField[] {ArrayField.weaponID1, ArrayField.weaponID2, ArrayField.weaponNumGemSlots, ArrayField.weaponGem1Index, ArrayField.weaponGem2Index, ArrayField.weaponGem3Index, ArrayField.weaponInventorySlot}, weaponTable); + + JScrollPane weaponScrollPane = new JScrollPane(weaponTable); + this.add(weaponScrollPane, "cell 0 1,growx,aligny top,spanx 2"); + + + String[] gemColumnNames = new String[] {"Index", "Gem ID (Name)", "Gem ID (Description)", "Rank", "Value", "Inventory Slot", "Unknown 1", "Unknown 2", "Unknown 3"}; gemTable = new JTable(); - gemTable.setModel(new DefaultTableModel(gemColumnNames, 300)); - - final String[] gemNames = { - "None", - "Strength Up", - "Chill Defence", - "Sleep Resist", - "Slow Resist", - "Bind Resist", - "Buff Time Plus", - "Weapon Power", - "Strength Down", - "Blaze Plus", - "Blaze Attack", - "Spike", - "Revival HP Up", - "Initial Tension", - "Aggro Up", - "EXP Up", - "Weaken", // Unused - "HP Up", - "Poison Defence", - "Spike Defence", - "Paralysis Resist", - "Debuff Resist", - "Recovery Up", - "Aura Heal", - "Damage Heal", - "Arts Heal", - "HP Steal", - "Unbeatable", - "AP Up", - "Aquatic Cloak", - "Auto-Heal Up", - "Terrain Defence", - "HP Weaken", // Unused - "Ether Up", - "Double Attack", - "Daze Resist", - "Pierce Resist", - "Daze Plus", - "Phys Def Down", - "Paralysis", - "Lightning Attack", - "Electric Plus", - "Back Atk Plus", - "First Attack Plus", - "Daze Up", - "Cast Quicken", // Unused - "Tension Swing", - "Daze Tension", - "Ether Weaken", // Unused - "Ether Def Up", - "Blaze Defence", - "Lock-On Resist", - "Confuse Resist", - "Critical Resist", // Unused - "Ether Protect", - "Slow", - "Bind", - "Ether Def Down", - "Chill Plus", - "Chill Attack", - "Auto-Atk Stealth", - "Arts Stealth", - "Talent Boost", - "Heat Sink", - "Ether Smash", // Unused - "Agility Up", - "Topple Resist", - "Good Footing", - "Arts Seal Resist", - "Accuracy Up", // Unused - "Haste", - "Topple Plus", - "Bleed Attack", - "Bleed Plus", - "Topple Up", - "Agility Down", - "Break", - "Quick Step", - "Fall Defence", - "Aerial Cloak", - "Agility Weaken", // Unused - "Muscle Up", - "Attack Stability", - "Attack Plus", - "Critical Up", - "Bleed Defence", - "Divine Protect", - "Physical Protect", - "Night Vision", - "Debuff Plus", - "Armour Power", // Unused - "Ether Down", - "Poison Plus", - "Poison Attack", - "Aggro Down", - "Earth Cloak", - "Muscle Waste", // Unused - "Unbeatable", - "Impurity" // Unused - }; + gemTable.setModel(new DefaultTableModel(gemColumnNames, 300) { + @Override + public boolean isCellEditable(int row, int column) { + return column == 0 ? false : true; // Makes the first column (index) unmodifiable + } + }); + + // set Index column values + DefaultTableModel gemTableModel = (DefaultTableModel) gemTable.getModel(); + for (int i = 0; i < gemTableModel.getRowCount(); i++) { + gemTableModel.setValueAt(i, i, 0); + } // set gemID1 to JComboBox - TableColumn gemID1Column = gemTable.getColumnModel().getColumn(0); + TableColumn gemID1Column = gemTable.getColumnModel().getColumn(1); JComboBox gemID1ComboBox = new JComboBox(gemNames); gemID1Column.setCellEditor(new DefaultCellEditor(gemID1ComboBox)); // set gemID2 to JComboBox - TableColumn gemID2Column = gemTable.getColumnModel().getColumn(1); + TableColumn gemID2Column = gemTable.getColumnModel().getColumn(2); gemID2Column.setMinWidth(100); JComboBox gemID2ComboBox = new JComboBox(gemNames); gemID2Column.setCellEditor(new DefaultCellEditor(gemID2ComboBox)); // set rank to uint3 - TableColumn gemRankColumn = gemTable.getColumnModel().getColumn(2); + TableColumn gemRankColumn = gemTable.getColumnModel().getColumn(3); JTextField gemRankTextField = new JTextField(); - AbstractDocument doc = (AbstractDocument) gemRankTextField.getDocument(); + doc = (AbstractDocument) gemRankTextField.getDocument(); doc.setDocumentFilter(gui.uint3); gemRankColumn.setCellEditor(new DefaultCellEditor(gemRankTextField)); // set value to uint11 - TableColumn gemValueColumn = gemTable.getColumnModel().getColumn(3); + TableColumn gemValueColumn = gemTable.getColumnModel().getColumn(4); JTextField gemValueTextField = new JTextField(); doc = (AbstractDocument) gemValueTextField.getDocument(); doc.setDocumentFilter(gui.uint11); gemValueColumn.setCellEditor(new DefaultCellEditor(gemValueTextField)); // set gemInventorySlot to uint8 - TableColumn gemInventorySlotColumn = gemTable.getColumnModel().getColumn(4); + TableColumn gemInventorySlotColumn = gemTable.getColumnModel().getColumn(5); JTextField gemInventorySlotTextField = new JTextField(); doc = (AbstractDocument) gemInventorySlotTextField.getDocument(); doc.setDocumentFilter(gui.uint8); gemInventorySlotColumn.setCellEditor(new DefaultCellEditor(gemInventorySlotTextField)); // set gemUnk1 to uint5 - TableColumn gemUnk1Column = gemTable.getColumnModel().getColumn(5); + TableColumn gemUnk1Column = gemTable.getColumnModel().getColumn(6); JTextField gemUnk1TextField = new JTextField(); doc = (AbstractDocument) gemUnk1TextField.getDocument(); doc.setDocumentFilter(gui.uint5); gemUnk1Column.setCellEditor(new DefaultCellEditor(gemUnk1TextField)); // set gemUnk2 to uint11 - TableColumn gemUnk2Column = gemTable.getColumnModel().getColumn(6); + TableColumn gemUnk2Column = gemTable.getColumnModel().getColumn(7); JTextField gemUnk2TextField = new JTextField(); doc = (AbstractDocument) gemUnk2TextField.getDocument(); doc.setDocumentFilter(gui.uint11); gemUnk2Column.setCellEditor(new DefaultCellEditor(gemUnk2TextField)); // set gemUnk3 to uint7 - TableColumn gemUnk3Column = gemTable.getColumnModel().getColumn(7); + TableColumn gemUnk3Column = gemTable.getColumnModel().getColumn(8); JTextField gemUnk3TextField = new JTextField(); doc = (AbstractDocument) gemUnk3TextField.getDocument(); doc.setDocumentFilter(gui.uint7); gemUnk3Column.setCellEditor(new DefaultCellEditor(gemUnk3TextField)); - gui.setArray(SaveField.gemArray, new ArrayField[] {ArrayField.gemID1, ArrayField.gemID2, ArrayField.gemRank, ArrayField.gemValue, ArrayField.gemInventorySlot, ArrayField.gemUnk1, ArrayField.gemUnk2, ArrayField.gemUnk3}, gemTable); + gui.setArray(SaveField.gemArray, new ArrayField[] {null, ArrayField.gemID1, ArrayField.gemID2, ArrayField.gemRank, ArrayField.gemValue, ArrayField.gemInventorySlot, ArrayField.gemUnk1, ArrayField.gemUnk2, ArrayField.gemUnk3}, gemTable); JScrollPane gemScrollPane = new JScrollPane(gemTable); - this.add(gemScrollPane, "cell 0 1,growx,aligny top,spanx 2"); + this.add(gemScrollPane, "cell 0 2,growx,aligny top,spanx 2"); } + public int getGemTableNumRows() { return this.gemTable.getModel().getRowCount(); } + public int getWeaponTableNumRows() { return this.weaponTable.getModel().getRowCount(); } } diff --git a/View/ViewEvent.java b/View/ViewEvent.java index 96ee25a..19cd77c 100644 --- a/View/ViewEvent.java +++ b/View/ViewEvent.java @@ -15,8 +15,11 @@ public class ViewEvent extends EventObject { private EventType type; private SaveField sf; - private ArrayField af; + + private SaveField destSf; + private ArrayField destAf; + private Integer destIndex; private String fileLocation; @@ -25,16 +28,17 @@ public class ViewEvent extends EventObject { private String value; public enum EventType { - OPEN_FILE, // param is file location - SAVE_FILE, // param null - GET_DATA, // param is a SaveField - SET_DATA, // param is "saveField:value" - SET_ARRAY_DATA, // param is "saveField(array):index:arrayField:value" - GET_ARRAY_DATA, // param is "saveField(array):index:arrayField" + OPEN_FILE, + SAVE_FILE, + GET_DATA, + SET_DATA, + SET_ARRAY_DATA, + GET_ARRAY_DATA, + SET_COPY_ARRAY_DATA, // copies array data from one array to another } /** - * ViewEvent constructor with param parameter (for event OPEN_FILE, SET_DATA) + * ViewEvent constructor * @param source the object that created this ViewEvent * @param type the type of ViewEvent described by the constants of this class * @param fileLocation the location of the file to be opened; or null if not applicable to the type @@ -65,6 +69,8 @@ public ViewEvent(Object source, EventType type, String fileLocation, SaveField s case SET_DATA: if (sf == null || value == null) throw new IllegalArgumentException(); break; + case SET_COPY_ARRAY_DATA: + throw new IllegalArgumentException(); } this.type = type; @@ -74,6 +80,18 @@ public ViewEvent(Object source, EventType type, String fileLocation, SaveField s this.index = index; this.value = value; } + + // ViewEvent constructor for SET_COPY_ARRAY_DATA + public ViewEvent(Object source, SaveField originSf, ArrayField originAf, Integer originIndex, SaveField destSf, ArrayField destAf, Integer destIndex) { + super(source); + this.type = EventType.SET_COPY_ARRAY_DATA; + this.sf = originSf; + this.af = originAf; + this.destSf = destSf; + this.destAf = destAf; + this.destIndex = destIndex; + this.index = originIndex; + } /** * @return the type of this ViewEvent described by the constants of this class; or null if not applicable @@ -90,6 +108,18 @@ public ViewEvent(Object source, EventType type, String fileLocation, SaveField s * Used in conjunction with an index to uniquely identify an Array element */ public ArrayField getArrayField() { return this.af; } + + /** + * @return the SaveField to copy to; null if not applicable + * Used only with SET_COPY_ARRAY_DATA + */ + public SaveField getDestSaveField() { return this.destSf; } + + /** + * @return the Array column name to copy to; null if not applicable + * Used only with SET_COPY_ARRAY_DATA + */ + public ArrayField getDestArrayField() { return this.destAf; } /** * @return the file location of the file to open, used only with EventType.OPEN_FILE @@ -101,6 +131,12 @@ public ViewEvent(Object source, EventType type, String fileLocation, SaveField s * Used in conjunction with an ArrayField to uniquely identify an Array element */ public Integer getIndex() { return this.index; } + + /** + * @return the Array index (or row) this ViewEvent wants to copy to; or null if not applicable + * Used only with SET_COPY_ARRAY_DATA + */ + public Integer getDestIndex() { return this.destIndex; } /** * @return the value to set a save field to; or null if not applicable