/*
* Lilith - a log event viewer.
* Copyright (C) 2007-2011 Joern Huxhorn
*
* 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 de.huxhorn.lilith.swing.taskmanager.table;
import de.huxhorn.sulky.io.IOUtilities;
import de.huxhorn.sulky.swing.RowBasedTableModel;
import de.huxhorn.sulky.tasks.Task;
import de.huxhorn.sulky.tasks.TaskListener;
import de.huxhorn.sulky.tasks.TaskManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.swing.event.EventListenerList;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TaskTableModel<T>
implements RowBasedTableModel<Task<T>>
{
private final Logger logger = LoggerFactory.getLogger(TaskTableModel.class);
private final List<Task<T>> tasks;
private final EventListenerList eventListenerList;
private Comparator<Task<T>> taskComparator = new Comparator<Task<T>>()
{
public int compare(Task<T> task1, Task<T> task2)
{
return (int) (task1.getId() - task2.getId());
}
};
public static final int ID_INDEX = 0;
public static final int NAME_INDEX = 1;
public static final int PROGRESS_INDEX = 2;
private static final Class[] COLUMN_CLASSES =
{
Long.class,
String.class,
Integer.class,
};
private static final String[] COLUMN_NAMES =
{
"ID",
"Name",
"Progress",
};
private TaskManager<T> taskManager;
private boolean paused;
private TaskListener<T> taskListener;
public TaskTableModel(TaskManager<T> taskManager)
{
this.tasks = new ArrayList<>();
this.paused = true;
this.eventListenerList = new EventListenerList();
this.taskListener = new UpdateViewTaskListener();
setTaskManager(taskManager);
}
public Class<?> getColumnClass(int columnIndex)
{
if(columnIndex >= 0 && columnIndex < COLUMN_CLASSES.length)
{
return COLUMN_CLASSES[columnIndex];
}
return null;
}
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return false;
}
public Object getValueAt(int rowIndex, int columnIndex)
{
Task<T> task = getValueAt(rowIndex);
if(task == null)
{
return null;
}
switch(columnIndex)
{
case ID_INDEX:
return task.getId();
case NAME_INDEX:
return task.getName();
case PROGRESS_INDEX:
return task.getProgress();
}
return null;
}
public void setValueAt(Object o, int rowIndex, int columnIndex)
{
}
public void addTableModelListener(TableModelListener l)
{
synchronized(eventListenerList)
{
eventListenerList.add(TableModelListener.class, l);
}
}
public void removeTableModelListener(TableModelListener l)
{
synchronized(eventListenerList)
{
eventListenerList.remove(TableModelListener.class, l);
}
}
public int getRowCount()
{
return tasks.size();
}
public int getColumnCount()
{
return COLUMN_CLASSES.length;
}
public String getColumnName(int columnIndex)
{
if(columnIndex >= 0 && columnIndex < COLUMN_NAMES.length)
{
return COLUMN_NAMES[columnIndex];
}
return null;
}
public Task<T> getValueAt(int row)
{
logger.debug("getValueAt {}", row);
if(row >= 0 && row < tasks.size())
{
Task<T> result = tasks.get(row);
logger.debug("getValueAt {} result={}", result);
return result;
}
logger.debug("getValueAt {} is null!", row);
return null;
}
private void fireTableChanged(TableModelEvent event)
{
Object[] listeners;
synchronized(eventListenerList)
{
listeners = eventListenerList.getListenerList();
}
// Process the listeners last to first, notifying
// those that are interested in this event
for(int i = listeners.length - 2; i >= 0; i -= 2)
{
if(listeners[i] == TableModelListener.class)
{
TableModelListener listener = ((TableModelListener) listeners[i + 1]);
if(logger.isDebugEnabled())
{
logger.debug("Firing TableChange at {}.", listener.getClass().getName());
}
try
{
listener.tableChanged(event);
}
catch(Throwable ex)
{
if(logger.isWarnEnabled()) logger.warn("Exception while firing change!", ex);
IOUtilities.interruptIfNecessary(ex);
}
}
}
}
private void initTasks()
{
tasks.clear();
if(taskManager != null)
{
Map<Long, Task<T>> taskMap = taskManager.getTasks();
if(logger.isDebugEnabled()) logger.debug("initTasks: {}", taskMap);
for(Map.Entry<Long, Task<T>> current : taskMap.entrySet())
{
tasks.add(current.getValue());
Collections.sort(tasks, taskComparator);
}
}
fireTableChanged(new TableModelEvent(this));
}
private void clearTasks()
{
if(logger.isDebugEnabled()) logger.debug("clearTasks");
tasks.clear();
fireTableChanged(new TableModelEvent(this));
}
private void addTask(Task<T> task)
{
tasks.add(task);
int index = tasks.size() - 1;
fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
private void removeTask(Task<T> task)
{
int index = tasks.indexOf(task);
tasks.remove(index);
fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
}
private void updateTask(Task<T> task)
{
int index = tasks.indexOf(task);
fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE));
}
public boolean isPaused()
{
return paused;
}
public void setPaused(boolean paused)
{
if(this.paused != paused)
{
if(!paused)
{
initTasks();
}
else
{
clearTasks();
}
this.paused = paused;
}
}
public TaskManager<?> getTaskManager()
{
return taskManager;
}
public void setTaskManager(TaskManager<T> taskManager)
{
if(this.taskManager != null)
{
this.taskManager.removeTaskListener(taskListener);
}
this.taskManager = taskManager;
if(this.taskManager != null)
{
this.taskManager.addTaskListener(taskListener);
}
if(!paused)
{
initTasks();
}
else
{
clearTasks();
}
}
private class UpdateViewTaskListener
implements TaskListener<T>
{
public void taskCreated(Task<T> task)
{
if(!paused)
{
addTask(task);
}
}
public void executionFailed(Task<T> task, ExecutionException exception)
{
if(!paused)
{
removeTask(task);
}
}
public void executionFinished(Task<T> task, T result)
{
if(!paused)
{
removeTask(task);
}
}
public void executionCanceled(Task<T> task)
{
if(!paused)
{
removeTask(task);
}
}
public void progressUpdated(Task<T> task, int progress)
{
if(!paused)
{
updateTask(task);
}
}
}
}