/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.components.tabular.model;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import org.openflexo.foundation.FlexoModelObject;
/**
* Please comment this class
*
* @author sguerin
*
*/
public abstract class TextColumn<D extends FlexoModelObject> extends AbstractColumn<D, String> implements EditableColumn<D, String>,
HeightAdjustableColumn {
public TextColumn(String title, int defaultWidth) {
this(title, defaultWidth, true);
}
public TextColumn(String title, int defaultWidth, boolean isResizable) {
this(title, defaultWidth, isResizable, true);
}
public TextColumn(String title, int defaultWidth, boolean isResizable, boolean displayTitle) {
super(title, defaultWidth, isResizable, displayTitle);
_textCellEditor = new TextCellEditor();
_textCellRenderer = new TextCellRenderer();
_taForRow = new Vector();
}
@Override
public Class getValueClass() {
return String.class;
}
@Override
public String getValueFor(D object) {
return getValue(object);
}
public abstract String getValue(D object);
@Override
public boolean isCellEditableFor(D object) {
return true;
}
@Override
public void setValueFor(D object, String value) {
setValue(object, value);
}
public abstract void setValue(D object, String aValue);
@Override
public String toString() {
return "TextColumn " + "@" + Integer.toHexString(hashCode());
}
/**
* @return
*/
@Override
public TableCellRenderer getCellRenderer() {
return _textCellRenderer;
}
private TextCellRenderer _textCellRenderer;
protected class TextCellRenderer extends TabularViewCellRenderer {
/**
*
* Returns the selector cell renderer.
*
* @param table
* the <code>JTable</code>
* @param value
* the value to assign to the cell at <code>[row, column]</code>
* @param isSelected
* true if cell is selected
* @param hasFocus
* true if cell has focus
* @param row
* the row of the cell to render
* @param column
* the column of the cell to render
* @return the default table cell renderer
*/
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
TextColumnEditor returned = getEditorForRow(row);
setComponentBackground(returned.getTextArea(), hasFocus, isSelected, row, column);
returned.setText((String) value);
returned.setEditable(false);
return returned.getTextArea();
}
}
private Vector _taForRow;
protected TextColumnEditor getEditorForRow(int row) {
if (_taForRow.size() <= row) {
for (int i = _taForRow.size(); i <= row; i++) {
TextColumnEditor newEditor = new TextColumnEditor(i);
_taForRow.add(newEditor);
}
}
return (TextColumnEditor) _taForRow.elementAt(row);
}
protected class TextColumnEditor {
protected JTextArea _textArea;
private int _row;
private TextColumnDocumentListener _docListener;
protected int knownLC = 0;
protected TextColumnEditor(int row) {
_row = row;
_textArea = new JTextArea();
_textArea.setRows(1);
_textArea.setLineWrap(true);
_textArea.setWrapStyleWord(true);
_docListener = new TextColumnDocumentListener(_textArea, row);
_textArea.getDocument().addDocumentListener(_docListener);
}
public void setEditable(boolean b) {
_textArea.setEditable(b);
}
public void setText(String aText) {
_textArea.getDocument().removeDocumentListener(_docListener);
_textArea.setText(aText);
_textArea.getDocument().addDocumentListener(_docListener);
if (knownLC != _textArea.getLineCount()) {
knownLC = _textArea.getLineCount();
fireRowHeightChanged(_row);
}
knownLC = _textArea.getLineCount();
}
protected class TextColumnDocumentListener implements DocumentListener {
private int _row;
private JTextArea _textArea;
protected TextColumnDocumentListener(JTextArea textArea, int row) {
super();
_row = row;
_textArea = textArea;
}
@Override
public void insertUpdate(DocumentEvent e) {
textChanged(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
textChanged(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
textChanged(e);
}
private void textChanged(DocumentEvent e) {
// logger.fine("Text changed for row "+_row+" lc="+_textArea.getLineCount()+" row="+_textArea.getRows()+" height="+_textArea.getHeight());
if (knownLC != _textArea.getLineCount()) {
knownLC = _textArea.getLineCount();
fireRowHeightChanged(_row);
}
}
}
public JTextArea getTextArea() {
return _textArea;
}
public int getDesiredSize() {
return 16 * _textArea.getLineCount();
}
}
@Override
public boolean requireCellEditor() {
return true;
}
@Override
public TableCellEditor getCellEditor() {
return _textCellEditor;
}
private TextCellEditor _textCellEditor;
protected class TextCellEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
// protected Hashtable _taForObject;
protected JTextArea _currentTA;
public TextCellEditor() {
}
@Override
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
@Override
protected void fireEditingStopped() {
super.fireEditingStopped();
}
@Override
public Object getCellEditorValue() {
return _currentTA.getText();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
TextColumnEditor returned = getEditorForRow(row);
returned.setText((String) value);
returned.setEditable(true);
_currentTA = returned.getTextArea();
return returned.getTextArea();
}
}
private Vector _rowHeightListeners = new Vector();
@Override
public void addRowHeightListener(RowHeightListener rhl) {
_rowHeightListeners.add(rhl);
}
@Override
public void removeRowHeightListener(RowHeightListener rhl) {
_rowHeightListeners.remove(rhl);
}
@Override
public void fireRowHeightChanged(int row) {
// logger.fine("On change de nb de lignes !!!!! row="+row+" desired size is now "+getRowHeight(row));
if (getRowHeight(row) > 0) {
for (Enumeration en = _rowHeightListeners.elements(); en.hasMoreElements();) {
RowHeightListener next = (RowHeightListener) en.nextElement();
next.notifyRowHeightChanged(row, getRowHeight(row));
}
}
}
@Override
public int getRowHeight(int row) {
return getEditorForRow(row).getDesiredSize();
}
}