This is a breaking change in the save format; the application discards previously saved data if it's
incompatible.
package net.jcornell.tile_draw;
+import javax.swing.JFrame;
import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.awt.Dimension;
import net.jcornell.tile_draw.util.Util;
data = Util.loadData();
} catch (IOException | ClassNotFoundException | Util.ImageLoadException e) {
e.printStackTrace();
+ data = new SaveData(new ArrayList<>(), null);
}
- List<TileConfigModel> tileModels;
- File chooserDir;
- if (data == null) {
- tileModels = new ArrayList<>();
- chooserDir = null;
- } else {
- tileModels = data.tileModels;
- chooserDir = data.fileChooserDir;
- }
-
- TileSelectController tsController = new TileSelectController(tileModels, chooserDir);
- Window window = tsController.view.window;
+ JFrame window = new JFrame("Tile Draw");
+ window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ TileSetsController controller = new TileSetsController(data.tileSets, data.fileChooserDir);
+ TileSetsSwingView view = new TileSetsSwingView(controller);
+ controller.view = view;
+ window.setContentPane(view.contentPane);
+ window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
import java.io.File;
import java.util.List;
+import net.jcornell.tile_draw.TileSetsController.TileSet;
+
public class SaveData implements Serializable {
- private static final long serialVersionUID = 0;
+ private static final long serialVersionUID = 1;
- public List<TileConfigModel> tileModels;
+ public List<TileSet> tileSets;
public File fileChooserDir;
public SaveData() {}
- public SaveData(List<TileConfigModel> tileModels, File fileChooserDir) {
- this.tileModels = tileModels;
+ public SaveData(List<TileSet> tileSets, File fileChooserDir) {
+ this.tileSets = tileSets;
this.fileChooserDir = fileChooserDir;
}
}
public void loadImage() throws Util.ImageLoadException {
imageView = new ImageIcon(
- Util.extractImage(imageFile).getScaledInstance(-1, TileSelectController.THUMBNAIL_HEIGHT, 0)
+ Util.extractImage(imageFile).getScaledInstance(-1, TileSetEditController.THUMBNAIL_HEIGHT, 0)
);
}
+
+ public TileConfigModel copy() {
+ try {
+ return new TileConfigModel(imageFile, multiplicity);
+ } catch (Util.ImageLoadException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
+++ /dev/null
-package net.jcornell.tile_draw;
-
-import java.awt.Dialog;
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Image;
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.swing.BorderFactory;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JFileChooser;
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSpinner;
-import javax.swing.JTable;
-import javax.swing.SpinnerNumberModel;
-import javax.swing.table.AbstractTableModel;
-
-import net.jcornell.tile_draw.util.Util;
-import net.jcornell.tile_draw.util.JSpinnerTableCellEditor;
-
-
-public class TileSelectController extends AbstractTableModel {
- public static final int DEFAULT_MULTIPLICITY = 1;
- public static final int THUMBNAIL_HEIGHT = 50;
- protected static final Class<?>[] COL_CLASSES = new Class<?>[] {Boolean.class, ImageIcon.class, Integer.class};
- protected static final String[] COL_NAMES = new String[] {"", "Tile", "Multiplicity"};
-
- public final List<TileConfigModel> tileModels;
- public final TileSelectView view;
- public File fileChooserDir;
-
- public TileSelectController(List<TileConfigModel> tileModels, File fileChooserDir) {
- this.tileModels = tileModels;
- view = new TileSelectView(this);
- this.fileChooserDir = fileChooserDir;
- view.setCanBegin(!tileModels.isEmpty());
- }
-
- public void addTiles(List<TileConfigModel> toAdd) {
- int oldSize = tileModels.size();
- tileModels.addAll(toAdd);
- super.fireTableRowsInserted(oldSize, tileModels.size());
- view.setCanBegin(true);
- saveData();
- }
-
- public void dropTiles(List<TileConfigModel> toDrop) {
- for (TileConfigModel m : toDrop) {
- int row = tileModels.indexOf(m);
- tileModels.remove(m);
- super.fireTableRowsDeleted(row, row);
- }
- view.setCanBegin(!tileModels.isEmpty());
- saveData();
- }
-
- public List<TileConfigModel> getSelectedTiles() {
- return tileModels.stream()
- .filter(m -> m.selected)
- .collect(Collectors.toList())
- ;
- }
-
- public void beginDraw() {
- DrawController c = new DrawController(tileModels);
- c.drawTile();
- Dialog dialog = c.view.dialog;
- dialog.pack();
- dialog.setResizable(false);
- dialog.setLocationRelativeTo(view.window);
- dialog.setVisible(true);
- }
-
- public void saveData() {
- SaveData data = new SaveData(tileModels, fileChooserDir);
- try {
- Util.saveData(data);
- } catch (IOException e) {}
- }
-
- @Override
- public int getRowCount() {
- return tileModels.size();
- }
-
- @Override
- public int getColumnCount() {
- return COL_CLASSES.length;
- }
-
- @Override
- public String getColumnName(int col) {
- return COL_NAMES[col];
- }
-
- @Override
- public Object getValueAt(int row, int col) {
- TileConfigModel m = tileModels.get(row);
- return new Object[] {m.selected, m.imageView, m.multiplicity}[col];
- }
-
- @Override
- public void setValueAt(Object value, int row, int col) {
- TileConfigModel m = tileModels.get(row);
- if (col == 0) {
- m.selected = (boolean) value;
- } else if (col == 2) {
- m.multiplicity = (int) value;
- saveData();
- } else {
- throw new AssertionError();
- }
- }
-
- @Override
- public Class<?> getColumnClass(int col) {
- return COL_CLASSES[col];
- }
-
- @Override
- public boolean isCellEditable(int row, int col) {
- return new boolean[] {true, false, true}[col];
- }
-}
-
-
-class TileSelectView {
- protected final TileSelectController controller;
- protected final JTable grid;
- protected final JButton beginButton;
- public final JFrame window;
-
- public TileSelectView(TileSelectController controller) {
- this.controller = controller;
- grid = createGrid();
- beginButton = new JButton("Begin");
- window = createWindow();
- }
-
- protected JTable createGrid() {
- JTable grid = new JTable(controller);
- grid.setRowHeight(TileSelectController.THUMBNAIL_HEIGHT);
- JSpinner spinner = new JSpinner(
- new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1)
- );
- grid.getColumnModel().getColumn(2).setCellEditor(new JSpinnerTableCellEditor(spinner));
- return grid;
- }
-
- private static TileConfigModel tryTileBuild(File imageFile) {
- try {
- return new TileConfigModel(imageFile, TileSelectController.DEFAULT_MULTIPLICITY);
- } catch (Util.ImageLoadException e) {
- return null;
- }
- }
-
- protected JFrame createWindow() {
- JFrame frame = new JFrame("Select Tiles");
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setLayout(new GridBagLayout());
-
- JScrollPane tilesScrollPane = new JScrollPane(grid);
- tilesScrollPane.setPreferredSize(new Dimension(400, 150));
-
- GridBagConstraints tilesPaneC = new GridBagConstraints();
- tilesPaneC.gridx = 0;
- tilesPaneC.gridy = GridBagConstraints.RELATIVE;
- tilesPaneC.fill = GridBagConstraints.BOTH;
- tilesPaneC.weightx = 1;
- tilesPaneC.weighty = 1;
- frame.add(tilesScrollPane, tilesPaneC);
-
- JButton deleteBtn = new JButton("Delete selected");
- deleteBtn.addActionListener(e -> {
- controller.dropTiles(controller.getSelectedTiles());
- });
-
- JButton addBtn = new JButton("Add…");
- addBtn.addActionListener(e -> {
- JFileChooser chooser = new JFileChooser(controller.fileChooserDir);
- chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
- chooser.setMultiSelectionEnabled(true);
- int result = chooser.showOpenDialog(addBtn);
- controller.fileChooserDir = chooser.getCurrentDirectory();
- controller.saveData();
- if (result == JFileChooser.APPROVE_OPTION) {
- File[] files = chooser.getSelectedFiles();
- List<TileConfigModel> newModels = Arrays.stream(files)
- .map(TileSelectView::tryTileBuild)
- .collect(Collectors.toList())
- ;
- if (newModels.contains(null)) {
- JOptionPane.showMessageDialog(
- frame, "Failed to load one or more files as images", "Image load error", JOptionPane.WARNING_MESSAGE
- );
- }
- List<TileConfigModel> okay = newModels.stream()
- .filter(m -> m != null)
- .collect(Collectors.toList())
- ;
- controller.addTiles(okay);
- }
- });
-
- beginButton.addActionListener(e -> {
- controller.beginDraw();
- });
-
- JPanel buttonRow = new JPanel();
- buttonRow.setLayout(new BoxLayout(buttonRow, BoxLayout.LINE_AXIS));
- buttonRow.add(deleteBtn);
- buttonRow.add(Box.createRigidArea(new Dimension(5, 0)));
- buttonRow.add(addBtn);
- buttonRow.add(Box.createHorizontalGlue());
- buttonRow.add(beginButton);
- buttonRow.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
-
- GridBagConstraints btnBarC = new GridBagConstraints();
- btnBarC.gridx = 0;
- btnBarC.gridy = GridBagConstraints.RELATIVE;
- btnBarC.fill = GridBagConstraints.HORIZONTAL;
- frame.add(buttonRow, btnBarC);
-
- frame.pack();
- return frame;
- }
-
- public void setCanBegin(boolean canBegin) {
- beginButton.setEnabled(canBegin);
- }
-}
--- /dev/null
+package net.jcornell.tile_draw;
+
+import java.awt.Dialog;
+import java.awt.Dimension;
+import javax.swing.JTextField;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.io.File;
+import java.awt.event.FocusEvent;
+import java.io.IOException;
+import java.util.Arrays;
+import javax.swing.JDialog;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.table.TableCellEditor;
+import javax.swing.ImageIcon;
+import java.awt.Insets;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JComponent;
+import java.awt.Component;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSpinner;
+import javax.swing.JTable;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.table.AbstractTableModel;
+
+import net.jcornell.tile_draw.TileSetsController.TileSet;
+import net.jcornell.tile_draw.util.JSpinnerTableCellEditor;
+import net.jcornell.tile_draw.util.Util;
+
+
+public class TileSetEditController extends AbstractTableModel {
+ public static final int DEFAULT_MULTIPLICITY = 1;
+ public static final int THUMBNAIL_HEIGHT = 50;
+ protected static final Class<?>[] COL_CLASSES = new Class<?>[] {Boolean.class, ImageIcon.class, Integer.class};
+ protected static final String[] COL_NAMES = new String[] {"", "Tile", "Multiplicity"};
+
+ public static interface EventListener {
+ public void onSubmitTileSet(TileSet value);
+ }
+
+ public final TileSet tileSet;
+ public TileSetEditSwingView view;
+ public final TileSetsController parent;
+ public final EventListener listener;
+ protected final TileSet originalValue;
+
+ public TileSetEditController(TileSet tileSet, EventListener listener, TileSetsController parent) {
+ this.tileSet = tileSet.copy();
+ this.parent = parent;
+ this.listener = listener;
+ originalValue = tileSet;
+ }
+
+ public void addTiles(List<TileConfigModel> toAdd) {
+ int oldSize = tileSet.tileModels.size();
+ tileSet.tileModels.addAll(toAdd);
+ super.fireTableRowsInserted(oldSize, tileSet.tileModels.size());
+ }
+
+ public void dropTiles(List<TileConfigModel> toDrop) {
+ for (TileConfigModel m : toDrop) {
+ int row = tileSet.tileModels.indexOf(m);
+ tileSet.tileModels.remove(m);
+ super.fireTableRowsDeleted(row, row);
+ }
+ }
+
+ public List<TileConfigModel> getSelectedTiles() {
+ return
+ tileSet.tileModels.stream()
+ .filter(m -> m.selected)
+ .collect(Collectors.toList())
+ ;
+ }
+
+ public File getChooserDir() {
+ return parent.fileChooserDir;
+ }
+
+ public void setChooserDir(File newDir) {
+ parent.setFileChooserDir(newDir);
+ }
+
+ public void submitChanges() {
+ listener.onSubmitTileSet(tileSet);
+ }
+
+ public boolean isClean() {
+ return tileSet.equals(originalValue);
+ }
+
+ @Override
+ public int getRowCount() {
+ return tileSet.tileModels.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return COL_CLASSES.length;
+ }
+
+ @Override
+ public String getColumnName(int col) {
+ return COL_NAMES[col];
+ }
+
+ @Override
+ public Object getValueAt(int row, int col) {
+ TileConfigModel m = tileSet.tileModels.get(row);
+ return new Object[] {m.selected, m.imageView, m.multiplicity}[col];
+ }
+
+ @Override
+ public void setValueAt(Object value, int row, int col) {
+ TileConfigModel m = tileSet.tileModels.get(row);
+ if (col == 0) {
+ m.selected = (boolean) value;
+ } else if (col == 2) {
+ m.multiplicity = (int) value;
+ } else {
+ throw new AssertionError();
+ }
+ }
+
+ @Override
+ public Class<?> getColumnClass(int col) {
+ return COL_CLASSES[col];
+ }
+
+ @Override
+ public boolean isCellEditable(int row, int col) {
+ return new boolean[] {true, false, true}[col];
+ }
+}
+
+
+class TileSetEditSwingView {
+ protected final TileSetEditController controller;
+ protected JTextField nameField;
+ protected JTable grid;
+ protected TableCellEditor multColumnEditor;
+ public JOptionPane optionPane;
+ public JDialog dialog;
+
+ public TileSetEditSwingView(TileSetEditController controller, Component dialogParent) {
+ this.controller = controller;
+ populateUi(dialogParent);
+ }
+
+ private static TileConfigModel tryTileBuild(File imageFile) {
+ try {
+ return new TileConfigModel(imageFile, TileSetEditController.DEFAULT_MULTIPLICITY);
+ } catch (Util.ImageLoadException e) {
+ return null;
+ }
+ }
+
+ protected void populateUi(Component dialogParent) {
+ grid = new JTable(controller);
+ grid.setRowHeight(TileSetEditController.THUMBNAIL_HEIGHT);
+ JSpinner spinner = new JSpinner(
+ new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1)
+ );
+ multColumnEditor = new JSpinnerTableCellEditor(spinner);
+ grid.getColumnModel().getColumn(2).setCellEditor(multColumnEditor);
+
+ JPanel panel = new JPanel(new GridBagLayout());
+
+ nameField = new JTextField(controller.originalValue.name);
+ GridBagConstraints nameFieldC = new GridBagConstraints();
+ nameFieldC.gridx = 0;
+ nameFieldC.gridy = GridBagConstraints.RELATIVE;
+ nameFieldC.fill = GridBagConstraints.HORIZONTAL;
+ nameFieldC.insets = new Insets(0, 0, 10, 0);
+ nameFieldC.ipady = 5;
+ panel.add(nameField, nameFieldC);
+
+ JScrollPane tilesScrollPane = new JScrollPane(grid);
+ tilesScrollPane.setPreferredSize(new Dimension(400, 150));
+
+ GridBagConstraints tilesPaneC = new GridBagConstraints();
+ tilesPaneC.gridx = 0;
+ tilesPaneC.gridy = GridBagConstraints.RELATIVE;
+ tilesPaneC.fill = GridBagConstraints.BOTH;
+ tilesPaneC.weightx = 1;
+ tilesPaneC.weighty = 1;
+ panel.add(tilesScrollPane, tilesPaneC);
+
+ JButton deleteBtn = new JButton("Delete selected");
+ deleteBtn.addActionListener(e -> {
+ controller.dropTiles(controller.getSelectedTiles());
+ });
+
+ JButton addBtn = new JButton("Add…");
+ addBtn.addActionListener(e -> {
+ JFileChooser chooser = new JFileChooser(controller.getChooserDir());
+ chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ chooser.setMultiSelectionEnabled(true);
+ int result = chooser.showOpenDialog(addBtn);
+ controller.setChooserDir(chooser.getCurrentDirectory());
+ if (result == JFileChooser.APPROVE_OPTION) {
+ File[] files = chooser.getSelectedFiles();
+ List<TileConfigModel> newModels = Arrays.stream(files)
+ .map(TileSetEditSwingView::tryTileBuild)
+ .collect(Collectors.toList())
+ ;
+ if (newModels.contains(null)) {
+ JOptionPane.showMessageDialog(
+ panel, "Failed to load one or more files as images", "Image load error", JOptionPane.WARNING_MESSAGE
+ );
+ }
+ List<TileConfigModel> okay =
+ newModels.stream()
+ .filter(m -> m != null)
+ .collect(Collectors.toList())
+ ;
+ controller.addTiles(okay);
+ }
+ });
+
+ JPanel buttonRow = new JPanel();
+ buttonRow.setLayout(new BoxLayout(buttonRow, BoxLayout.LINE_AXIS));
+ buttonRow.add(deleteBtn);
+ buttonRow.add(Box.createRigidArea(new Dimension(5, 0)));
+ buttonRow.add(addBtn);
+ buttonRow.add(Box.createHorizontalGlue());
+
+ GridBagConstraints btnBarC = new GridBagConstraints();
+ btnBarC.gridx = 0;
+ btnBarC.gridy = GridBagConstraints.RELATIVE;
+ btnBarC.fill = GridBagConstraints.HORIZONTAL;
+ btnBarC.insets = new Insets(10, 0, 5, 0);
+ panel.add(buttonRow, btnBarC);
+
+ optionPane = new JOptionPane(panel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
+ dialog = optionPane.createDialog(dialogParent, "Tile set editor");
+ dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ }
+
+ public void finishEditing() {
+ multColumnEditor.stopCellEditing();
+ }
+
+ public void submitChanges() {
+ controller.tileSet.name = nameField.getText();
+ controller.submitChanges();
+ }
+}
--- /dev/null
+package net.jcornell.tile_draw;
+
+import javax.swing.JComponent;
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JDialog;
+import javax.swing.JScrollPane;
+import javax.swing.JFrame;
+import java.util.stream.Collectors;
+import javax.swing.ListSelectionModel;
+import javax.swing.JOptionPane;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.Serializable;
+import java.io.File;
+import java.io.IOException;
+import java.awt.BorderLayout;
+import java.awt.Dialog;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import net.jcornell.tile_draw.TileSetsController.TileSet;
+import net.jcornell.tile_draw.util.Util;
+
+
+public class TileSetsController {
+ public static class TileSet implements Serializable {
+ private static final long serialVersionUID = 0;
+
+ public String name;
+ public List<TileConfigModel> tileModels;
+
+ public TileSet(String name, List<TileConfigModel> tileModels) {
+ this.name = name;
+ this.tileModels = tileModels;
+ }
+
+ public TileSet copy() {
+ return new TileSet(name, tileModels.stream().map(TileConfigModel::copy).collect(Collectors.toList()));
+ }
+
+ @Override public boolean equals(Object otherObj) {
+ TileSet other = (TileSet) otherObj;
+ return other.name.equals(name) && other.tileModels.equals(tileModels);
+ }
+ }
+
+ protected final List<TileSet> tileSets;
+ protected TileSetsSwingView view;
+ public File fileChooserDir;
+
+ public TileSetsController(List<TileSet> tileSets, File fileChooserDir) {
+ this.tileSets = tileSets;
+ this.fileChooserDir = fileChooserDir;
+ }
+
+ public void addSet(TileSet set) {
+ tileSets.add(set);
+ view.addSet(set);
+ saveData();
+ }
+
+ protected void setSetAt(int index, TileSet value) {
+ tileSets.set(index, value);
+ view.setSetAt(index, value);
+ saveData();
+ }
+
+ public void deleteSetAt(int index) {
+ tileSets.remove(index);
+ view.deleteSetAt(index);
+ saveData();
+ }
+
+ public void saveData() {
+ try {
+ Util.saveData(new SaveData(tileSets, fileChooserDir));
+ } catch (IOException e) {
+ view.onSaveFailed(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void setFileChooserDir(File value) {
+ fileChooserDir = value;
+ saveData();
+ }
+
+ public void beginEdit(int setIndex) {
+ TileSetEditController.EventListener listener = new TileSetEditController.EventListener() {
+ @Override public void onSubmitTileSet(TileSet value) {
+ setSetAt(setIndex, value);
+ }
+ };
+
+ TileSet target = tileSets.get(setIndex);
+ TileSetEditController subController = new TileSetEditController(target, listener, this);
+ TileSetEditSwingView subView = view.getEditView(subController);
+ subController.view = subView;
+ view.doEdit(subView);
+ }
+
+ public void beginDraw(int setIndex) {
+ DrawController c = new DrawController(tileSets.get(setIndex).tileModels);
+ c.drawTile();
+ Dialog dialog = c.view.dialog;
+ dialog.pack();
+ dialog.setResizable(false);
+ dialog.setLocationRelativeTo(view.contentPane);
+ dialog.setVisible(true);
+ }
+}
+
+
+class TileSetsSwingView {
+ protected final TileSetsController controller;
+ protected final DefaultListModel<TileSetWrapper> viewModel;
+ protected final JList<TileSetWrapper> setList;
+ protected final JButton deleteButton, editButton, beginButton;
+
+ public final JComponent contentPane;
+
+ protected static class TileSetWrapper {
+ protected final TileSet tileSet;
+
+ public TileSetWrapper(TileSet tileSet) {
+ this.tileSet = tileSet;
+ }
+
+ public String toString() {
+ return tileSet.name;
+ }
+ }
+
+ public TileSetsSwingView(TileSetsController controller) {
+ this.controller = controller;
+ viewModel = new DefaultListModel<>();
+ for (TileSet tileSet : controller.tileSets) {
+ viewModel.addElement(new TileSetWrapper(tileSet));
+ }
+ setList = new JList<>(viewModel);
+ setList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ contentPane = new JPanel(new BorderLayout());
+ JPanel buttonBar = new JPanel();
+
+ JButton addButton = new JButton("Add");
+ addButton.addActionListener(e -> {
+ String newName = (String) JOptionPane.showInputDialog(
+ contentPane,
+ "Enter a name for the new tile set",
+ "New tile set",
+ JOptionPane.PLAIN_MESSAGE
+ );
+ if (newName != null) {
+ controller.addSet(new TileSet(newName, new ArrayList<>()));
+ }
+ });
+ buttonBar.add(addButton);
+
+ deleteButton = new JButton("Delete");
+ deleteButton.addActionListener(e -> {
+ int sel = setList.getSelectedIndex();
+ if (sel != -1) {
+ int response = JOptionPane.showConfirmDialog(
+ contentPane, "Delete this tile set?", "Confirm delete",
+ JOptionPane.OK_CANCEL_OPTION
+ );
+ if (response == JOptionPane.OK_OPTION) {
+ controller.deleteSetAt(sel);
+ }
+ }
+ });
+ buttonBar.add(deleteButton);
+
+ editButton = new JButton("Edit");
+ editButton.addActionListener(e -> {
+ controller.beginEdit(setList.getSelectedIndex());
+ });
+ buttonBar.add(editButton);
+
+ beginButton = new JButton("Begin");
+ beginButton.addActionListener(e -> {
+ controller.beginDraw(setList.getSelectedIndex());
+ });
+ buttonBar.add(beginButton);
+
+ setList.addListSelectionListener(e -> updateButtonStates());
+
+ JScrollPane setPane = new JScrollPane(setList);
+
+ contentPane.add(setPane, BorderLayout.CENTER);
+ contentPane.add(buttonBar, BorderLayout.PAGE_END);
+ updateButtonStates();
+ }
+
+ public void addSet(TileSet set) {
+ viewModel.addElement(new TileSetWrapper(set));
+ }
+
+ public void setSetAt(int index, TileSet value) {
+ viewModel.set(index, new TileSetWrapper(value));
+ updateButtonStates();
+ }
+
+ public void deleteSetAt(int index) {
+ viewModel.removeElementAt(index);
+ }
+
+ public TileSetEditSwingView getEditView(TileSetEditController subController) {
+ return new TileSetEditSwingView(subController, contentPane);
+ }
+
+ public void doEdit(TileSetEditSwingView editView) {
+ editView.dialog.setVisible(true);
+ editView.finishEditing();
+ Object value = editView.optionPane.getValue();
+ if (value != null && (int) value == JOptionPane.OK_OPTION) {
+ editView.submitChanges();
+ }
+ }
+
+ public void updateButtonStates() {
+ int selIndex = setList.getSelectedIndex();
+ boolean hasSelection = selIndex != -1;
+ deleteButton.setEnabled(hasSelection);
+ editButton.setEnabled(hasSelection);
+
+ boolean canBegin = hasSelection && !controller.tileSets.get(selIndex).tileModels.isEmpty();
+ beginButton.setEnabled(canBegin);
+ }
+
+ public void onSaveFailed(Throwable exception) {
+ JOptionPane.showMessageDialog(
+ contentPane,
+ "Error saving data: " + exception.toString(),
+ "Save error",
+ JOptionPane.ERROR_MESSAGE
+ );
+ }
+}
import net.jcornell.tile_draw.SaveData;
import net.jcornell.tile_draw.TileConfigModel;
+import net.jcornell.tile_draw.TileSetsController.TileSet;
public final class Util {
);
public static SaveData loadData() throws IOException, ClassNotFoundException, Util.ImageLoadException {
+ Files.createDirectories(SAVE_LOCATION.getParent());
SaveData data;
try (InputStream input = Files.newInputStream(SAVE_LOCATION)) {
data = (SaveData) new ObjectInputStream(input).readObject();
}
- for (TileConfigModel m : data.tileModels) {
- m.loadImage();
+ for (TileSet set : data.tileSets) {
+ for (TileConfigModel m : set.tileModels) {
+ m.loadImage();
+ }
}
return data;
}