/* * (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.inspector.model; import java.awt.Color; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.StringTokenizer; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Icon; import org.openflexo.inspector.AbstractController; import org.openflexo.inspector.InspectableObject; import org.openflexo.inspector.widget.propertylist.AbstractColumn; import org.openflexo.inspector.widget.propertylist.BooleanColumn; import org.openflexo.inspector.widget.propertylist.ColorColumn; import org.openflexo.inspector.widget.propertylist.CustomColumn; import org.openflexo.inspector.widget.propertylist.DropDownColumn; import org.openflexo.inspector.widget.propertylist.EditableStringColumn; import org.openflexo.inspector.widget.propertylist.IconColumn; import org.openflexo.inspector.widget.propertylist.IntegerColumn; import org.openflexo.inspector.widget.propertylist.StringColumn; import org.openflexo.kvc.KeyValueCoding; import org.openflexo.xmlcode.AccessorInvocationException; public class PropertyListColumn extends PropertyModel { static final Logger logger = Logger.getLogger(PropertyListColumn.class.getPackage().getName()); public static final String READ_ONLY_TEXT_FIELD = "READ_ONLY_TEXT_FIELD"; public static final String TEXT_FIELD = "TEXT_FIELD"; public static final String CHECKBOX = "CHECKBOX"; public static final String INTEGER = "INTEGER"; public static final String DROPDOWN = "DROPDOWN"; public static final String COLOR = "COLOR"; public static final String ICON = "ICON"; public static final String CUSTOM = "CUSTOM"; private Vector<String> availableWidgetValues; public Vector<String> getAvailableWidgetValues() { if (availableWidgetValues == null) { availableWidgetValues = new Vector<String>(); availableWidgetValues.add(READ_ONLY_TEXT_FIELD); availableWidgetValues.add(TEXT_FIELD); availableWidgetValues.add(CHECKBOX); availableWidgetValues.add(INTEGER); availableWidgetValues.add(DROPDOWN); availableWidgetValues.add(ICON); } return availableWidgetValues; } public static final int DEFAULT_COLUMN_WIDTH = 80; // public String name; // public String label; // public String widget; private AbstractColumn _tableColumn; private PropertyListModel _propertyListModel = null; public PropertyListColumn() { super(); _tableColumn = null; } public PropertyListModel getPropertyListModel() { return _propertyListModel; } public void setPropertyListModel(PropertyListModel propertyListModel) { _propertyListModel = propertyListModel; } public void notifyValueChangedFor(InspectableObject object) { // Override if required } public AbstractColumn getTableColumn(AbstractController controller) { if (_tableColumn == null) { if (getWidget().equals(READ_ONLY_TEXT_FIELD)) { _tableColumn = new StringColumn(label, getColumnWidth(), isResizable(), displayTitle(), font()) { @Override public String getValue(InspectableObject object) { Object cellValue = getCellValue(object); if (cellValue instanceof String) { return (String) cellValue; } else if (cellValue != null) { return cellValue.toString(); } else { return "null ???"; } } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(TEXT_FIELD)) { _tableColumn = new EditableStringColumn(label, getColumnWidth(), isResizable(), displayTitle(), font()) { @Override public String getValue(InspectableObject object) { Object cellValue = getCellValue(object); if (cellValue instanceof String) { return (String) cellValue; } else if (cellValue != null) { return cellValue.toString(); } else { return ""; } } @Override public boolean isCellEditableFor(InspectableObject object) { return isEditable(object); } @Override public void setValue(InspectableObject object, String aValue) { setCellValue(aValue, object); } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(CHECKBOX)) { _tableColumn = new BooleanColumn(label, getColumnWidth(), isResizable(), displayTitle()) { @Override public Boolean getValue(InspectableObject object) { return new Boolean(getBooleanCellValue(object)); } @Override public void setValue(InspectableObject object, Boolean aValue) { setBooleanCellValue(aValue.booleanValue(), object); } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(INTEGER)) { _tableColumn = new IntegerColumn(label, getColumnWidth(), isResizable(), displayTitle()) { @Override public Integer getValue(InspectableObject object) { return new Integer(getIntegerCellValue(object)); } @Override public void setValue(InspectableObject object, Integer aValue) { setIntegerCellValue(aValue.intValue(), object); } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(DROPDOWN)) { _tableColumn = new DropDownColumn(label, getColumnWidth()) { @Override public Object getValue(InspectableObject object) { // logger.info("getValue() for "+object+" return "+getCellValue(object)); return getCellValue(object); /* Object cellValue = getCellValue(object); if (cellValue instanceof String) { return (String) cellValue; } else if (cellValue != null) { return cellValue.toString(); } else { return null; }*/ } @Override public void setValue(InspectableObject object, Object aValue) { setCellValue(aValue, object); } @Override public String renderValue(Object object) { return getStringRepresentation(object); // return object.toString(); } @Override public List<?> getAvailableValues(InspectableObject object) { // logger.info("getAvailableValues() for "+object); // if (logger.isLoggable(Level.SEVERE)) // logger.severe("getAvailableValues() on a "+object+" hasDynList="+hasDynamicList()); if (hasDynamicList()) { return getDynamicList(object); } else if (hasStaticList()) { return getStaticList(); } else if (object.getTypeForKey(name) != null && object.getTypeForKey(name).isEnum()) { List<Object> returned = new ArrayList<Object>(); for (Object e : object.getTypeForKey(name).getEnumConstants()) { returned.add(e); } return returned; } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("There is an error in some configuration file :\n the property named '" + name + "' is supposed to be a list, but it doesn't hold any list definition!"); } return Collections.emptyList(); } } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(COLOR)) { _tableColumn = new ColorColumn(label, getColumnWidth(), isResizable(), displayTitle()) { @Override public Object getValue(InspectableObject object) { return getCellValue(object); } @Override public void setValue(InspectableObject object, Object aValue) { setCellValue(aValue, object); _colorCellEditor.setColor((Color) aValue); } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(ICON)) { _tableColumn = new IconColumn(label, getColumnWidth(), isResizable(), displayTitle()) { @Override public Icon getValue(InspectableObject object) { return (Icon) getCellValue(object); } @Override public void setValue(InspectableObject object, Icon aValue) { setCellValue(aValue, object); } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else if (getWidget().equals(CUSTOM)) { _tableColumn = new CustomColumn(this, label, getColumnWidth(), isResizable(), displayTitle(), controller) { @Override public void setValue(InspectableObject object, Object aValue) { // if (logger.isLoggable(Level.FINE)) // logger.fine("setCellValue() for property "+name+" and // object "+object+" with "+aValue); setCellValue(aValue, object); } @Override public Object getValue(InspectableObject object) { if (logger.isLoggable(Level.FINE)) { logger.fine("getCellValue() for property " + name + " and object " + object + " returns " + getCellValue(object)); } return getCellValue(object); } @Override public void notifyValueChangedFor(InspectableObject object) { super.notifyValueChangedFor(object); PropertyListColumn.this.notifyValueChangedFor(object); } }; } else { logger.warning("Unexpected widget type: " + getWidget()); } if (_tableColumn != null) { _tableColumn.setTooltipKey(getValueForParameter("tooltip")); } } return _tableColumn; } protected boolean modelUpdating = false; protected boolean widgetUpdating = false; protected boolean valueInError = false; /** * This method can be called to store the newValue in the model. * * @param newValue */ protected synchronized void setCellValue(Object newValue, InspectableObject object) { try { if (logger.isLoggable(Level.FINE)) { logger.fine("setCellValue() for property " + name + " with " + newValue); } KeyValueCoding target = getTargetObject(object); if (target != null) { target.setObjectForKey(newValue, getLastAccessor()); } } catch (AccessorInvocationException e) { valueInError = true; modelUpdating = false; /* * if (!getIn.handleException(object, name, newValue, e.getTargetException())) { // Revert to value defined in the model ! if * (logger.isLoggable(Level.INFO)) logger.info("Exception was NOT handled"); } else { if (logger.isLoggable(Level.INFO)) * logger.info("Exception was handled"); } */ valueInError = false; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("setCellValue() with " + newValue + " failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.printStackTrace(); } } public Object getCellValue(InspectableObject object) { try { if (object == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("model is null"); } return null; } KeyValueCoding target = getTargetObject(object); if (target != null) { return target.objectForKey(getLastAccessor()); } else { return null; } } catch (AccessorInvocationException e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("getCellValue() failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.getTargetException().printStackTrace(); return null; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("getObjectValue() failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.printStackTrace(); return null; } } protected synchronized void setBooleanCellValue(boolean value, InspectableObject object) { try { if (logger.isLoggable(Level.FINE)) { logger.fine("setBooleanCellValue() for property " + name + " with " + value); } KeyValueCoding target = getTargetObject(object); if (target != null) { target.setBooleanValueForKey(value, getLastAccessor()); } } catch (AccessorInvocationException e) { valueInError = true; modelUpdating = false; /* * if (!InspectorController.instance().handleException(object, name, new Boolean(value), e.getTargetException())) { // Revert to * value defined in the model ! if (logger.isLoggable(Level.INFO)) logger.info("Exception was NOT handled"); } else { if * (logger.isLoggable(Level.INFO)) logger.info("Exception was handled"); } */ valueInError = false; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("setBooleanCellValue() with " + value + " failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.printStackTrace(); } } protected synchronized boolean getBooleanCellValue(InspectableObject object) { try { if (object == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("model is null"); } return false; } KeyValueCoding target = getTargetObject(object); if (target != null) { return target.booleanValueForKey(getLastAccessor()); } else { return false; } } catch (AccessorInvocationException e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("getCellValue() failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.getTargetException().printStackTrace(); return false; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("getObjectValue() failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } return false; } } protected synchronized void setIntegerCellValue(int value, InspectableObject object) { try { if (logger.isLoggable(Level.FINE)) { logger.fine("setIntegerCellValue() for property " + name + " with " + value); } KeyValueCoding target = getTargetObject(object); if (target != null) { target.setIntegerValueForKey(value, getLastAccessor()); } } catch (AccessorInvocationException e) { valueInError = true; modelUpdating = false; /* * if (!InspectorController.instance().handleException(object, name, Integer.valueOf(value), e.getTargetException())) { // * Revert to value defined in the model ! if (logger.isLoggable(Level.INFO)) logger.info("Exception was NOT handled"); } else { * if (logger.isLoggable(Level.INFO)) logger.info("Exception was handled"); } */ valueInError = false; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("setIntegerCellValue() with " + value + " failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.printStackTrace(); } } protected synchronized int getIntegerCellValue(InspectableObject object) { try { if (object == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("model is null"); } return 0; } KeyValueCoding target = getTargetObject(object); if (target != null) { return target.integerValueForKey(getLastAccessor()); } else { return 0; } } catch (AccessorInvocationException e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("getCellValue() failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } e.getTargetException().printStackTrace(); return 0; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("getObjectValue() failed for property " + name + " for object " + object.getClass().getName() + " : exception " + e.getMessage()); } return 0; } } public KeyValueCoding getTargetObject(InspectableObject anObject) { KeyValueCoding object = anObject; String listAccessor = name; StringTokenizer strTok = new StringTokenizer(listAccessor, "."); String accessor; Object currentObject = object; while (strTok.hasMoreTokens() && currentObject != null && currentObject instanceof KeyValueCoding) { accessor = strTok.nextToken(); if (strTok.hasMoreTokens()) { if (currentObject != null) { currentObject = ((KeyValueCoding) currentObject).objectForKey(accessor); } } } if (currentObject instanceof KeyValueCoding) { return (KeyValueCoding) currentObject; } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not find target object for object=" + object + " listAccessor=" + listAccessor + ": must be a non-null KeyValueCoding object (getting " + currentObject + ")"); } return null; } } private String _lastAccessor; @Override public String getLastAccessor() { if (_lastAccessor == null) { String listAccessor = name; StringTokenizer strTok = new StringTokenizer(listAccessor, "."); String accessor = null; while (strTok.hasMoreTokens()) { accessor = strTok.nextToken(); } _lastAccessor = accessor; } return _lastAccessor; } public static final String COLUMN_WIDTH = "column_width"; public static final String RESIZABLE = "resizable"; public static final String DISPLAY_TITLE = "display_title"; public static final String FONT = "font"; public static final String FORMAT = "format"; public static final String DYNAMIC_LIST = "dynamiclist"; public int getColumnWidth() { if (hasValueForParameter(COLUMN_WIDTH)) { return getIntValueForParameter(COLUMN_WIDTH); } return DEFAULT_COLUMN_WIDTH; } public void setColumnWidth(int columnWidth) { setIntValueForParameter(COLUMN_WIDTH, columnWidth); } public boolean isResizable() { if (hasValueForParameter(RESIZABLE)) { return getBooleanValueForParameter(RESIZABLE); } return true; } public void setIsResizable(boolean isResizable) { setBooleanValueForParameter(RESIZABLE, isResizable); } public boolean displayTitle() { if (hasValueForParameter(DISPLAY_TITLE)) { return getBooleanValueForParameter(DISPLAY_TITLE); } return true; } public void setDisplayTitle(boolean displayTitle) { setBooleanValueForParameter(DISPLAY_TITLE, displayTitle); } public String getFormat() { if (hasValueForParameter(FORMAT)) { return getValueForParameter(FORMAT); } return null; } public void setFormat(String format) { setValueForParameter(FORMAT, format); } public String getDynamicList() { if (hasValueForParameter(DYNAMIC_LIST)) { return getValueForParameter(DYNAMIC_LIST); } return null; } public void setDynamicList(String format) { setValueForParameter(DYNAMIC_LIST, format); } public String font() { if (hasValueForParameter(FONT)) { return getValueForParameter(FONT); } return null; } public void setFont(String font) { setValueForParameter(FONT, font); } }