package timeflow.views;
import timeflow.app.ui.HtmlDisplay;
import timeflow.data.db.*;
import timeflow.data.time.*;
import timeflow.format.field.DateTimeGuesser;
import timeflow.model.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
import java.util.*;
public class TableView extends AbstractView {
private JTable table=new JTable();
private int colorColumn=-1, labelColumn=-1;
private Font font, bold;
private boolean editable=true;
private JPanel controls;
public TableView(TFModel model)
{
super(model);
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
table.setAutoCreateRowSorter(true);
font=model.getDisplay().plain();
bold=model.getDisplay().bold();
table.setFont(font);
final int fh=getFontMetrics(font).getHeight();
table.setRowHeight(fh+12);
table.setShowGrid(false);
table.getTableHeader().setPreferredSize(new Dimension(10, fh+15));
table.getTableHeader().setFont(font);
setReorderable(false);
setLayout(new GridLayout(1,1));
add(scrollPane);
controls=new HtmlControls("Use the table view for<br> a rapid overview<br> "+
"of your data. <p>You can click<br> on the headers to sort the columns,<br> "+
"and you can edit data<br> directly in the table cells.");
}
@Override
public JComponent _getControls()
{
return controls;
}
public void setEditable(boolean editable)
{
this.editable=editable;
}
public JTable getTable()
{
return table;
}
@Override
public void onscreen(boolean majorChange)
{
_note(null);
}
@Override
protected void _note(TFEvent e) {
setActs(getModel().getActs());
}
public void setActs(ActList acts)
{
TableModel t=new TimelineTableModel(acts);
table.setModel(t);
ActTableRenderer r=new ActTableRenderer(acts);
table.setDefaultRenderer(Object.class, r);
table.setDefaultRenderer(Double.class, r);
table.setDefaultEditor(String[].class, new StringArrayEditor());
table.setDefaultEditor(RoughTime.class, new RoughTimeEditor());
repaint();
}
@Override
public String getName() {
return "Table";
}
class ActTableRenderer extends DefaultTableCellRenderer {
ActList acts;
Color zebra=new Color(240,240,240);
boolean color=false;
Color dataColor;
ActTableRenderer(ActList acts)
{
this.acts=acts;
}
public void setValue(Object value) {
if (value==null)
{
super.setValue("");
return;
}
setHorizontalAlignment(value instanceof Double ? SwingConstants.RIGHT : SwingConstants.LEFT);
super.setValue(getModel().getDisplay().toString(value));
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
if (vColIndex==labelColumn || vColIndex==colorColumn)
setFont(bold);
else
setFont(font);
setBackground(rowIndex%2==0 ? Color.white : zebra);
color=vColIndex==colorColumn || vColIndex==labelColumn;
Field colorField=null;
if (color)
{
colorField=getModel().getColorField();
color &= colorField!=null;
}
if (color)
{
int actIndex=table.convertRowIndexToModel(rowIndex);
Act act=acts.get(actIndex);
if (colorField==null || colorField.getType()!=String.class)
dataColor=getModel().getDisplay().getColor("timeline.unspecified.color");
else
dataColor=getModel().getDisplay().makeColor(act.getString(colorField));
setForeground(dataColor);
setValue(value);
}
else
{
setForeground(Color.black);
setValue(value);
}
return this;
}
}
class TimelineTableModel implements TableModel
{
ActList acts;
Field[] fields;
TimelineTableModel(ActList acts)
{
this.acts=acts;
ArrayList<Field> a=new ArrayList<Field>();
int i=0;
Field colorField=getModel().getColorField();
Field labelField=getModel().getDB().getField(VirtualField.LABEL);
for (Field f:acts.getDB().getFields())
{
a.add(f);
if (f==colorField)
colorColumn=i;
if (f==labelField)
labelColumn=i;
i++;
}
fields=(Field[])a.toArray(new Field[0]);
}
@Override
public void addTableModelListener(TableModelListener l) {
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return fields[columnIndex].getType();
}
@Override
public int getColumnCount() {
return fields.length;
}
@Override
public String getColumnName(int columnIndex) {
return fields[columnIndex].getName();
}
@Override
public int getRowCount() {
return acts.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return acts.get(rowIndex).get(fields[columnIndex]);
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return editable;
}
@Override
public void removeTableModelListener(TableModelListener l) {
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
acts.get(rowIndex).set(fields[columnIndex], aValue);
getModel().noteRecordChange(TableView.this);
}
}
public class StringArrayEditor extends AbstractCellEditor implements TableCellEditor
{
JComponent component = new JTextField();
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int rowIndex, int vColIndex) {
((JTextField)component).setText(getModel().getDisplay().toString(value));
return component;
}
public Object getCellEditorValue()
{
String s= ((JTextField)component).getText();
String[] tags=s.split(",");
for (int i=0; i<tags.length; i++)
tags[i]=tags[i].trim();
return tags;
}
}
public class RoughTimeEditor extends AbstractCellEditor implements TableCellEditor
{
JComponent component = new JTextField();
DateTimeGuesser guesser=new DateTimeGuesser();
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int rowIndex, int vColIndex) {
RoughTime r=(RoughTime)value;
JTextField t=((JTextField)component);
t.setText(r==null ? "" : r.format());
return component;
}
public Object getCellEditorValue()
{
String s= ((JTextField)component).getText();
return s.trim().length()==0 ? null : guesser.guess(s);
}
}
public void setReorderable(boolean allow) {
table.getTableHeader().setReorderingAllowed(allow);
}
}