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
a rapid overview
"+ "of your data.

You can click
on the headers to sort the columns,
"+ "and you can edit data
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 a=new ArrayList(); 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