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
}
|