/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter.themes.impl.simple;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.swing.JButton;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import org.pepsoft.worldpainter.Terrain;
/**
*
* @author pepijn
*/
public class TerrainRangesTableModel implements TableModel {
public TerrainRangesTableModel(SortedMap<Integer, Terrain> terrainRanges) {
levels = new int[terrainRanges.size()];
terrains = new Terrain[terrainRanges.size()];
rows = terrainRanges.size();
int i = 0;
for (Map.Entry<Integer, Terrain> row: terrainRanges.entrySet()) {
levels[i] = row.getKey() + 1;
terrains[i] = row.getValue();
i++;
}
}
public void addRow(int level, Terrain terrain) {
SortedMap<Integer, Terrain> sortedMap = new TreeMap<>();
sortedMap.put(level, terrain);
for (int i = 0; i < rows; i++) {
sortedMap.put(levels[i], terrains[i]);
}
rows++;
if (rows > levels.length) {
levels = new int[rows];
terrains = new Terrain[rows];
}
int i = 0;
for (Map.Entry<Integer, Terrain> row: sortedMap.entrySet()) {
levels[i] = row.getKey();
terrains[i] = row.getValue();
i++;
}
TableModelEvent event = new TableModelEvent(this);
for (TableModelListener listener: listeners) {
listener.tableChanged(event);
}
notifyChangeListener();
}
public void deleteRow(int row) {
System.arraycopy(levels, row + 1, levels, row, rows - 1 - row);
System.arraycopy(terrains, row + 1, terrains, row, rows - 1 - row);
rows--;
TableModelEvent event = new TableModelEvent(this, row, row, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE);
for (TableModelListener listener: listeners) {
listener.tableChanged(event);
}
notifyChangeListener();
}
public SortedMap<Integer, Terrain> getTerrainRanges() {
SortedMap<Integer, Terrain> terrainRanges = new TreeMap<>();
for (int i = 0; i < rows; i++) {
terrainRanges.put(levels[i] - 1, terrains[i]);
}
return terrainRanges;
}
public boolean isValid() {
for (int i = 1; i < rows; i++) {
if (levels[i] == levels[i - 1]) {
return false;
}
}
return true;
}
public ChangeListener getChangeListener() {
return changeListener;
}
public void setChangeListener(ChangeListener changeListener) {
this.changeListener = changeListener;
}
// TableModel
@Override
public int getRowCount() {
return rows;
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
return "Level";
case 1:
return "Terrain type";
case 2:
return "Actions";
default:
throw new IllegalArgumentException();
}
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Integer.class;
case 1:
return Terrain.class;
case 2:
return JButton.class;
default:
throw new IllegalArgumentException();
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
// Level or action of first row should not be editable
return (rowIndex > 0) || (columnIndex == 1);
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return levels[rowIndex];
case 1:
return terrains[rowIndex];
case 2:
if (rowIndex > 0) {
return deleteButton;
} else {
return null;
}
default:
throw new IllegalArgumentException();
}
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
levels[rowIndex] = (Integer) aValue;
sortIfNeeded();
notifyChangeListener();
break;
case 1:
terrains[rowIndex] = (Terrain) aValue;
notifyChangeListener();
break;
case 2:
// Do nothing
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void addTableModelListener(TableModelListener l) {
listeners.add(l);
}
@Override
public void removeTableModelListener(TableModelListener l) {
listeners.remove(l);
}
private void sortIfNeeded() {
for (int i = 1; i < rows; i++) {
if (levels[i] < levels[i - 1]) {
SortedMap<Integer, Terrain> sortedMap = new TreeMap<>();
for (int j = 0; j < rows; j++) {
sortedMap.put(levels[j], terrains[j]);
}
int j = 0;
for (Map.Entry<Integer, Terrain> row: sortedMap.entrySet()) {
levels[j] = row.getKey();
terrains[j] = row.getValue();
j++;
}
TableModelEvent event = new TableModelEvent(this, 0, rows - 1);
for (TableModelListener listener: listeners) {
listener.tableChanged(event);
}
notifyChangeListener();
break;
}
}
}
private void notifyChangeListener() {
if (changeListener != null) {
changeListener.dataChanged(this);
}
}
private final JButton deleteButton = new JButton("Delete");
private final List<TableModelListener> listeners = new ArrayList<>();
private int[] levels;
private Terrain[] terrains;
private int rows;
private ChangeListener changeListener;
public interface ChangeListener {
/**
* Indicates that the data in the specified model changed, either
* because of an edit by a JTable, or someone invoking the public API.
*
* @param model The model that has changed.
*/
void dataChanged(TerrainRangesTableModel model);
}
}