/*
* (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.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.logging.Logger;
import javax.swing.ScrollPaneConstants;
import javax.swing.tree.TreeNode;
import org.openflexo.antar.binding.BindingDefinition;
import org.openflexo.antar.binding.BindingDefinition.BindingDefinitionType;
import org.openflexo.antar.binding.BindingModel;
import org.openflexo.antar.binding.BindingVariableImpl;
import org.openflexo.antar.binding.ParameterizedTypeImpl;
import org.openflexo.fib.controller.FIBComponentDynamicModel;
import org.openflexo.fib.controller.FIBController;
import org.openflexo.fib.model.validation.FixProposal;
import org.openflexo.fib.model.validation.ValidationIssue;
import org.openflexo.fib.model.validation.ValidationReport;
import org.openflexo.fib.model.validation.ValidationRule;
import org.openflexo.fib.model.validation.ValidationWarning;
import org.openflexo.fib.view.FIBView;
import org.openflexo.localization.LocalizedDelegate;
import org.openflexo.toolbox.StringUtils;
public abstract class FIBComponent extends FIBModelObject implements TreeNode {
private static final Logger logger = Logger.getLogger(FIBComponent.class.getPackage().getName());
public static Color DISABLED_COLOR = Color.GRAY;
public static BindingDefinition VISIBLE = new BindingDefinition("visible", Boolean.class, BindingDefinitionType.GET, false);
private BindingDefinition DATA;
private String definitionFile;
private Date lastModified;
public BindingDefinition getDataBindingDefinition() {
if (DATA == null) {
DATA = new BindingDefinition("data", getDefaultDataClass(), BindingDefinitionType.GET, false);
}
return DATA;
}
public static enum Parameters implements FIBModelAttribute {
index,
data,
visible,
dataClass,
controllerClass,
font,
opaque,
backgroundColor,
foregroundColor,
width,
height,
minWidth,
minHeight,
maxWidth,
maxHeight,
useScrollBar,
horizontalScrollbarPolicy,
verticalScrollbarPolicy,
constraints,
explicitDependancies
}
public static enum VerticalScrollBarPolicy {
VERTICAL_SCROLLBAR_AS_NEEDED {
@Override
public int getPolicy() {
return ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
}
},
VERTICAL_SCROLLBAR_NEVER {
@Override
public int getPolicy() {
return ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER;
}
},
VERTICAL_SCROLLBAR_ALWAYS {
@Override
public int getPolicy() {
return ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
}
};
public abstract int getPolicy();
}
public static enum HorizontalScrollBarPolicy {
HORIZONTAL_SCROLLBAR_AS_NEEDED {
@Override
public int getPolicy() {
return ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
}
},
HORIZONTAL_SCROLLBAR_NEVER {
@Override
public int getPolicy() {
return ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;
}
},
HORIZONTAL_SCROLLBAR_ALWAYS {
@Override
public int getPolicy() {
return ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
}
};
public abstract int getPolicy();
}
private Integer index;
private DataBinding data;
private DataBinding visible;
private Font font;
private Boolean opaque;
private Color backgroundColor;
private Color foregroundColor;
private Integer width;
private Integer height;
private Integer minWidth;
private Integer minHeight;
private Integer maxWidth;
private Integer maxHeight;
private boolean useScrollBar = false;
private HorizontalScrollBarPolicy horizontalScrollbarPolicy = null;
private VerticalScrollBarPolicy verticalScrollbarPolicy = null;
// private String dataClassName;
private final Vector<FIBComponent> mayDepends;
private final Vector<FIBComponent> mayAlters;
private Class dataClass;
private Class<? extends FIBController> controllerClass;
private FIBContainer parent;
public FIBComponent() {
super();
explicitDependancies = new Vector<FIBDependancy>();
mayDepends = new Vector<FIBComponent>();
mayAlters = new Vector<FIBComponent>();
}
@Override
public void delete() {
logger.info("//////////// DELETE " + this);
if (getParent() != null) {
getParent().removeFromSubComponents(this);
}
super.delete();
}
public void setParent(FIBContainer parent) {
this.parent = parent;
}
@Override
public FIBContainer getParent() {
return parent;
}
/**
* Return a boolean indicating if hierarchy is valid (no cycle was detected in hierarchy)
*
* @return
*/
private boolean hasValidHierarchy() {
List<FIBComponent> ancestors = new Vector<FIBComponent>();
FIBComponent c = this;
while (c != null) {
if (ancestors.contains(c)) {
return false;
}
ancestors.add(c);
c = c.getParent();
}
return true;
}
/*public Hashtable<String,String> getLayoutConstraints()
{
return layoutConstraints;
}
public String getConstraint(String constraint)
{
return layoutConstraints.get(constraint);
}
public boolean getBooleanConstraint(String constraint)
{
return layoutConstraints.get(constraint) != null && layoutConstraints.get(constraint).equalsIgnoreCase("true");
}
public String _getConstraints()
{
if (layoutConstraints.size() == 0) return null;
StringBuffer returned = new StringBuffer();
boolean isFirst = true;
for (String key : layoutConstraints.keySet()) {
String value = layoutConstraints.get(key);
returned.append((isFirst?"":";")+key+"="+value);
isFirst = false;
}
return returned.toString();
}
public void _setConstraints(String someConstraints)
{
StringTokenizer st = new StringTokenizer(someConstraints,";");
while (st.hasMoreTokens()) {
String next = st.nextToken();
StringTokenizer st2 = new StringTokenizer(next,"=");
String key = null;
String value = null;
if (st2.hasMoreTokens()) key = st2.nextToken();
if (st2.hasMoreTokens()) value = st2.nextToken();
if (key != null && value != null) {
layoutConstraints.put(key,value);
}
}
}
*/
private ComponentConstraints constraints;
public ComponentConstraints getConstraints() {
constraints = _normalizeConstraintsWhenRequired(constraints);
return constraints;
}
public void setConstraints(ComponentConstraints someConstraints) {
// ComponentConstraints normalizedConstraints = constraints;
ComponentConstraints normalizedConstraints = _normalizeConstraintsWhenRequired(someConstraints);
FIBAttributeNotification<ComponentConstraints> notification = requireChange(Parameters.constraints, normalizedConstraints);
if (notification != null) {
normalizedConstraints.setComponent(this);
this.constraints = normalizedConstraints;
hasChanged(notification);
}
}
private ComponentConstraints _normalizeConstraintsWhenRequired(ComponentConstraints someConstraints) {
if (getParent() instanceof FIBSplitPanel) {
if (someConstraints == null) {
SplitLayoutConstraints returned = new SplitLayoutConstraints(((FIBSplitPanel) getParent()).getFirstEmptyPlaceHolder());
returned.setComponent(this);
return returned;
}
if (!(someConstraints instanceof SplitLayoutConstraints)) {
return new SplitLayoutConstraints(someConstraints);
}
someConstraints.setComponent(this);
return someConstraints;
} else if (getParent() instanceof FIBPanel) {
// Init to default value when relevant but null
if (someConstraints == null) {
ComponentConstraints returned;
switch (((FIBPanel) getParent()).getLayout()) {
case none:
returned = new NoneLayoutConstraints();
break;
case flow:
returned = new FlowLayoutConstraints();
break;
case grid:
returned = new GridLayoutConstraints();
break;
case box:
returned = new BoxLayoutConstraints();
break;
case border:
returned = new BorderLayoutConstraints();
break;
case twocols:
returned = new TwoColsLayoutConstraints();
break;
case gridbag:
returned = new GridBagLayoutConstraints();
break;
default:
returned = new NoneLayoutConstraints();
break;
}
returned.setComponent(this);
return returned;
}
// Mutate to right type when necessary
switch (((FIBPanel) getParent()).getLayout()) {
case none:
if (!(someConstraints instanceof NoneLayoutConstraints)) {
return new NoneLayoutConstraints(someConstraints);
}
break;
case flow:
if (!(someConstraints instanceof FlowLayoutConstraints)) {
return new FlowLayoutConstraints(someConstraints);
}
break;
case grid:
if (!(someConstraints instanceof GridLayoutConstraints)) {
return new GridLayoutConstraints(someConstraints);
}
break;
case box:
if (!(someConstraints instanceof BoxLayoutConstraints)) {
return new BoxLayoutConstraints(someConstraints);
}
break;
case border:
if (!(someConstraints instanceof BorderLayoutConstraints)) {
return new BorderLayoutConstraints(someConstraints);
}
break;
case twocols:
if (!(someConstraints instanceof TwoColsLayoutConstraints)) {
return new TwoColsLayoutConstraints(someConstraints);
}
break;
case gridbag:
if (!(someConstraints instanceof GridBagLayoutConstraints)) {
return new GridBagLayoutConstraints(someConstraints);
}
break;
default:
}
someConstraints.setComponent(this);
return someConstraints;
} else {
// No constraints for a component which container is not custom layouted
return someConstraints;
}
}
/*public String _getConditional()
{
return conditional;
}
public void _setConditional(String conditional)
{
this.conditional = conditional;
DefaultExpressionParser parser = new DefaultExpressionParser();
Vector<Variable> variables;
try {
conditionalExpression = parser.parse(conditional);
variables = Expression.extractVariables(conditional);
System.out.println("Variables for "+conditional+"\n"+variables);
} catch (ParseException e) {
e.printStackTrace();
} catch (TypeMismatchException e) {
e.printStackTrace();
}
}
public boolean isConditional()
{
return conditional != null;
}
public boolean evaluateCondition(final Object dataObject)
{
if (dataObject == null) return false;
try {
Expression returned = conditionalExpression.evaluate(
new EvaluationContext(
new ExpressionParser.DefaultConstantFactory(),
new VariableFactory() {
public Expression makeVariable(Word value) {
Object valueObject = FIBKeyValueCoder.getObjectValue(dataObject,value.getValue());
if (valueObject instanceof String) {
return new Constant.StringConstant((String)valueObject);
}
else if (valueObject instanceof Enum) {
return new Constant.EnumConstant(((Enum)valueObject).name());
}
else if (valueObject instanceof Integer) {
return new Constant.IntegerConstant((Integer)valueObject);
}
else if (valueObject instanceof Long) {
return new Constant.IntegerConstant((Long)valueObject);
}
else if (valueObject instanceof Short) {
return new Constant.IntegerConstant((Short)valueObject);
}
else if (valueObject instanceof Float) {
return new Constant.FloatConstant((Float)valueObject);
}
else if (valueObject instanceof Double) {
return new Constant.FloatConstant((Double)valueObject);
}
else if (valueObject instanceof Boolean) {
return ((Boolean)valueObject ? Constant.BooleanConstant.TRUE : Constant.BooleanConstant.FALSE);
}
// TODO Handle others
return new Variable(value.getValue());
}
},
new ExpressionParser.DefaultFunctionFactory()));
System.out.println("After evaluation: "+returned+" of "+returned.getClass().getName());
if (returned instanceof BooleanConstant) return ((BooleanConstant)returned).getValue();
logger.warning("Could not evaluate: "+conditional+" found: "+returned);
return true;
}
catch (TypeMismatchException e) {
e.printStackTrace();
logger.warning("TypeMismatch: "+e.getMessage());
}
return true;
}*/
public boolean isRootComponent() {
return getParent() == null;
}
@Override
public FIBComponent getRootComponent() {
FIBComponent current = this;
while (current != null && !current.isRootComponent()) {
current = current.getParent();
}
return current;
}
protected BindingModel _bindingModel = null;
@Override
public BindingModel getBindingModel() {
if (isRootComponent()) {
if (_bindingModel == null) {
createBindingModel();
}
return _bindingModel;
} else {
return super.getBindingModel();
}
}
public void updateBindingModel() {
if (deserializationPerformed) {
logger.fine("updateBindingModel()");
if (getRootComponent() != null) {
getRootComponent()._bindingModel = null;
getRootComponent().createBindingModel();
}
}
}
/**
* Creates binding variable identified by "data"<br>
* Default behavior is to generate a binding variable with the java type identified by data class
*/
protected void createDataBindingVariable() {
_bindingModel.addToBindingVariables(new BindingVariableImpl(this, "data", dataClass != null ? dataClass : Object.class));
}
protected void createBindingModel() {
_bindingModel = new BindingModel();
/*Class dataClass = null;
try {
if (dataClassName != null) {
dataClass = Class.forName(dataClassName);
logger.fine("Found: "+dataClassName);
}
} catch (ClassNotFoundException e) {
logger.warning("Not found: "+dataClassName);
}*/
// if (dataClass == null) dataClass = Object.class;
createDataBindingVariable();
if (StringUtils.isNotEmpty(getName()) && getDynamicAccessType() != null) {
_bindingModel.addToBindingVariables(new BindingVariableImpl(this, getName(), getDynamicAccessType()));
}
Iterator<FIBComponent> it = subComponentIterator();
while (it.hasNext()) {
FIBComponent subComponent = it.next();
if (StringUtils.isNotEmpty(subComponent.getName()) && subComponent.getDynamicAccessType() != null) {
_bindingModel.addToBindingVariables(new BindingVariableImpl(this, subComponent.getName(), subComponent
.getDynamicAccessType()));
}
}
Class myControllerClass = getControllerClass();
if (myControllerClass == null) {
myControllerClass = FIBController.class;
}
_bindingModel.addToBindingVariables(new BindingVariableImpl(this, "controller", myControllerClass));
it = subComponentIterator();
while (it.hasNext()) {
FIBComponent subComponent = it.next();
subComponent.notifiedBindingModelRecreated();
}
// logger.info("Created binding model at root component level:\n"+_bindingModel);
}
public void notifiedBindingModelRecreated() {
}
protected boolean deserializationPerformed = true;
@Override
public void initializeDeserialization() {
super.initializeDeserialization();
deserializationPerformed = false;
}
@Override
public void finalizeDeserialization() {
// System.out.println("finalizeDeserialization for "+this+" isRoot="+isRootComponent());
super.finalizeDeserialization();
deserializationPerformed = true;
if (getRootComponent().getBindingModel() == null) {
getRootComponent().createBindingModel();
}
if (isRootComponent()) {
updateBindingModel();
}
if (data != null) {
data.finalizeDeserialization();
}
if (visible != null) {
visible.finalizeDeserialization();
}
/*if (conditional != null) {
Vector<Variable> variables;
try {
variables = Expression.extractVariables(conditional);
//System.out.println("Variables for "+conditional+"\n"+variables);
Iterator<FIBComponent> subComponents = getRootComponent().subComponentIterator();
while (subComponents.hasNext()) {
FIBComponent next = subComponents.next();
if (next != this) {
if (next instanceof FIBWidget && ((FIBWidget)next).getData() != null) {
String data = ((FIBWidget)next).getData().toString();
if (data != null) {
for (Variable v : variables) {
if (v.getName().startsWith(data) || data.startsWith(v.getName())) {
mayDepends.add(next);
next.mayAlters.add(this);
logger.info("Component "+this+" depends of "+next);
}
}
}
}
}
}
} catch (ParseException e) {
e.printStackTrace();
} catch (TypeMismatchException e) {
e.printStackTrace();
}
}*/
}
public Vector<FIBComponent> getNamedComponents() {
Vector<FIBComponent> returned = new Vector<FIBComponent>();
for (FIBComponent c : retrieveAllSubComponents()) {
if (StringUtils.isNotEmpty(c.getName())) {
returned.add(c);
}
}
return returned;
}
public FIBComponent getComponentNamed(String name) {
for (FIBComponent c : retrieveAllSubComponents()) {
if (StringUtils.isNotEmpty(c.getName()) && c.getName().equals(name)) {
return c;
}
}
return null;
}
public Vector<FIBComponent> retrieveAllSubComponents() {
if (this instanceof FIBContainer) {
Vector<FIBComponent> returned = new Vector<FIBComponent>();
addAllSubComponents((FIBContainer) this, returned);
return returned;
}
return null;
}
private void addAllSubComponents(FIBContainer c, Vector<FIBComponent> returned) {
for (FIBComponent c2 : c.getSubComponents()) {
returned.add(c2);
if (c2 instanceof FIBContainer) {
addAllSubComponents((FIBContainer) c2, returned);
}
}
}
public Iterator<FIBComponent> subComponentIterator() {
Vector<FIBComponent> allSubComponents = retrieveAllSubComponents();
if (allSubComponents == null) {
return new Iterator<FIBComponent>() {
@Override
public boolean hasNext() {
return false;
}
@Override
public FIBComponent next() {
return null;
}
@Override
public void remove() {
}
};
} else {
return allSubComponents.iterator();
}
}
public Vector<FIBComponent> getMayDepends() {
return mayDepends;
}
public Iterator<FIBComponent> getMayDependsIterator() {
return new ArrayList<FIBComponent>(mayDepends).iterator();
}
public Iterator<FIBComponent> getMayAltersIterator() {
return new ArrayList<FIBComponent>(mayAlters).iterator();
}
public void declareDependantOf(FIBComponent aComponent) /*throws DependancyLoopException*/{
// logger.info("Component "+this+" depends of "+aComponent);
if (aComponent == this) {
logger.warning("Forbidden reflexive dependencies");
return;
}
// Look if this dependancy may cause a loop in dependancies
/*try {
Vector<FIBComponent> dependancies = new Vector<FIBComponent>();
dependancies.add(aComponent);
searchLoopInDependenciesWith(aComponent, dependancies);
} catch (DependencyLoopException e) {
logger.warning("Forbidden loop in dependencies: " + e.getMessage());
throw e;
}*/
if (!mayDepends.contains(aComponent)) {
mayDepends.add(aComponent);
logger.fine("Component " + this + " depends of " + aComponent);
}
if (!aComponent.mayAlters.contains(this)) {
aComponent.mayAlters.add(this);
}
}
/*private void searchLoopInDependanciesWith(FIBComponent aComponent, Vector<FIBComponent> dependancies) throws DependancyLoopException {
for (FIBComponent c : aComponent.mayDepends) {
if (c == this) {
throw new DependencyLoopException(dependencies);
}
Vector<FIBComponent> newVector = new Vector<FIBComponent>();
newVector.addAll(dependencies);
newVector.add(c);
searchLoopInDependenciesWith(c, newVector);
}
}*/
/*protected static class DependancyLoopException extends Exception {
private final Vector<FIBComponent> dependancies;
public DependencyLoopException(Vector<FIBComponent> dependancies) {
this.dependencies = dependancies;
}
@Override
public String getMessage() {
return "DependencyLoopException: " + dependencies;
}
}*/
public Integer getIndex() {
if (index == null) {
if (getConstraints() != null && getConstraints().hasIndex()) {
return getConstraints().getIndex();
}
}
return index;
}
public void setIndex(Integer index) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.index, index);
if (notification != null) {
this.index = index;
hasChanged(notification);
if (getParent() != null) {
getParent().reorderComponents();
}
}
}
public DataBinding getData() {
if (data == null) {
data = new DataBinding(this, Parameters.data, getDataBindingDefinition());
}
return data;
}
public void setData(DataBinding data) {
if (data != null) {
data.setOwner(this);
data.setBindingAttribute(Parameters.data);
data.setBindingDefinition(getDataBindingDefinition());
}
this.data = data;
}
public DataBinding getVisible() {
if (visible == null) {
visible = new DataBinding(this, Parameters.visible, VISIBLE);
}
return visible;
}
public void setVisible(DataBinding visible) {
if (visible != null) {
visible.setOwner(this);
visible.setBindingAttribute(Parameters.visible);
visible.setBindingDefinition(VISIBLE);
}
this.visible = visible;
}
@Override
public String toString() {
return getClass().getSimpleName() + " (" + (getName() != null ? getName() : getIdentifier() != null ? getIdentifier() : "unnamed")
+ ")";
}
public abstract String getIdentifier();
public Type getDataType() {
if (dataClass == null) {
return Object.class;
}
return dataClass;
/*if (dataClassName == null) return null;
if (dataClass == null) {
try {
dataClass = Class.forName(dataClassName);
} catch (ClassNotFoundException e) {
logger.warning("Not found: "+dataClassName);
dataClass = Object.class;
}
}
return dataClass;*/
}
public Class<?> getDataClass() {
return dataClass;
}
@SuppressWarnings("rawtypes")
public void setDataClass(Class<?> dataClass) {
FIBAttributeNotification<Class> notification = requireChange(Parameters.dataClass, (Class) dataClass);
if (notification != null) {
this.dataClass = dataClass;
updateBindingModel();
hasChanged(notification);
}
}
public Class<? extends FIBController> getControllerClass() {
return controllerClass;
}
public void setControllerClass(Class<? extends FIBController> controllerClass) {
FIBAttributeNotification<Class> notification = requireChange(Parameters.controllerClass, (Class) controllerClass);
if (notification != null) {
this.controllerClass = controllerClass;
updateBindingModel();
hasChanged(notification);
}
}
public Type getDefaultDataClass() {
return Object.class;
}
// Default behaviour: only data is managed
public Type getDynamicAccessType() {
if (data != null) {
Type[] args = new Type[1];
args[0] = getDataType();
return new ParameterizedTypeImpl(FIBComponentDynamicModel.class, args);
}
return null;
}
public void clearParameters() {
getParameters().clear();
}
public final Font retrieveValidFont() {
if (font == null) {
if (!isRootComponent() && hasValidHierarchy()) {
return getParent().retrieveValidFont();
} else {
return null; // Use system default
}
}
return getFont();
}
public final Color retrieveValidForegroundColor() {
if (foregroundColor == null) {
if (!isRootComponent() && hasValidHierarchy()) {
return getParent().retrieveValidForegroundColor();
} else {
return null; // Use default
}
}
return getForegroundColor();
}
public final Color retrieveValidBackgroundColor() {
if (backgroundColor == null) {
if (!isRootComponent() && hasValidHierarchy()) {
return getParent().retrieveValidBackgroundColor();
} else {
return null; // Use system default
}
}
return getBackgroundColor();
}
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 getOpaque() {
return opaque;
}
public void setOpaque(Boolean opaque) {
FIBAttributeNotification<Boolean> notification = requireChange(Parameters.opaque, opaque);
if (notification != null) {
this.opaque = opaque;
hasChanged(notification);
}
}
public Color getBackgroundColor() {
return backgroundColor;
}
public void setBackgroundColor(Color backgroundColor) {
FIBAttributeNotification<Color> notification = requireChange(Parameters.backgroundColor, backgroundColor);
if (notification != null) {
this.backgroundColor = backgroundColor;
hasChanged(notification);
}
}
public Color getForegroundColor() {
return foregroundColor;
}
public void setForegroundColor(Color foregroundColor) {
FIBAttributeNotification<Color> notification = requireChange(Parameters.foregroundColor, foregroundColor);
if (notification != null) {
this.foregroundColor = foregroundColor;
hasChanged(notification);
}
}
public boolean getUseScrollBar() {
return useScrollBar;
}
public void setUseScrollBar(boolean useScrollBar) {
FIBAttributeNotification<Boolean> notification = requireChange(Parameters.useScrollBar, useScrollBar);
if (notification != null) {
this.useScrollBar = useScrollBar;
if (useScrollBar) {
horizontalScrollbarPolicy = HorizontalScrollBarPolicy.HORIZONTAL_SCROLLBAR_AS_NEEDED;
verticalScrollbarPolicy = VerticalScrollBarPolicy.VERTICAL_SCROLLBAR_AS_NEEDED;
} else {
horizontalScrollbarPolicy = null;
verticalScrollbarPolicy = null;
}
hasChanged(notification);
}
}
public HorizontalScrollBarPolicy getHorizontalScrollbarPolicy() {
return horizontalScrollbarPolicy;
}
public void setHorizontalScrollbarPolicy(HorizontalScrollBarPolicy horizontalScrollbarPolicy) {
FIBAttributeNotification<HorizontalScrollBarPolicy> notification = requireChange(Parameters.horizontalScrollbarPolicy,
horizontalScrollbarPolicy);
if (notification != null) {
this.horizontalScrollbarPolicy = horizontalScrollbarPolicy;
hasChanged(notification);
}
}
public VerticalScrollBarPolicy getVerticalScrollbarPolicy() {
return verticalScrollbarPolicy;
}
public void setVerticalScrollbarPolicy(VerticalScrollBarPolicy verticalScrollbarPolicy) {
FIBAttributeNotification<VerticalScrollBarPolicy> notification = requireChange(Parameters.verticalScrollbarPolicy,
verticalScrollbarPolicy);
if (notification != null) {
this.verticalScrollbarPolicy = verticalScrollbarPolicy;
hasChanged(notification);
}
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.width, width);
if (notification != null) {
this.width = width;
hasChanged(notification);
}
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.height, height);
if (notification != null) {
this.height = height;
hasChanged(notification);
}
}
public Integer getMinWidth() {
return minWidth;
}
public void setMinWidth(Integer minWidth) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.minWidth, minWidth);
if (notification != null) {
this.minWidth = minWidth;
hasChanged(notification);
}
}
public Integer getMinHeight() {
return minHeight;
}
public void setMinHeight(Integer minHeight) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.minHeight, minHeight);
if (notification != null) {
this.minHeight = minHeight;
hasChanged(notification);
}
}
public Integer getMaxWidth() {
return maxWidth;
}
public void setMaxWidth(Integer maxWidth) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.maxWidth, maxWidth);
if (notification != null) {
this.maxWidth = maxWidth;
hasChanged(notification);
}
}
public Integer getMaxHeight() {
return maxHeight;
}
public void setMaxHeight(Integer maxHeight) {
FIBAttributeNotification<Integer> notification = requireChange(Parameters.maxHeight, maxHeight);
if (notification != null) {
this.maxHeight = maxHeight;
hasChanged(notification);
}
}
@Override
public void setName(String name) {
if (StringUtils.isEmpty(name)) {
name = null;
}
super.setName(name);
updateBindingModel();
}
@Override
public void addToParameters(FIBParameter p) {
// Little hask to recover previously created fib
if (p.getName().equals("controllerClassName")) {
try {
Class<?> myControllerClass = Class.forName(p.getValue());
if (FIBController.class.isAssignableFrom(myControllerClass)) {
setControllerClass((Class<? extends FIBController>) myControllerClass);
}
} catch (ClassNotFoundException e) {
logger.warning("Could not find class " + p.getValue());
}
} else {
super.addToParameters(p);
updateBindingModel();
}
}
public boolean definePreferredDimensions() {
return width != null && height != null;
}
public void setDefinePreferredDimensions(boolean definePreferredDimensions) {
if (definePreferredDimensions) {
FIBView<?, ?> v = FIBController.makeView(this, (LocalizedDelegate) null);
Dimension p = v.getJComponent().getPreferredSize();
setWidth(p.width);
setHeight(p.height);
v.delete();
} else {
setWidth(null);
setHeight(null);
}
}
public boolean defineMaxDimensions() {
return maxWidth != null && maxHeight != null;
}
public void setDefineMaxDimensions(boolean defineMaxDimensions) {
if (defineMaxDimensions) {
FIBView<?, ?> v = FIBController.makeView(this, (LocalizedDelegate) null);
setMaxWidth(1024);
setMaxHeight(1024);
v.delete();
} else {
setMaxWidth(null);
setMaxHeight(null);
}
}
public boolean defineMinDimensions() {
return minWidth != null && minHeight != null;
}
public void setDefineMinDimensions(boolean defineMinDimensions) {
if (defineMinDimensions) {
FIBView<?, ?> v = FIBController.makeView(this, (LocalizedDelegate) null);
Dimension p = v.getJComponent().getMinimumSize();
setMinWidth(p.width);
setMinHeight(p.height);
v.delete();
} else {
setMinWidth(null);
setMinHeight(null);
}
}
private Vector<FIBDependancy> explicitDependancies;
// private Vector<FIBComponentDependancy> componentDependancies;
/*public Vector<FIBComponentDependancy> getComponentDependancies()
{
if (componentDependancies == null) {
componentDependancies = new Vector<FIBComponentDependancy>();
for (Iterator<FIBComponent> it=getMayDependsIterator(); it.hasNext();) {
componentDependancies.add(new DynamicFIBDependancy(this,it.next()));
}
componentDependancies.addAll(explicitDependancies);
}
return componentDependancies;
}*/
public Vector<FIBDependancy> getExplicitDependancies() {
return explicitDependancies;
}
public void setExplicitDependancies(Vector<FIBDependancy> explicitDependancies) {
FIBAttributeNotification<Vector<FIBDependancy>> notification = requireChange(Parameters.explicitDependancies, explicitDependancies);
explicitDependancies = null;
if (notification != null) {
this.explicitDependancies = explicitDependancies;
hasChanged(notification);
}
}
public void addToExplicitDependancies(FIBDependancy p) {
p.setOwner(this);
explicitDependancies.add(p);
if (p.getMasterComponent() != null) {
// try {
p.getOwner().declareDependantOf(p.getMasterComponent());
/*} catch (DependancyLoopException e) {
logger.warning("DependancyLoopException raised while applying explicit dependancy for " + p.getOwner() + " and "
+ p.getMasterComponent() + " message: " + e.getMessage());
}*/
}
// componentDependancies = null;
setChanged();
notifyObservers(new FIBAddingNotification<FIBDependancy>(Parameters.explicitDependancies, p));
}
public void removeFromExplicitDependancies(FIBDependancy p) {
p.setOwner(null);
explicitDependancies.remove(p);
// componentDependancies = null;
setChanged();
notifyObservers(new FIBRemovingNotification<FIBDependancy>(Parameters.explicitDependancies, p));
}
public FIBDependancy createNewExplicitDependancy() {
FIBDependancy returned = new FIBDependancy();
addToExplicitDependancies(returned);
return returned;
}
public void deleteExplicitDependancy(FIBDependancy p) {
removeFromExplicitDependancies(p);
}
private FIBLocalizedDictionary localizedDictionary;
public FIBLocalizedDictionary retrieveFIBLocalizedDictionary() {
if (getLocalizedDictionary() == null) {
setLocalizedDictionary(new FIBLocalizedDictionary());
}
return getLocalizedDictionary();
}
public void setLocalizedDictionary(FIBLocalizedDictionary localizedDictionary) {
if (localizedDictionary != null) {
localizedDictionary.setComponent(this);
}
this.localizedDictionary = localizedDictionary;
}
public FIBLocalizedDictionary getLocalizedDictionary() {
return localizedDictionary;
}
public String getDefinitionFile() {
return definitionFile;
}
public void setDefinitionFile(String definitionFile) {
this.definitionFile = definitionFile;
}
public List<FIBButton> getDefaultButtons() {
List<FIBButton> defaultButtons = new ArrayList<FIBButton>();
if (this instanceof FIBContainer) {
List<FIBButton> buttons = getFIBButtons(((FIBContainer) this).getSubComponents());
if (buttons.size() > 0) {
for (FIBButton b : buttons) {
if (b.isDefault() != null && b.isDefault()) {
defaultButtons.add(b);
}
}
}
}
return defaultButtons;
}
private List<FIBButton> getFIBButtons(List<FIBComponent> subComponents) {
List<FIBButton> buttons = new ArrayList<FIBButton>();
for (FIBComponent c : subComponents) {
if (c instanceof FIBButton) {
buttons.add((FIBButton) c);
} else if (c instanceof FIBContainer) {
buttons.addAll(getFIBButtons(((FIBContainer) c).getSubComponents()));
}
}
return buttons;
}
@Override
protected void applyValidation(ValidationReport report) {
super.applyValidation(report);
performValidation(RootComponentShouldHaveDataClass.class, report);
performValidation(DataBindingMustBeValid.class, report);
performValidation(VisibleBindingMustBeValid.class, report);
performValidation(NonRootComponentShouldNotHaveLocalizedDictionary.class, report);
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public static class RootComponentShouldHaveDataClass extends ValidationRule<RootComponentShouldHaveDataClass, FIBComponent> {
public RootComponentShouldHaveDataClass() {
super(FIBModelObject.class, "root_component_should_have_data_class");
}
@Override
public ValidationIssue<RootComponentShouldHaveDataClass, FIBComponent> applyValidation(FIBComponent object) {
if (object.isRootComponent() && object.getDataClass() == null) {
return new ValidationWarning<RootComponentShouldHaveDataClass, FIBComponent>(this, object,
"component_($object.toString)_is_declared_as_root_but_does_not_have_any_data_class");
}
return null;
}
}
public static class NonRootComponentShouldNotHaveLocalizedDictionary extends
ValidationRule<NonRootComponentShouldNotHaveLocalizedDictionary, FIBComponent> {
public NonRootComponentShouldNotHaveLocalizedDictionary() {
super(FIBModelObject.class, "non_root_component_should_not_have_localized_dictionary");
}
@Override
public ValidationIssue<NonRootComponentShouldNotHaveLocalizedDictionary, FIBComponent> applyValidation(FIBComponent object) {
if (!object.isRootComponent() && object.getLocalizedDictionary() != null) {
RemoveExtraLocalizedDictionary fixProposal = new RemoveExtraLocalizedDictionary();
return new ValidationWarning<NonRootComponentShouldNotHaveLocalizedDictionary, FIBComponent>(this, object,
"component_($object.toString)_has_a_localized_dictionary_but_is_not_root_component", fixProposal);
}
return null;
}
}
protected static class RemoveExtraLocalizedDictionary extends
FixProposal<NonRootComponentShouldNotHaveLocalizedDictionary, FIBComponent> {
public RemoveExtraLocalizedDictionary() {
super("remove_extra_dictionary");
}
@Override
protected void fixAction() {
getObject().setLocalizedDictionary(null);
}
}
public static class RootComponentShouldHaveMaximumOneDefaultButton extends
ValidationRule<RootComponentShouldHaveMaximumOneDefaultButton, FIBComponent> {
public RootComponentShouldHaveMaximumOneDefaultButton() {
super(FIBModelObject.class, "root_component_should_have_maximum_one_default_button");
}
@Override
public ValidationIssue<RootComponentShouldHaveMaximumOneDefaultButton, FIBComponent> applyValidation(FIBComponent object) {
if (object.isRootComponent() && object instanceof FIBContainer) {
List<FIBButton> defaultButtons = object.getDefaultButtons();
if (defaultButtons.size() > 1) {
return new ValidationWarning<RootComponentShouldHaveMaximumOneDefaultButton, FIBComponent>(this, object,
"component_($object.toString)_has_more_than_one_default_button");
}
}
return null;
}
}
public static class DataBindingMustBeValid extends BindingMustBeValid<FIBComponent> {
public DataBindingMustBeValid() {
super("'data'_binding_is_not_valid", FIBComponent.class);
}
@Override
public DataBinding getBinding(FIBComponent object) {
return object.getData();
}
@Override
public BindingDefinition getBindingDefinition(FIBComponent object) {
return object.getDataBindingDefinition();
}
}
public static class VisibleBindingMustBeValid extends BindingMustBeValid<FIBComponent> {
public VisibleBindingMustBeValid() {
super("'visible'_binding_is_not_valid", FIBComponent.class);
}
@Override
public DataBinding getBinding(FIBComponent object) {
return object.getVisible();
}
@Override
public BindingDefinition getBindingDefinition(FIBComponent object) {
return VISIBLE;
}
}
}