A hint, however. The line you commented out is important, because it's how MASON updates other widgets and displays to reflect the change you just made in your inspector. Imagine if you had TWO inspectors popped up which view the same object. The simulation is paused. You make a change to one inspector, and without that line, MASON won't update the other inspector until the next simulation timestep.
Obviously what's going on here is that in newValue() we're refreshing the console, which in turn calls PropertyField.update(), which calls setValue(). In setValue normally it changes the slider, but it only does so if the boolean "sliding" isn't set (which is meant to break loops). I wonder if your update is resulting in a later callback in which this sliding variable isn't set any more.
Perhaps one way to fix this would be to change the ChangeListener for the slider to an ActionListener, so it's not responding to changes in the slider but instead responding to physical slides the user is making. That oughta break the loop you're seeing.
Sean
On Jan 29, 2014, at 8:44 AM, Sean Luke <[log in to unmask]> wrote:
> I can't help you with Scala, sorry.
>
> Sean
>
> On Jan 29, 2014, at 5:53 AM, Roman Seidl <[log in to unmask]> wrote:
>
>> Hi!
>>
>> I have been trying to implement a simple own Properties Class to be able
>> to declare my Properties in a way I like better than declaring lots of
>> methods.
>>
>> Maybe one could think about adding the possibility of Java Annotations
>> to declare the domain, description etc.? Or would this break with Masons
>> JDK compatbility target?
>>
>> The disadvantage of reflection would still be that there is not ordering
>> of the properties - at least I don't think that reflecting on a class
>> would guarantee any ordering of the properties that reflects the
>> ordering in the code.
>>
>> Anyway, I have produce a class derive from sim.util.Properties that
>> delivers the information and made my inspected class implement
>> Propertied. For the source code see below. It' in Scala but that should
>> not be the reason for any of my problems.
>>
>> When using this combination with SimpleInspector and a Domain-Slider I
>> get into an endless loop in SimpleInspector of
>> - PropertyField.newValue calling
>> - SimpleInspector.this.state.controller.refresh() calling
>> - SimpleInspector.updateInspector() calling
>> - SimpleInspector.generateProperties(start) calling
>> - PropertyField.newValue calling
>> ...
>>
>>
>> The responsible lines of code in SimpleInspector.generateProperties are:
>>
>> if (SimpleInspector.this.state.controller != null)
>> SimpleInspector.this.state.controller.refresh();
>>
>> If I just comment them out everything seems to be just fine. There is
>> not problems with the display not refreshing whatsoever.
>>
>> Strange enough this kind of endless loop does not happen with the
>> standard SimpleProperties generated by Reflection. There is some looping
>> going on but it stops after some rounds. There has to be some race
>> condition or something alike that by chance works out fine. Or is there
>> some other reason? I couldn't figure it out.
>>
>> Any ideas? Maybe this is just a bug. Then it would be fine and
>> commenting out the two lines of code above would fix it.
>>
>> regards
>> roman
>>
>> -------------------------
>> Custom Properties code:
>> -------------------------
>>
>> package at.granul.mason
>>
>> import scala.collection.mutable
>> import java.lang.reflect.Method
>> import sim.util.{Properties, Propertied}
>> import scala.Boolean
>> import java.lang.Class
>>
>> import at.granul.mason.Property
>> import java.text.NumberFormat
>>
>> /**
>> * Created by Roman Seidl on 28.01.14.
>> */
>>
>> trait DeclaredPropertied extends Propertied {
>> var ___properties = DeclaredProperties(this)
>>
>> override def properties(): Properties = ___properties
>>
>> def setProperties(p: PropertyElement*) : DeclaredProperties =
>> ___properties.setProperties(p :_*)
>>
>> }
>>
>> abstract class PropertyElement(nam: String){
>> val name = nam
>> }
>>
>> case class Property(override val name : String, var title : String =
>> null, var domain : AnyRef = null, var isReadOnly : Boolean = false)
>> extends PropertyElement(name) {
>> if (title == null)
>> title = name
>>
>> def dom(lower: Long, upper: Long) : Property = {
>> domain = new sim.util.Interval(lower, upper)
>> this
>> }
>>
>> def dom(lower: Double, upper: Double) : Property = {
>> domain = new sim.util.Interval(lower, upper)
>> this
>> }
>>
>> def dom(dom: Array[String]) : Property = {
>> domain = dom
>> this
>> }
>>
>>
>> def caption(tf : String) : Property = title(tf)
>> def text(tf : String) : Property = title(tf)
>> def title(tf : String) : Property = {
>> title = tf
>> this
>> }
>>
>> def readOnly = ro
>> def ro : Property = {
>> isReadOnly = true
>> this
>> }
>>
>> //override def toString: String = super.toString + " Domain: " + "
>> Domain: " + domain + " Field: " + targetField
>> }
>>
>>
>> case class DeclaredProperties(obj: Object, p : PropertyElement*) extends
>> sim.util.Properties {
>>
>> val propertyElements = mutable.Buffer[PropertyElement]()
>> val elements = mutable.Buffer[Property]()
>> this.setProperties(p :_*)
>>
>> var getMethods = mutable.Buffer[Method]()
>> var setMethods = mutable.Buffer[Method]()
>>
>> def setProperties(p : PropertyElement*) : DeclaredProperties = {
>> for (pe <- p.iterator)
>> this.+(pe)
>> this
>> }
>>
>> def +(prop : PropertyElement) : DeclaredProperties = {
>> propertyElements += prop
>> if( prop.isInstanceOf[Property]){
>> elements += prop.asInstanceOf[Property]
>>
>> val getMethodStub = obj.getClass.getMethods.find(m => {m.getName
>> == prop.name || m.getName == ("get" + prop.name.capitalize) || m.getName
>> == ("is" + prop.name.capitalize)})
>> val getMethod = if(getMethodStub != null) getMethodStub.get else null
>> getMethods += getMethod
>>
>> val setMethodStub = obj.getClass.getMethods.find(m => {(m.getName
>> == prop.name + "_$eq") || m.getName == ("set" + prop.name.capitalize)})
>> val setMethod = if(setMethodStub != null) setMethodStub.get else null
>> setMethods += setMethod
>> }
>> this
>> }
>>
>>
>> def numProperties(): Int = elements.size
>>
>> def isVolatile: Boolean = true
>>
>>
>> def getValue(index: Int): Object = {
>> val method = getMethods(index)
>> if(method != null) method.invoke(obj) else null
>> }
>>
>> def _setValue(index: Int, value: Object): Object = {
>> /* if(isReadWrite(index: Int))
>> {*/
>> var method = setMethods(index)
>> if(method != null) {
>> method.invoke(obj, value.asInstanceOf[AnyRef])
>> getValue(index)
>> } else null
>> /* }
>> getValue(index)*/
>> }
>>
>> override def getDomain(index: Int): AnyRef = elements(index).domain
>>
>> def isReadWrite(index: Int): Boolean = !elements(index).isReadOnly
>>
>> def getName(index: Int): String = elements(index).title
>>
>> def getType(index: Int): Class[_] = {
>> val method = getMethods(index)
>> if(method != null) method.getReturnType else null
>> }
>>
>> override def toString: String = super.toString + " obj: " + obj + "
>> elements:"+ propertyElements
>> }
|