package org.phenoscape.view;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.log4j.Logger;
import org.obo.app.swing.BugWorkaroundTable;
import org.obo.app.swing.PlaceholderRenderer;
import org.obo.app.swing.SortDisabler;
import org.obo.app.swing.TableColumnPrefsSaver;
import org.phenoscape.controller.PhenexController;
import org.phenoscape.model.Character;
import org.phenoscape.model.DataSet;
import org.phenoscape.util.ConsolidationUtil;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.gui.AdvancedTableFormat;
import ca.odell.glazedlists.gui.WritableTableFormat;
import ca.odell.glazedlists.swing.EventTableModel;
import ca.odell.glazedlists.swing.TableComparatorChooser;
import com.eekboom.utils.Strings;
public class CharacterTableComponent extends PhenoscapeGUIComponent {
private JButton addCharacterButton;
private JButton deleteCharacterButton;
public CharacterTableComponent(String id, PhenexController controller) {
super(id, controller);
}
@Override
public void init() {
super.init();
this.initializeInterface();
}
public void consolidateSelectedCharacters() {
//FIXME some of this logic should be moved down into the model
this.getController().getUndoController().beginCoalescingEdits("Consolidate Characters");
final List<Character> characters = Collections.unmodifiableList(this.getSelectedCharacters());
if (characters.size() > 1) {
ConsolidationUtil.consolidateCharacters(characters, this.getController().getDataSet());
}
this.getController().getUndoController().endCoalescingEdits();
}
private void initializeInterface() {
this.setLayout(new BorderLayout());
final EventTableModel<Character> charactersTableModel = new EventTableModel<Character>(this.getController().getSortedCharacters(), new CharactersTableFormat());
final JTable charactersTable = new BugWorkaroundTable(charactersTableModel);
charactersTable.setSelectionModel(this.getController().getCharactersSelectionModel());
charactersTable.setDefaultRenderer(Object.class, new PlaceholderRenderer("None"));
charactersTable.putClientProperty("Quaqua.Table.style", "striped");
new TableColumnPrefsSaver(charactersTable, this.getClass().getName());
final TableComparatorChooser<Character> sortChooser = new TableComparatorChooser<Character>(charactersTable, this.getController().getSortedCharacters(), false);
sortChooser.addSortActionListener(new SortDisabler());
this.add(new JScrollPane(charactersTable), BorderLayout.CENTER);
this.add(this.createToolBar(), BorderLayout.NORTH);
this.getController().getCharactersSelectionModel().addListSelectionListener(new CharacterSelectionListener());
}
private void addCharacter() {
this.getController().getDataSet().newCharacter();
}
private void deleteSelectedCharacter() {
final List<Character> characters = Collections.unmodifiableList(this.getSelectedCharacters());
final DataSet data = this.getController().getDataSet();
data.getCharacters().removeAll(characters);
}
private List<Character> getSelectedCharacters() {
return this.getController().getCharactersSelectionModel().getSelected();
}
private void updateButtonStates() {
this.deleteCharacterButton.setEnabled(!this.getSelectedCharacters().isEmpty());
}
private void selectFirstState() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (!getController().getStatesForCurrentCharacterSelection().isEmpty()) {
getController().getCurrentStatesSelectionModel().setSelectionInterval(0, 0);
}
}
});
}
private JToolBar createToolBar() {
final JToolBar toolBar = new JToolBar();
this.addCharacterButton = new JButton(new AbstractAction(null, new ImageIcon(this.getClass().getResource("/org/phenoscape/view/images/list-add.png"))) {
@Override
public void actionPerformed(ActionEvent e) {
addCharacter();
}
});
this.addCharacterButton.setToolTipText("Add Character");
toolBar.add(this.addCharacterButton);
this.deleteCharacterButton = new JButton(new AbstractAction(null, new ImageIcon(this.getClass().getResource("/org/phenoscape/view/images/list-remove.png"))) {
@Override
public void actionPerformed(ActionEvent e) {
deleteSelectedCharacter();
}
});
this.deleteCharacterButton.setToolTipText("Delete Character");
toolBar.add(this.deleteCharacterButton);
toolBar.setFloatable(false);
return toolBar;
}
private class CharactersTableFormat implements WritableTableFormat<Character>, AdvancedTableFormat<Character> {
@Override
public boolean isEditable(Character character, int column) {
return column != 0;
}
@Override
public Character setColumnValue(Character character, Object editedValue, int column) {
switch(column) {
case 0: break;
case 1: character.setLabel(editedValue.toString()); break;
case 2: character.setComment(editedValue.toString()); break;
case 3: character.setFigure(editedValue.toString()); break;
case 4: character.setDiscussion(editedValue.toString()); break;
}
return character;
}
@Override
public int getColumnCount() {
return 5;
}
@Override
public String getColumnName(int column) {
switch(column) {
case 0: return " ";
case 1: return "Character Description";
case 2: return "Comment";
case 3: return "Figure";
case 4: return "Discussion";
default: return null;
}
}
@Override
public Object getColumnValue(Character character, int column) {
switch(column) {
case 0: return getController().getDataSet().getCharacters().indexOf(character) + 1;
case 1: return character.getLabel();
case 2: return character.getComment();
case 3: return character.getFigure();
case 4: return character.getDiscussion();
default: return null;
}
}
@Override
public Class<?> getColumnClass(int column) {
switch(column) {
case 0: return Integer.class;
case 1: return String.class;
case 2: return String.class;
case 3: return String.class;
case 4: return String.class;
default: return null;
}
}
@Override
public Comparator<?> getColumnComparator(int column) {
switch(column) {
case 0: return GlazedLists.comparableComparator();
case 1: return Strings.getNaturalComparator();
case 2: return Strings.getNaturalComparator();
case 3: return Strings.getNaturalComparator();
case 4: return Strings.getNaturalComparator();
default: return null;
}
}
}
private class CharacterSelectionListener implements ListSelectionListener {
public CharacterSelectionListener() {
updateButtonStates();
}
@Override
public void valueChanged(ListSelectionEvent e) {
updateButtonStates();
selectFirstState();
}
}
@Override
protected Logger log() {
return Logger.getLogger(this.getClass());
}
}