/******************************************************************************* * Copyright (c) 2009-2013 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Bert Lisser - Bert.Lisser@cwi.nl (CWI) * * Paul Klint - Paul.Klint@cwi.nl - CWI * * Arnold Lankamp - Arnold.Lankamp@cwi.nl *******************************************************************************/ package org.rascalmpl.eclipse.library.vis.properties; import java.util.HashMap; import org.rascalmpl.eclipse.library.vis.figure.Figure; import org.rascalmpl.eclipse.library.vis.swt.ICallbackEnv; import org.rascalmpl.eclipse.library.vis.swt.IFigureConstructionEnv; import org.rascalmpl.eclipse.library.vis.util.NameResolver; import org.rascalmpl.eclipse.library.vis.util.vector.Dimension; import io.usethesource.vallang.IConstructor; import io.usethesource.vallang.IList; import io.usethesource.vallang.IValue; import io.usethesource.vallang.IValueFactory; import io.usethesource.vallang.type.Type; import org.rascalmpl.values.ValueFactoryFactory; /** * Manage the properties of a figure. * * @author paulk * */ @SuppressWarnings("rawtypes") public class PropertyManager { static IValueFactory vf = ValueFactoryFactory.getValueFactory(); static IList emptyList = vf.list(); HashMap<Properties, PropertyValue> explicitValues, stdValues; PropertyManager parent; IRunTimePropertyChanges runTimeChanges; public static PropertyManager extendProperties(IFigureConstructionEnv fpa, IConstructor c, PropertyManager pm, IList childProps){ IList props = (IList) c.get(c.arity()-1); return new PropertyManager(fpa, pm, props); } public static IList getChildProperties(IList props){ IList result = null; for (IValue v : props) { if(v instanceof IConstructor && ((IConstructor)v).getName().equals("_child")){ IList childList = (IList)((IConstructor)v).get(0); if(result == null){ result = childList; } else { result.concat(childList); } } } return result; } public PropertyManager(IFigureConstructionEnv env, PropertyManager inherited, IList props) { explicitValues = new HashMap<Properties, PropertyValue>(); stdValues = new HashMap<Properties, PropertyValue>(); parent = inherited; setProperties(env,props); this.runTimeChanges = env.getRunTimePropertyChanges(); } public PropertyManager(IFigureConstructionEnv env) { explicitValues = new HashMap<Properties, PropertyValue>(0); stdValues = new HashMap<Properties, PropertyValue>(0); parent = null; if(env!=null){ this.runTimeChanges = env.getRunTimePropertyChanges(); } } public PropertyManager() { this(null); } @SuppressWarnings("unchecked") private void setProperties(IFigureConstructionEnv env, IList props) { for (IValue v : props) { HashMap<Properties,PropertyValue> addIn; IConstructor c = (IConstructor) v; String pname = c.getName(); if(pname.startsWith("_child")){ continue; } if(pname.equals("std")){ c = (IConstructor)c.get(0); pname = c.getName(); addIn = stdValues; } else { addIn = explicitValues; } Properties prop = Properties.propertyLookup.get(pname); if(prop == null){ System.out.printf("Cannot find %s !\n", pname); } else { PropertyValue val = prop.producePropertyValue(c.get(0), this, env); if(addIn.containsKey(prop)){ System.out.printf("Combining!\n"); addIn.put(prop, new CombinedProperty(addIn.get(prop),val,prop.combine)); } else { addIn.put(prop, val); } } } } public boolean hasHandlerProperties(){ for(Properties p : explicitValues.keySet()){ if(p.type == Types.HANDLER) return true; } return false; } public void stealExternalPropertiesFrom(PropertyManager other){ stealExternalProperties(other.explicitValues, explicitValues); stealExternalProperties(other.stdValues, stdValues); } private void stealExternalProperties(HashMap<Properties, PropertyValue> from, HashMap<Properties, PropertyValue> to){ for(Properties p : Properties.values()){ if(from.containsKey(p)){ if(p.semantics == PropertySemantics.EXTERNAL) { to.put(p, from.get(p)); from.remove(p); } if(p.semantics == PropertySemantics.BOTH){ to.put(p, from.get(p)); } } } } public void registerMeasures(NameResolver resolver){ for(PropertyValue v : explicitValues.values()){ v.registerMeasures(resolver); } for(PropertyValue v : stdValues.values()){ v.registerMeasures(resolver); } } public boolean isSet(Properties property){ return explicitValues.containsKey(property); } public PropertyValue getPropertyValue(Properties property){ if(explicitValues.containsKey(property)){ return explicitValues.get(property); } else { return getStdPropertyValue(property); } } PropertyValue getStdPropertyValue(Properties property) { if(stdValues.containsKey(property)){ return stdValues.get(property); } else if (parent != null){ return parent.getStdPropertyValue(property); } else { return null; } } private Object adoptProperty(Properties property, Object val){ if(runTimeChanges == null){ return val; } else { return runTimeChanges.adoptPropertyVal(property, val); } } public Object getProperty(Properties property){ PropertyValue pv = getPropertyValue(property); if(pv == null){ return adoptProperty(property,property.stdDefault); } else { return adoptProperty(property,pv.getValue()); } } public void checkCorrectType(Properties property, Types type){ if(property.type != type ){ throw new Error(String.format("Property %s is not of type %s\n",property,Types.BOOL)); } } public boolean anyExplicitPropertiesSet() { return explicitValues.size() > 0; } public boolean getBool(Properties property) { checkCorrectType(property, Types.BOOL); return (Boolean)getProperty(property); } public int getInt(Properties property) { checkCorrectType(property, Types.INT); return (Integer)getProperty(property); } public double getReal(Properties property) { checkCorrectType(property, Types.REAL); return (Double)getProperty(property); } public String getStr(Properties property) { checkCorrectType(property, Types.STR); return (String)getProperty(property); } public int getColor(Properties property) { checkCorrectType(property, Types.COLOR); return (Integer)getProperty(property); } public Figure getFig(Properties property) { checkCorrectType(property, Types.FIGURE); return (Figure)getProperty(property); } public boolean handlerCanBeExecuted(Properties property){ return isSet(property) || isStandardHandlerSet(property) || isStandardDefaultHandlerSet(property); } public boolean isStandardHandlerSet(Properties property){ checkCorrectType(property, Types.HANDLER); return stdValues.containsKey(property); } public boolean isStandardDefaultHandlerSet(Properties property){ return false; // std default handler are not supported } public IValue executeHandler(ICallbackEnv env,Properties property,Type[] types,IValue[] args ){ return getPropertyValue(property).execute(env,types, args); } public Object get2DProperty(Dimension d,TwoDProperties prop){ switch(d){ case X: return getProperty(prop.hor); case Y: return getProperty(prop.ver); } return null; } public boolean is2DPropertySet(Dimension d,TwoDProperties prop){ switch(d){ case X: return isSet(prop.hor); case Y: return isSet(prop.ver); } return false; } public double get2DReal(Dimension d, TwoDProperties prop){ checkCorrectType(prop.hor, Types.REAL); checkCorrectType(prop.ver, Types.REAL); return (Double)get2DProperty(d, prop); } public boolean get2DBool(Dimension d, TwoDProperties prop){ checkCorrectType(prop.hor, Types.BOOL); checkCorrectType(prop.ver, Types.BOOL); return (Boolean)get2DProperty(d, prop); } public void stealProperty(Properties p, PropertyManager prop) { if(prop.explicitValues.containsKey(p)){ explicitValues.put(p, prop.explicitValues.get(p)); prop.explicitValues.remove(p); } } }