/*
* (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.view.widget.browser;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Logger;
import javax.swing.Icon;
import org.openflexo.antar.binding.AbstractBinding;
import org.openflexo.antar.binding.AbstractBinding.BindingEvaluationContext;
import org.openflexo.antar.binding.BindingVariable;
import org.openflexo.fib.controller.FIBController;
import org.openflexo.fib.model.DataBinding;
import org.openflexo.fib.model.FIBAttributeNotification;
import org.openflexo.fib.model.FIBBrowser;
import org.openflexo.fib.model.FIBBrowserElement;
import org.openflexo.fib.model.FIBBrowserElement.FIBBrowserElementChildren;
import org.openflexo.fib.view.widget.FIBBrowserWidget;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.toolbox.ToolBox;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
public class FIBBrowserElementType implements BindingEvaluationContext, Observer {
private final class CastFunction implements Function<Object, Object>, BindingEvaluationContext {
private final FIBBrowserElementChildren children;
private Object child;
private CastFunction(FIBBrowserElementChildren children) {
this.children = children;
}
@Override
public synchronized Object apply(Object arg0) {
child = arg0;
try {
Object result = children.getCast().getBindingValue(this);
return result;
} finally {
child = null;
}
}
@Override
public Object getValue(BindingVariable variable) {
if (variable.getVariableName().equals("child")) {
return child;
} else {
return FIBBrowserElementType.this.getValue(variable);
}
}
}
private static final Logger logger = Logger.getLogger(FIBBrowserElementType.class.getPackage().getName());
private FIBBrowserModel fibBrowserModel;
private FIBBrowserElement browserElementDefinition;
private boolean isFiltered = false;
private FIBController controller;
public FIBBrowserElementType(FIBBrowserElement browserElementDefinition, FIBBrowserModel browserModel, FIBController controller) {
super();
this.controller = controller;
this.fibBrowserModel = browserModel;
this.browserElementDefinition = browserElementDefinition;
browserElementDefinition.addObserver(this);
}
public void delete() {
if (browserElementDefinition != null) {
browserElementDefinition.deleteObserver(this);
}
this.controller = null;
this.browserElementDefinition = null;
}
public FIBBrowserModel getBrowserModel() {
return fibBrowserModel;
}
@Override
public void update(Observable o, Object arg) {
if (arg instanceof FIBAttributeNotification && o == browserElementDefinition) {
FIBAttributeNotification dataModification = (FIBAttributeNotification) arg;
((FIBBrowserWidget) controller.viewForComponent(browserElementDefinition.getBrowser())).updateBrowser();
}
}
public FIBController getController() {
return controller;
}
public FIBBrowser getBrowser() {
return browserElementDefinition.getBrowser();
}
public String getLocalized(String key) {
return FlexoLocalization.localizedForKey(getController().getLocalizerForComponent(getBrowser()), key);
}
protected void setModel(FIBBrowserModel model) {
fibBrowserModel = model;
}
protected FIBBrowserModel getModel() {
return fibBrowserModel;
}
/*public Object elementAt(int row)
{
return fibBrowserModel.elementAt(row);
}*/
private void appendToDependingObjects(DataBinding binding, List<AbstractBinding> returned) {
if (binding.isSet()) {
returned.add(binding.getBinding());
}
}
public List<AbstractBinding> getDependencyBindings(final Object object) {
if (browserElementDefinition == null) {
return null;
}
iteratorObject = object;
List<AbstractBinding> returned = new ArrayList<AbstractBinding>();
appendToDependingObjects(browserElementDefinition.getLabel(), returned);
appendToDependingObjects(browserElementDefinition.getIcon(), returned);
appendToDependingObjects(browserElementDefinition.getTooltip(), returned);
appendToDependingObjects(browserElementDefinition.getEnabled(), returned);
appendToDependingObjects(browserElementDefinition.getVisible(), returned);
for (FIBBrowserElementChildren children : browserElementDefinition.getChildren()) {
appendToDependingObjects(children.getData(), returned);
appendToDependingObjects(children.getCast(), returned);
appendToDependingObjects(children.getVisible(), returned);
}
return returned;
}
public String getLabelFor(final Object object) {
if (browserElementDefinition == null) {
return "???" + object.toString();
}
if (browserElementDefinition.getLabel().isSet()) {
iteratorObject = object;
return (String) browserElementDefinition.getLabel().getBindingValue(this);
}
return object.toString();
}
public String getTooltipFor(final Object object) {
if (browserElementDefinition == null) {
return "???" + object.toString();
}
if (browserElementDefinition.getTooltip().isSet()) {
iteratorObject = object;
return (String) browserElementDefinition.getTooltip().getBindingValue(this);
}
return browserElementDefinition.getName();
}
public Icon getIconFor(final Object object) {
if (browserElementDefinition == null) {
return null;
}
if (browserElementDefinition.getIcon().isSet()) {
iteratorObject = object;
Object returned = browserElementDefinition.getIcon().getBindingValue(this);
if (returned instanceof Icon) {
return (Icon) returned;
}
return null;
} else {
return browserElementDefinition.getImageIcon();
}
}
public boolean isEnabled(final Object object) {
if (browserElementDefinition == null) {
return false;
}
if (browserElementDefinition.getEnabled().isSet()) {
iteratorObject = object;
Object enabledValue = browserElementDefinition.getEnabled().getBindingValue(this);
if (enabledValue != null) {
return (Boolean) enabledValue;
}
return true;
} else {
return true;
}
}
public boolean isVisible(final Object object) {
if (browserElementDefinition == null) {
return false;
}
if (isFiltered()) {
return false;
}
if (browserElementDefinition.getVisible().isSet()) {
iteratorObject = object;
return (Boolean) browserElementDefinition.getVisible().getBindingValue(this);
} else {
return true;
}
}
public List<Object> getChildrenFor(final Object object) {
if (browserElementDefinition == null) {
return Collections.EMPTY_LIST;
}
List<Object> returned = new ArrayList<Object>();
for (FIBBrowserElementChildren children : browserElementDefinition.getChildren()) {
if (children.isMultipleAccess()) {
// System.out.println("add all children for "+browserElementDefinition.getName()+" children "+children.getName()+" data="+children.getData());
// System.out.println("Obtain "+getChildrenListFor(children, object));
List<?> childrenObjects = getChildrenListFor(children, object);
// Might be null if some visibility was declared
if (childrenObjects != null) {
returned.addAll(childrenObjects);
}
// System.out.println("For " + object + " of " + object.getClass().getSimpleName() + " children=" + children.getData()
// + " values=" + object);
} else {
// System.out.println("add children for "+browserElementDefinition.getName()+" children "+children.getName()+" data="+children.getData());
// System.out.println("Obtain "+getChildrenFor(children, object));
// System.out.println("accessed type="+children.getAccessedType());
Object childrenObject = getChildrenFor(children, object);
// Might be null if some visibility was declared
if (childrenObject != null) {
returned.add(childrenObject);
}
// System.out.println("For " + object + " of " + object.getClass().getSimpleName() + " children=" + children.getData()
// + " value=" + childrenObject);
}
}
return returned;
}
protected Object getChildrenFor(FIBBrowserElementChildren children, final Object object) {
if (children.getData().isSet()) {
iteratorObject = object;
if (children.getVisible().isSet()) {
boolean visible = (Boolean) children.getVisible().getBindingValue(this);
if (!visible) {
// Finally we dont want to see it
return null;
}
}
Object result = children.getData().getBindingValue(this);
if (children.getCast().isSet()) {
return new CastFunction(children).apply(result);
}
return result;
} else {
return null;
}
}
protected List<?> getChildrenListFor(final FIBBrowserElementChildren children, final Object object) {
if (children.getData().isSet() && children.isMultipleAccess()) {
iteratorObject = object;
if (children.getVisible().isSet()) {
boolean visible = (Boolean) children.getVisible().getBindingValue(this);
if (!visible) {
// Finally we dont want to see it
return null;
}
}
Object bindingValue = children.getData().getBindingValue(this);
List<?> list = ToolBox.getListFromIterable(bindingValue);
if (list != null && children.getCast().isSet()) {
list = Lists.transform(list, new CastFunction(children));
}
return list;
} else {
return null;
}
}
public boolean isLabelEditable() {
return getBrowserElement().getIsEditable() && getBrowserElement().getEditableLabel().isSet()
&& getBrowserElement().getEditableLabel().getBinding().isSettable();
}
public synchronized String getEditableLabelFor(final Object object) {
if (isLabelEditable()) {
iteratorObject = object;
return (String) browserElementDefinition.getEditableLabel().getBindingValue(this);
}
return object.toString();
}
public synchronized void setEditableLabelFor(final Object object, String value) {
if (isLabelEditable()) {
iteratorObject = object;
browserElementDefinition.getEditableLabel().setBindingValue(value, this);
}
}
protected Object iteratorObject;
@Override
public synchronized Object getValue(BindingVariable variable) {
if (variable.getVariableName().equals(browserElementDefinition.getName())) {
return iteratorObject;
} else if (variable.getVariableName().equals("object")) {
return iteratorObject;
} else {
return getController().getValue(variable);
}
}
public FIBBrowserElement getBrowserElement() {
return browserElementDefinition;
}
public Font getFont(final Object object) {
if (browserElementDefinition.getDynamicFont().isSet()) {
iteratorObject = object;
Object returned = browserElementDefinition.getDynamicFont().getBindingValue(this);
if (returned instanceof Font) {
return (Font) returned;
}
}
if (getBrowserElement() != null) {
return getBrowserElement().retrieveValidFont();
}
return null;
}
public boolean isFiltered() {
return isFiltered;
}
public void setFiltered(boolean isFiltered) {
System.out.println("Element " + getBrowserElement().getName() + " filtered: " + isFiltered);
if (this.isFiltered != isFiltered) {
this.isFiltered = isFiltered;
// Later, try to implement a way to rebuild tree with same expanded nodes
fibBrowserModel.fireTreeRestructured();
}
}
}