/*
 * Copyright (c) 2005-2007 Thomas Schuett, www.roboshock.de
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the Roboshock Public License.
 * A copy of this license is included in each distribution of this software
 * or any derived work.
 *
 */

package de.roboshock.gui.util.tablegui;

import java.awt.BorderLayout;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableColumnModel;

/**
 * This GUI window shows all analog sensors, as given in the
 * body configuration, and their current values as bars.
 */

public abstract class AbstractTablePanel<E> extends JPanel {
    protected JTable table;
    protected List<E> rows;
    protected JScrollPane scrollPane;
    private boolean dirty = true;
    
	public AbstractTablePanel() {
		// create Table
		// !!! do not change the instruction order !!!
		table = new JTable();
		rows = getRows();
		DefaultTableColumnModel columnModel = getColumnModel();
		table.setModel(getTableModel(columnModel));
		table.setColumnModel(columnModel);

		setLayout(new BorderLayout());
		add(scrollPane = new JScrollPane(table), BorderLayout.CENTER);
		
		JScrollBar vertical = scrollPane.getVerticalScrollBar();
		vertical.setValue( vertical.getMaximum() );

		// must be done in the concrete class 
		//EventBusService.subscribe(this);  // see @EventHandler annotated methods in here
	}
	
	protected abstract List<E> getRows();
	
	protected abstract RowBasedTableModel<E> getTableModel(DefaultTableColumnModel columnModel);

	protected abstract DefaultTableColumnModel getColumnModel();

	public abstract String getTableChangedEventName();

	public void setVisible(boolean b) {
		super.setVisible(b);
		if (b && dirty) {
			refreshTable();
		}
	}
	
	// @EventHandler not working here in abstract class, must be called from sub class
	public void updateTable() {
		if (isVisible()) {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					refreshTable();
				}
			});
		}
		else {
			dirty = true;
		}
	}

	@SuppressWarnings("unchecked")
	private void refreshTable() {
		rows = getRows();
		((RowBasedTableModel<E>)table.getModel()).setRows(rows);
		table.tableChanged(new TableModelEvent(table.getModel()));
		repaint();
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JScrollBar vertical = scrollPane.getVerticalScrollBar();
				vertical.setValue( vertical.getMaximum() );
			}
		});
		dirty = false;
	}
}
