/**
* @file ConfigurationManager.java
* @brief Class implementing a frame for managing multiple configurations.
*
* @section License
*
* Copyright (C) 2015 Robert B. Colton
* This file is a part of the LateralGM IDE.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
package org.lateralgm.subframes;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.lateralgm.components.impl.NameDocument;
import org.lateralgm.file.ProjectFile;
import org.lateralgm.main.LGM;
import org.lateralgm.messages.Messages;
import org.lateralgm.resources.GameSettings;
public class ConfigurationManager extends JDialog implements ActionListener
{
/**
* NOTE: Default UID generated, change if necessary.
*/
private static final long serialVersionUID = 683154513336137335L;
JList<GameSettings> configList = null;
private VectorListModel<GameSettings> vlm;
private JButton deleteButton;
private static ConfigurationManager INSTANCE = null;
public static ConfigurationManager getInstance() {
if (INSTANCE == null) {
INSTANCE = new ConfigurationManager();
INSTANCE.setConfigList(LGM.currentFile.gameSettings);
}
return INSTANCE;
}
// The purpose of this internal class is because Vectors and ArrayLists are handled by reference for Java
// so instead of converting to an array and doing all kinds of crazy updating, we can just make a list model
// that handles the array by reference.
public class VectorListModel<T> extends AbstractListModel<T> {
/**
* NOTE: Default UID generated, change if necessary.
*/
private static final long serialVersionUID = 8672982566605074780L;
private Vector<T> vector = null;
public VectorListModel(Vector<T> vec) {
vector = vec;
}
public void add(int index, T element) {
vector.add(index,element);
super.fireIntervalAdded(this,index,index);
}
public void addElement(T element) {
vector.addElement(element);
super.fireIntervalAdded(this,vector.size()-1,vector.size()-1);
}
public boolean remove(T element) {
int index = vector.indexOf(element);
boolean ret = vector.remove(element);
super.fireIntervalRemoved(this,index,index);
return ret;
}
public boolean removeAll(List<T> elements) {
boolean ret = vector.removeAll(elements);
super.fireIntervalRemoved(this,0,elements.size());
return ret;
}
public T getElementAt(int index) {
return vector.get(index);
}
public T get(int index) {
return vector.get(index);
}
public Enumeration<T> elements() {
return vector.elements();
}
public Object[] toArray() {
return vector.toArray();
}
public int size() {
return vector.size();
}
public boolean isEmpty() {
return vector.isEmpty();
}
@Override
public int getSize()
{
return vector.size();
}
}
public ConfigurationManager() {
super(LGM.frame);
setResizable(false);
setAlwaysOnTop(true);
setTitle(Messages.getString("ConfigurationManager.TITLE"));
setIconImage(LGM.getIconForKey("ConfigurationManager.ICON").getImage());
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
deleteButton = makeToolbarButton("DELETE");
configList = new JList<GameSettings>();
toolbar.add(makeToolbarButton("ADD"));
toolbar.add(makeToolbarButton("COPY"));
toolbar.add(deleteButton);
toolbar.addSeparator();
toolbar.add(makeToolbarButton("EDIT_SETTINGS"));
toolbar.add(makeToolbarButton("EDIT_CONSTANTS"));
toolbar.addSeparator();
toolbar.add(new JLabel(Messages.getString("ConfigurationManager.NAME")));
final JTextField nameField = new JTextField();
nameField.setDocument(new NameDocument());
nameField.setColumns(10);
nameField.setMaximumSize(nameField.getPreferredSize());
nameField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateNameField(e);
}
public void removeUpdate(DocumentEvent e) {
updateNameField(e);
}
public void insertUpdate(DocumentEvent e) {
updateNameField(e);
}
public void updateNameField(DocumentEvent e) {
GameSettings sel = configList.getSelectedValue();
if (sel == null) return;
sel.setName(nameField.getText());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run()
{
configList.updateUI();
}
});
sel.constants.setName(nameField.getText());
LGM.getConstantsFrame().updateTitle();
LGM.getGameSettings().updateTitle();
}
});
configList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent ev)
{
GameSettings sel = configList.getSelectedValue();
if (sel == null) return;
nameField.setText(sel.getName());
}
});
toolbar.add(nameField);
this.add(toolbar, BorderLayout.NORTH);
JScrollPane scroll = new JScrollPane(configList);
this.add(scroll, BorderLayout.CENTER);
this.pack();
this.setSize(this.getWidth(),320);
setLocationRelativeTo(LGM.frame);
}
JButton makeToolbarButton(String key) {
key = "ConfigurationManager." + key;
JButton jb = new JButton();
jb.setToolTipText(Messages.getString(key));
jb.setIcon(LGM.getIconForKey(key));
jb.setActionCommand(key);
jb.addActionListener(this);
return jb;
}
@Override
public void actionPerformed(ActionEvent ev)
{
String cmd = ev.getActionCommand();
VectorListModel<GameSettings> model = (VectorListModel<GameSettings>) configList.getModel();
if (cmd.endsWith("ADD")) {
GameSettings config = ProjectFile.createDefaultConfig();
int id = 0;
for (GameSettings cfg : LGM.currentFile.gameSettings) {
if (cfg.getName().startsWith("Configuration")) {
id++;
}
}
config.setName("Configuration" + id);
model.addElement(config);
configList.setSelectedValue(config,true);
LGM.configsCombo.updateUI();
} else if (cmd.endsWith("COPY")) {
GameSettings sel = configList.getSelectedValue();
if (sel == null) return;
GameSettings config = sel.clone();
int id = 0;
for (GameSettings cfg : LGM.currentFile.gameSettings) {
if (cfg.getName().startsWith("Configuration")) {
id++;
}
}
config.setName("Configuration" + id);
model.addElement(config);
configList.setSelectedValue(config,true);
LGM.configsCombo.updateUI();
} else if (cmd.endsWith("DELETE")) {
//Stop the user from deleting all configs, they must keep at least 1
List<GameSettings> selList = configList.getSelectedValuesList();
if (selList.size() >= model.getSize()) {
selList.remove(0);
}
model.removeAll(selList);
// Make sure the JCombo on the main toolbar wasn't selecting what we just deleted
if (LGM.configsCombo.getSelectedIndex() >= LGM.configsCombo.getItemCount() || LGM.configsCombo.getSelectedIndex() < 0) {
LGM.configsCombo.setSelectedIndex(0);
}
LGM.configsCombo.updateUI();
} else if (cmd.endsWith("EDIT_SETTINGS")) {
GameSettings sel = configList.getSelectedValue();
if (sel == null) return;
LGM.showGameSettings(sel);
} else if (cmd.endsWith("EDIT_CONSTANTS")) {
GameSettings sel = configList.getSelectedValue();
if (sel == null) return;
sel.constants.setName(sel.getName());
LGM.showConstantsFrame(sel.constants);
}
}
public void setConfigList(Vector<GameSettings> gameSettings)
{
vlm = new VectorListModel<GameSettings>(LGM.currentFile.gameSettings);
vlm.addListDataListener(new ListDataListener() {
@Override
public void contentsChanged(ListDataEvent arg0)
{
deleteButton.setEnabled(vlm.getSize() > 1);
}
@Override
public void intervalAdded(ListDataEvent arg0)
{
deleteButton.setEnabled(vlm.getSize() > 1);
}
@Override
public void intervalRemoved(ListDataEvent arg0)
{
deleteButton.setEnabled(vlm.getSize() > 1);
}
});
configList.setModel(vlm);
// check at least once
deleteButton.setEnabled(vlm.getSize() > 1);
}
}