package org.korsakow.ide.resources.widget;
import java.awt.Component;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import org.apache.log4j.Logger;
import org.korsakow.ide.util.UIUtil;
import org.korsakow.ide.util.Util;
/**
* An implementation of TableWidgetPropertiesEditor that uses pluggable PropertyHandlers (EditorModelHandler) to Render
* and Edit its cells.
*
* Most of the work of this class involves managing and delegating the handlers.
*
* @author d
*
*/
public class DefaultTableWidgetPropertiesEditor extends AbstractTableWidgetPropertiesEditor implements TableCellRenderer
{
protected HashMap<String, EditorModelHandler> propertyHandlerMap = new HashMap<String, EditorModelHandler>();
protected JLabel defaultEditor = new JLabel();
protected EditorModelHandler currentEditorHandler;
public DefaultTableWidgetPropertiesEditor(WidgetModel widget) {
this(Util.list(WidgetModel.class, widget));
}
public DefaultTableWidgetPropertiesEditor(Collection<WidgetModel> widgets) {
super(widgets);
table.getColumn(Column.NAME).setCellRenderer(new NameRenderer());
table.getColumn(Column.VALUE).setCellRenderer(this);
UIUtil.runUITaskLater(new Runnable() {
public void run() {
configureTableModel((DefaultTableModel)table.getModel());
}
});
}
protected void configureTableModel(DefaultTableModel model)
{
Set<String> ids = new TreeSet<String>();
// build list of common properties
for (WidgetModel widget : widgets)
ids.addAll(widget.getDynamicPropertyIds());
for (WidgetModel widget : widgets)
ids.retainAll(widget.getDynamicPropertyIds());
IDS:
for (String id : ids) {
Object value = widgets.isEmpty()?null:widgets.iterator().next().getDynamicProperty(id);
for (WidgetModel widget : widgets) {
if (widget.getWidgetEditor() instanceof DefaultTableWidgetPropertiesEditor) {
if (!((DefaultTableWidgetPropertiesEditor)widget.getWidgetEditor()).propertyHandlerMap.containsKey(id))
continue IDS;
}
Object o = widget.getDynamicProperty(id);
if (value != null && !value.equals(o)) {
value = null;
break;
}
}
model.addRow(new Object[] {id, value });
}
}
protected void addPropertyHandler(String propertyName, EditorModelHandler handler)
{
propertyHandlerMap.put(propertyName, handler);
}
protected EditorModelHandler getHandler(String propertyName)
{
EditorModelHandler handler = propertyHandlerMap.get(propertyName);
if (handler == null) {
try {
for (WidgetModel widget : widgets) {
if (widget.getWidgetEditor() instanceof DefaultTableWidgetPropertiesEditor) {
handler = ((DefaultTableWidgetPropertiesEditor)widget.getWidgetEditor()).propertyHandlerMap.get(propertyName);
if (handler != null)
break;
}
}
} catch (Exception e) {
// the below comment isn't clear. I wish I knew when to expect this.
Logger.getLogger(DefaultTableWidgetPropertiesEditor.class).error("couldn't get a handler for: " + propertyName, e);
// no registered editor, or unknown property
}
if (handler == null) {
Logger.getLogger(DefaultTableWidgetPropertiesEditor.class).error("", new Exception("No handler for: " + propertyName));
}
}
return handler;
}
@Override
protected void prepareEditor(int row, int column)
{
super.prepareEditor(row, column);
EditorModelHandler handler = getHandler(editingName);
if (handler != null) {
cellEditor.removeCellEditorListener(this); // otherwise we might get notifications during init that could stop editing prematurely
handler.initializeEditor(widgets, propertyEditor, editingName);
// the thing is... we still have our own listener on the table... it seems like we should give the handler
// a chance to be the one to notify and if it doesn't then we use our regular one.
// now we do both.
handler.removeEditorListener(this);
handler.addEditorListener(this); // when would be a good time to remove this listener?
cellEditor.addCellEditorListener(this);
}
currentEditorHandler = handler;
}
@Override
protected boolean commitPropertyChanges(String name, Object value)
{
if (currentEditorHandler != null) {
currentEditorHandler.commitProperty(widgets, editingName, value);
currentEditorHandler = null;
return true;
}
currentEditorHandler = null;
return false;
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
String name = (String)table.getValueAt(row, 0);
EditorModelHandler handler = getHandler(name);
if (handler != null)
return handler.getPropertyRenderer(name, value);
else {
defaultEditor.setText(value!=null?value.toString():null);
return defaultEditor;
}
}
}