/*******************************************************************************
* GenPlay, Einstein Genome Analyzer
* Copyright (C) 2009, 2014 Albert Einstein College of Medicine
*
* 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/>.
* Authors: Julien Lajugie <julien.lajugie@einstein.yu.edu>
* Nicolas Fourel <nicolas.fourel@einstein.yu.edu>
* Eric Bouhassira <eric.bouhassira@einstein.yu.edu>
*
* Website: <http://genplay.einstein.yu.edu>
******************************************************************************/
package edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.MGProperties.filterTable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.table.AbstractTableModel;
import edu.yu.einstein.genplay.gui.MGDisplaySettings.FiltersData;
/**
* @author Nicolas Fourel
*/
public class FilterTableModel extends AbstractTableModel {
/** Generated serial version ID */
private static final long serialVersionUID = 3478197435828366331L;
/** Name of the columns of the table */
protected static final String[] COLUMN_NAMES = {"Edit", "Layer", "ID", "Filter", "File"};
/** Index used for edit column */
protected static final int EDIT_BUTTON_INDEX = 0;
/** Index used for layer column */
protected static final int LAYER_INDEX = 1;
/** Index used for the vcf header id column */
protected static final int ID_INDEX = 2;
/** Index used for the filter column */
protected static final int FILTER_INDEX = 3;
/** Index used for vcf file column */
protected static final int VCF_FILE_INDEX = 4;
protected final String[] columnNames; // the table column names
protected List<FiltersData> data; // list of data
protected List<JButton> buttons; // list of buttons
private FiltersData currentData;
/**
* Constructor of {@link FilterTableModel}
*/
protected FilterTableModel () {
columnNames = COLUMN_NAMES;
data = new ArrayList<FiltersData>();
buttons = new ArrayList<JButton>();
currentData = null;
}
/**
* Add a row
* @param row row to insert
*/
protected void addRow (FiltersData row) {
data.add(row);
buttons.add(getNewButton());
fireTableRowsInserted(data.size() - 1, data.size() - 1);
}
/**
* Deletes a row
* @param row the row number
*/
protected void deleteRow(int row) {
data.remove(row);
buttons.remove(row);
fireTableRowsDeleted(row, row);
}
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
case VCF_FILE_INDEX:
return String.class;
case ID_INDEX:
return String.class;
case FILTER_INDEX:
return String.class;
case LAYER_INDEX:
return String.class;
default:
return Object.class;
}
}
@Override
public int getColumnCount() {
return columnNames.length;
}
/**
* @return the columnNames
*/
public String[] getColumnNames() {
return columnNames;
}
public FiltersData getCurrentData () {
return currentData;
}
/**
* @return the data
*/
protected List<FiltersData> getData() {
return data;
}
/**
* @return the index of the edit column
*/
protected int getEditColumnIndex () {
return EDIT_BUTTON_INDEX;
}
protected JButton getNewButton () {
JButton button = new JButton();
button.setText("e");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
JButton button = (JButton) arg0.getSource();
currentData = data.get(buttons.indexOf(button));
}
});
return button;
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public Object getValueAt(int row, int col) {
if (col == EDIT_BUTTON_INDEX) {
return buttons.get(row);
}
FiltersData filtersData = data.get(row);
switch (col) {
case VCF_FILE_INDEX:
return filtersData.getReaderForDisplay();
case ID_INDEX:
return filtersData.getIDForDisplay();
case FILTER_INDEX:
return filtersData.getFilterForDisplay();
case LAYER_INDEX:
return filtersData.getLayersForDisplay();
default:
return new Object();
}
}
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
/**
* This method moves (up or down) a list of row.
* @param list the list of row numbers to move
* @param toUp rows will be move up if true, down if false
*/
protected int[] move (int[] list, boolean toUp) {
int[] movedRows = new int[list.length];
int cpt = 0;
if (toUp) {
for (int i: list) {
movedRows[cpt] = moveDataUp(i);
cpt++;
}
} else {
int[] reversedList = reverseIntArray(list);
for (int i: reversedList) {
movedRows[cpt] = moveDataDown(i);
cpt++;
}
}
fireTableDataChanged();
return movedRows;
}
/**
* Move a data one step higher in the list in order to show it one row closer to the bottom of the table.
* @param index index of the row
*/
private int moveDataDown (int index) {
if (index < (data.size() - 1)) {
FiltersData dataToMove = data.get(index);
FiltersData dataToReplace = data.get(index + 1);
List<FiltersData> newDataList = new ArrayList<FiltersData>();
int currentIndex = 0;
while (currentIndex < data.size()){
FiltersData currentData = data.get(currentIndex);
if (currentData.equals(dataToMove)) {
newDataList.add(dataToReplace);
newDataList.add(dataToMove);
currentIndex++;
} else {
newDataList.add(currentData);
}
currentIndex++;
}
data = newDataList;
return (index + 1);
}
return index;
}
/**
* Move a data one step lower in the list in order to show it one row closer to the top of the table.
* @param index index of the row
*/
private int moveDataUp (int index) {
if (index > 0) {
FiltersData dataToMove = data.get(index);
FiltersData dataToReplace = data.get(index - 1);
List<FiltersData> newDataList = new ArrayList<FiltersData>();
int currentIndex = 0;
while (currentIndex < data.size()){
FiltersData currentData = data.get(currentIndex);
if (currentData.equals(dataToReplace)) {
newDataList.add(dataToMove);
newDataList.add(dataToReplace);
currentIndex++;
} else {
newDataList.add(currentData);
}
currentIndex++;
}
data = newDataList;
return (index - 1);
}
return index;
}
public void resetCurrentData () {
currentData = null;
}
/**
* Reverse an array: the last value becomes the firt one and so on.
* @param array array to reverse
* @return the reversed array
*/
private int[] reverseIntArray (int[] array) {
int[] newArray = new int[array.length];
for (int i = 0; i < newArray.length; i++) {
int index = array.length - 1 - i;
newArray[i] = array[index];
}
return newArray;
}
/**
* @param data the data to set
*/
protected void setData(List<FiltersData> data) {
this.data = data;
buttons = new ArrayList<JButton>();
for (int row = 0; row <data.size(); row++) {
buttons.add(getNewButton());
fireTableCellUpdated(row, VCF_FILE_INDEX);
fireTableCellUpdated(row, ID_INDEX);
fireTableCellUpdated(row, FILTER_INDEX);
fireTableCellUpdated(row, LAYER_INDEX);
fireTableCellUpdated(row, EDIT_BUTTON_INDEX);
}
}
}