/*
* (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.fib.model;
import java.awt.Font;
import java.io.File;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.openflexo.antar.binding.Bindable;
import org.openflexo.antar.binding.BindingDefinition;
import org.openflexo.antar.binding.BindingDefinition.BindingDefinitionType;
import org.openflexo.antar.binding.BindingFactory;
import org.openflexo.antar.binding.BindingModel;
import org.openflexo.antar.binding.BindingVariableImpl;
import org.openflexo.antar.binding.TypeUtils;
import org.openflexo.fib.model.FIBBrowserAction.FIBAddAction;
import org.openflexo.fib.model.FIBBrowserAction.FIBCustomAction;
import org.openflexo.fib.model.FIBBrowserAction.FIBRemoveAction;
public class FIBBrowserElement extends FIBModelObject {
private static final Logger logger = Logger.getLogger(FIBBrowserElement.class.getPackage().getName());
private FIBBrowser browser;
public static enum Parameters implements FIBModelAttribute {
dataClass, label, icon, tooltip, enabled, visible, imageIconFile, isEditable, editableLabel, font, dynamicFont, filtered, defaultVisible, children, actions;
}
public static BindingDefinition LABEL = new BindingDefinition("label", String.class, BindingDefinitionType.GET, false);
public static BindingDefinition ICON = new BindingDefinition("icon", Icon.class, BindingDefinitionType.GET, false);
public static BindingDefinition TOOLTIP = new BindingDefinition("tooltip", String.class, BindingDefinitionType.GET, false);
public static BindingDefinition ENABLED = new BindingDefinition("enabled", Boolean.class, BindingDefinitionType.GET, false);
public static BindingDefinition VISIBLE = new BindingDefinition("visible", Boolean.class, BindingDefinitionType.GET, false);
public static BindingDefinition EDITABLE_LABEL = new BindingDefinition("editableLabel", String.class, BindingDefinitionType.GET_SET,
false);
public static BindingDefinition DYNAMIC_FONT = new BindingDefinition("dynamicFont", Font.class, BindingDefinitionType.GET, false);
private Class dataClass;
private DataBinding label;
private DataBinding icon;
private DataBinding tooltip;
private DataBinding enabled;
private DataBinding visible;
private DataBinding format;
private File imageIconFile;
private ImageIcon imageIcon;
private boolean isEditable = false;
private DataBinding editableLabel;
private DataBinding dynamicFont;
private boolean filtered = false;
private boolean defaultVisible = true;
private Font font;
private Vector<FIBBrowserAction> actions;
private Vector<FIBBrowserElementChildren> children;
private BindingModel actionBindingModel;
private FIBBrowserElementIterator iterator;
public FIBBrowserElement() {
iterator = new FIBBrowserElementIterator();
children = new Vector<FIBBrowserElementChildren>();
actions = new Vector<FIBBrowserAction>();
}
public FIBBrowser getBrowser() {
return browser;
}
public void setBrowser(FIBBrowser browser) {
this.browser = browser;
}
@Override
public FIBComponent getRootComponent() {
if (getBrowser() != null) {
return getBrowser().getRootComponent();
}
return null;
}
public DataBinding getLabel() {
if (label == null) {
label = new DataBinding(this, Parameters.label, LABEL);
}
return label;
}
public void setLabel(DataBinding label) {
label.setOwner(iterator);
label.setBindingAttribute(Parameters.label);
label.setBindingDefinition(LABEL);
this.label = label;
}
public DataBinding getIcon() {
if (icon == null) {
icon = new DataBinding(this, Parameters.icon, ICON);
}
return icon;
}
public void setIcon(DataBinding icon) {
icon.setOwner(iterator);
icon.setBindingAttribute(Parameters.icon);
icon.setBindingDefinition(ICON);
this.icon = icon;
}
public DataBinding getTooltip() {
if (tooltip == null) {
tooltip = new DataBinding(this, Parameters.tooltip, TOOLTIP);
}
return tooltip;
}
public void setTooltip(DataBinding tooltip) {
tooltip.setOwner(iterator);
tooltip.setBindingAttribute(Parameters.tooltip);
tooltip.setBindingDefinition(TOOLTIP);
this.tooltip = tooltip;
}
public DataBinding getEnabled() {
if (enabled == null) {
enabled = new DataBinding(this, Parameters.enabled, ENABLED);
}
return enabled;
}
public void setEnabled(DataBinding enabled) {
enabled.setOwner(iterator);
enabled.setBindingAttribute(Parameters.enabled);
enabled.setBindingDefinition(ENABLED);
this.enabled = enabled;
}
public DataBinding getVisible() {
if (visible == null) {
visible = new DataBinding(this, Parameters.visible, VISIBLE);
}
return visible;
}
public void setVisible(DataBinding visible) {
visible.setOwner(iterator);
visible.setBindingAttribute(Parameters.visible);
visible.setBindingDefinition(VISIBLE);
this.visible = visible;
}
public boolean getIsEditable() {
return isEditable;
}
public void setIsEditable(boolean isEditable) {
FIBAttributeNotification<Boolean> notification = requireChange(Parameters.isEditable, isEditable);
if (notification != null) {
this.isEditable = isEditable;
hasChanged(notification);
}
}
public DataBinding getEditableLabel() {
if (editableLabel == null) {
editableLabel = new DataBinding(this, Parameters.editableLabel, EDITABLE_LABEL);
}
return editableLabel;
}
public void setEditableLabel(DataBinding editableLabel) {
editableLabel.setOwner(iterator);
editableLabel.setBindingAttribute(Parameters.editableLabel);
editableLabel.setBindingDefinition(EDITABLE_LABEL);
this.editableLabel = editableLabel;
}
public boolean getFiltered() {
return filtered;
}
public void setFiltered(boolean filtered) {
FIBAttributeNotification<Boolean> notification = requireChange(Parameters.filtered, filtered);
if (notification != null) {
this.filtered = filtered;
hasChanged(notification);
}
}
public boolean getDefaultVisible() {
return defaultVisible;
}
public void setDefaultVisible(boolean defaultVisible) {
FIBAttributeNotification<Boolean> notification = requireChange(Parameters.defaultVisible, defaultVisible);
if (notification != null) {
this.defaultVisible = defaultVisible;
hasChanged(notification);
}
}
public void finalizeBrowserDeserialization() {
logger.fine("finalizeBrowserDeserialization() for FIBBrowserElement " + dataClass);
if (label != null) {
label.finalizeDeserialization();
}
if (icon != null) {
icon.finalizeDeserialization();
}
if (tooltip != null) {
tooltip.finalizeDeserialization();
}
if (enabled != null) {
enabled.finalizeDeserialization();
}
if (visible != null) {
visible.finalizeDeserialization();
}
if (editableLabel != null) {
editableLabel.finalizeDeserialization();
}
for (FIBBrowserElementChildren c : children) {
c.finalizeBrowserDeserialization();
}
}
@Override
public BindingModel getBindingModel() {
if (getBrowser() != null) {
return getBrowser().getBindingModel();
}
return null;
}
public BindingModel getActionBindingModel() {
if (actionBindingModel == null) {
createActionBindingModel();
}
return actionBindingModel;
}
private void createActionBindingModel() {
actionBindingModel = new BindingModel(getBindingModel());
actionBindingModel.addToBindingVariables(new BindingVariableImpl(this, "selected", getDataClass()));
// System.out.println("dataClass="+getDataClass()+" dataClassName="+dataClassName);
// logger.info("******** Table: "+getName()+" Add BindingVariable: iterator type="+getIteratorClass());
}
public void notifiedBindingModelRecreated() {
createActionBindingModel();
}
public Font retrieveValidFont() {
if (font == null && getBrowser() != null) {
return getBrowser().retrieveValidFont();
}
return getFont();
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
FIBAttributeNotification<Font> notification = requireChange(Parameters.font, font);
if (notification != null) {
this.font = font;
hasChanged(notification);
}
}
public boolean getHasSpecificFont() {
return getFont() != null;
}
public void setHasSpecificFont(boolean aFlag) {
if (aFlag) {
setFont(retrieveValidFont());
} else {
setFont(null);
}
}
public DataBinding getDynamicFont() {
if (dynamicFont == null) {
dynamicFont = new DataBinding(this, Parameters.dynamicFont, DYNAMIC_FONT);
}
return dynamicFont;
}
public void setDynamicFont(DataBinding dynamicFont) {
if (dynamicFont != null) {
dynamicFont.setOwner(iterator);
dynamicFont.setBindingAttribute(Parameters.dynamicFont);
dynamicFont.setBindingDefinition(DYNAMIC_FONT);
}
this.dynamicFont = dynamicFont;
}
public File getImageIconFile() {
return imageIconFile;
}
public void setImageIconFile(File imageIconFile) {
FIBAttributeNotification<File> notification = requireChange(Parameters.imageIconFile, imageIconFile);
if (notification != null) {
this.imageIconFile = imageIconFile;
this.imageIcon = new ImageIcon(imageIconFile.getAbsolutePath());
hasChanged(notification);
}
}
public ImageIcon getImageIcon() {
return imageIcon;
}
public FIBBrowserElementIterator getIterator() {
return iterator;
}
private class FIBBrowserElementIterator extends FIBModelObject implements Bindable {
private BindingModel iteratorBindingModel = null;
@Override
public BindingModel getBindingModel() {
if (iteratorBindingModel == null) {
createFormatterBindingModel();
}
return iteratorBindingModel;
}
private void createFormatterBindingModel() {
iteratorBindingModel = new BindingModel(FIBBrowserElement.this.getBindingModel());
iteratorBindingModel.addToBindingVariables(new BindingVariableImpl<Object>(this, "object", Object.class) {
@Override
public Type getType() {
return getDataClass();
}
@Override
public String getVariableName() {
return FIBBrowserElement.this.getName();
}
});
}
@Override
public FIBComponent getRootComponent() {
return FIBBrowserElement.this.getRootComponent();
}
@Override
public List<? extends FIBModelObject> getEmbeddedObjects() {
return null;
}
}
public Class getDataClass() {
if (dataClass == null && getBrowser() != null) {
return getBrowser().getIteratorClass();
}
return dataClass;
}
public void setDataClass(Class dataClass) {
FIBAttributeNotification<Class> notification = requireChange(Parameters.dataClass, dataClass);
if (notification != null) {
this.dataClass = dataClass;
hasChanged(notification);
}
}
public Vector<FIBBrowserAction> getActions() {
return actions;
}
public void setActions(Vector<FIBBrowserAction> actions) {
this.actions = actions;
}
public void addToActions(FIBBrowserAction anAction) {
logger.fine("Add to actions " + anAction);
anAction.setBrowserElement(this);
actions.add(anAction);
setChanged();
notifyObservers(new FIBAddingNotification<FIBBrowserAction>(Parameters.actions, anAction));
}
public void removeFromActions(FIBBrowserAction anAction) {
anAction.setBrowserElement(null);
actions.remove(anAction);
setChanged();
notifyObservers(new FIBRemovingNotification<FIBBrowserAction>(Parameters.actions, anAction));
}
public FIBAddAction createAddAction() {
FIBAddAction newAction = new FIBAddAction();
newAction.setName("add_action");
addToActions(newAction);
return newAction;
}
public FIBRemoveAction createRemoveAction() {
FIBRemoveAction newAction = new FIBRemoveAction();
newAction.setName("delete_action");
addToActions(newAction);
return newAction;
}
public FIBCustomAction createCustomAction() {
FIBCustomAction newAction = new FIBCustomAction();
newAction.setName("custom_action");
addToActions(newAction);
return newAction;
}
public FIBBrowserAction deleteAction(FIBBrowserAction actionToDelete) {
logger.info("Called deleteAction() with " + actionToDelete);
removeFromActions(actionToDelete);
return actionToDelete;
}
public Vector<FIBBrowserElementChildren> getChildren() {
return children;
}
public void setChildren(Vector<FIBBrowserElementChildren> children) {
this.children = children;
}
public void addToChildren(FIBBrowserElementChildren aChildren) {
aChildren.setBrowserElement(this);
children.add(aChildren);
setChanged();
notifyObservers(new FIBAddingNotification<FIBBrowserElementChildren>(Parameters.children, aChildren));
}
public void removeFromChildren(FIBBrowserElementChildren aChildren) {
aChildren.setBrowserElement(null);
children.remove(aChildren);
setChanged();
notifyObservers(new FIBRemovingNotification<FIBBrowserElementChildren>(Parameters.children, aChildren));
}
public FIBBrowserElementChildren createChildren() {
logger.info("Called createChildren()");
FIBBrowserElementChildren newChildren = new FIBBrowserElementChildren();
newChildren.setName("children" + (children.size() > 0 ? children.size() : ""));
addToChildren(newChildren);
return newChildren;
}
public FIBBrowserElementChildren deleteChildren(FIBBrowserElementChildren elementToDelete) {
logger.info("Called elementToDelete() with " + elementToDelete);
removeFromChildren(elementToDelete);
return elementToDelete;
}
public void moveToTop(FIBBrowserElementChildren e) {
if (e == null) {
return;
}
children.remove(e);
children.insertElementAt(e, 0);
setChanged();
notifyObservers(new FIBAddingNotification<FIBBrowserElementChildren>(Parameters.children, e));
}
public void moveUp(FIBBrowserElementChildren e) {
if (e == null) {
return;
}
int index = children.indexOf(e);
children.remove(e);
children.insertElementAt(e, index - 1);
setChanged();
notifyObservers(new FIBAddingNotification<FIBBrowserElementChildren>(Parameters.children, e));
}
public void moveDown(FIBBrowserElementChildren e) {
if (e == null) {
return;
}
int index = children.indexOf(e);
children.remove(e);
children.insertElementAt(e, index + 1);
setChanged();
notifyObservers(new FIBAddingNotification<FIBBrowserElementChildren>(Parameters.children, e));
}
public void moveToBottom(FIBBrowserElementChildren e) {
if (e == null) {
return;
}
children.remove(e);
children.add(e);
setChanged();
notifyObservers(new FIBAddingNotification<FIBBrowserElementChildren>(Parameters.children, e));
}
public static class FIBBrowserElementChildren extends FIBModelObject {
private FIBBrowserElement browserElement;
private DataBinding data;
private DataBinding visible;
private DataBinding cast;
private FIBChildBindable childBindable;
public static BindingDefinition DATA = new BindingDefinition("data", Object.class, BindingDefinitionType.GET, false);
public static BindingDefinition VISIBLE = new BindingDefinition("visible", Boolean.class, BindingDefinitionType.GET, false);
public static BindingDefinition CAST = new BindingDefinition("cast", Object.class, BindingDefinitionType.GET, false);
private class FIBChildBindable extends FIBModelObject implements Bindable {
private BindingModel childBindingModel = null;
@Override
public BindingFactory getBindingFactory() {
return FIBBrowserElementChildren.this.getBindingFactory();
}
@Override
public BindingModel getBindingModel() {
if (childBindingModel == null) {
createChildBindingModel();
}
return childBindingModel;
}
private void createChildBindingModel() {
childBindingModel = new BindingModel(FIBBrowserElementChildren.this.getBindingModel());
childBindingModel.addToBindingVariables(new BindingVariableImpl<Object>(this, "child", Object.class) {
@Override
public Type getType() {
if (getData().isSet()) {
Type type = getData().getBinding().getAccessedType();
if (isSupportedListType(type)) {
if (type instanceof ParameterizedType) {
return ((ParameterizedType) type).getActualTypeArguments()[0];
}
logger.warning("Found supported list type " + type
+ " but it is not parameterized so I can't guess its content");
return Object.class;
}
return type;
}
return Object.class;
}
});
}
@Override
public FIBComponent getRootComponent() {
return browserElement.getRootComponent();
}
@Override
public List<? extends FIBModelObject> getEmbeddedObjects() {
return null;
}
}
public static enum Parameters implements FIBModelAttribute {
data, visible, cast;
}
public FIBBrowserElementChildren() {
}
public FIBChildBindable getChildBindable() {
if (childBindable == null) {
childBindable = new FIBChildBindable();
}
return childBindable;
}
public FIBBrowser getBrowser() {
return getBrowserElement().getBrowser();
}
public DataBinding getData() {
if (data == null) {
data = new DataBinding(this, Parameters.data, DATA);
}
return data;
}
public void setData(DataBinding data) {
data.setOwner(browserElement != null ? browserElement.getIterator() : null);
data.setBindingAttribute(Parameters.data);
data.setBindingDefinition(DATA);
this.data = data;
}
public DataBinding getVisible() {
if (visible == null) {
visible = new DataBinding(this, Parameters.visible, VISIBLE);
}
return visible;
}
public void setVisible(DataBinding visible) {
visible.setOwner(browserElement != null ? browserElement.getIterator() : null);
visible.setBindingAttribute(Parameters.visible);
visible.setBindingDefinition(VISIBLE);
this.visible = visible;
}
public DataBinding getCast() {
if (cast == null) {
cast = new DataBinding(getChildBindable(), Parameters.cast, CAST);
}
return cast;
}
public void setCast(DataBinding cast) {
cast.setOwner(getChildBindable());
cast.setBindingAttribute(Parameters.cast);
cast.setBindingDefinition(CAST);
this.cast = cast;
}
public FIBBrowserElement getBrowserElement() {
return browserElement;
}
public void setBrowserElement(FIBBrowserElement browserElement) {
this.browserElement = browserElement;
}
@Override
public FIBComponent getRootComponent() {
if (getBrowserElement() != null) {
return getBrowserElement().getRootComponent();
}
return null;
}
public void finalizeBrowserDeserialization() {
logger.fine("finalizeBrowserDeserialization() for FIBBrowserElementChildren ");
if (data != null) {
data.setOwner(browserElement.getIterator());
data.setBindingAttribute(Parameters.data);
data.finalizeDeserialization();
}
if (visible != null) {
visible.setOwner(browserElement.getIterator());
visible.setBindingAttribute(Parameters.visible);
visible.finalizeDeserialization();
}
}
public Type getAccessedType() {
if (data != null && data.isSet()) {
return data.getBinding().getAccessedType();
}
return null;
}
public boolean isMultipleAccess() {
/*System.out.println("This="+this);
System.out.println("getAccessedType()="+getAccessedType());
System.out.println("TypeUtils.isClassAncestorOf(List.class, TypeUtils.getBaseClass(accessedType))="+TypeUtils.isClassAncestorOf(List.class, TypeUtils.getBaseClass(getAccessedType())));
System.out.println("accessedType instanceof ParameterizedType="+(getAccessedType() instanceof ParameterizedType));
System.out.println("((ParameterizedType)accessedType).getActualTypeArguments().length > 0="+(((ParameterizedType)getAccessedType()).getActualTypeArguments().length > 0));*/
Type accessedType = getAccessedType();
if (accessedType == null) {
return false;
}
return isSupportedListType(accessedType);
}
private boolean isSupportedListType(Type accessedType) {
return TypeUtils.isClassAncestorOf(Iterable.class, TypeUtils.getBaseClass(accessedType))
|| TypeUtils.isClassAncestorOf(Enumeration.class, TypeUtils.getBaseClass(accessedType));
}
@Override
public List<? extends FIBModelObject> getEmbeddedObjects() {
return null;
}
}
@Override
public List<? extends FIBModelObject> getEmbeddedObjects() {
return null;
}
}