added a few classes for doing property change listening (using pure kotlin code so its easier to work with JS and Java)
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2012 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package stdlib.testall;
|
||||||
|
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
import test.properties.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public class PropertiesAllTest {
|
||||||
|
public static TestSuite suite() {
|
||||||
|
return new TestSuite(PropertiesTest.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package std.properties
|
||||||
|
|
||||||
|
import std.*
|
||||||
|
import std.util.*
|
||||||
|
import java.util.List
|
||||||
|
import java.util.Map
|
||||||
|
import java.util.HashMap
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
class ChangeEvent(val source: Any, val name: String, val oldValue: Any?, val newValue: Any?) {
|
||||||
|
var propogationId: Any? = null
|
||||||
|
|
||||||
|
fun toString() = "ChangeEvent($name, $oldValue, $newValue)"
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ChangeListener {
|
||||||
|
fun onPropertyChange(event: ChangeEvent): Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an object where properties can be listened to and notified on
|
||||||
|
* updates for easier binding to user interfaces, undo/redo command stacks and
|
||||||
|
* change tracking mechanisms for persistence or distributed change notifications.
|
||||||
|
*/
|
||||||
|
abstract class ChangeSupport {
|
||||||
|
private var allListeners: List<ChangeListener>? = null
|
||||||
|
private var nameListeners: Map<String, List<ChangeListener>>? = null
|
||||||
|
|
||||||
|
|
||||||
|
fun addChangeListener(listener: ChangeListener) {
|
||||||
|
if (allListeners == null) {
|
||||||
|
allListeners = ArrayList<ChangeListener>()
|
||||||
|
}
|
||||||
|
allListeners?.add(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addChangeListener(name: String, listener: ChangeListener) {
|
||||||
|
if (nameListeners == null) {
|
||||||
|
nameListeners = HashMap<String, List<ChangeListener>>()
|
||||||
|
}
|
||||||
|
var listeners = nameListeners?.get(name)
|
||||||
|
if (listeners == null) {
|
||||||
|
listeners = arrayList<ChangeListener>()
|
||||||
|
nameListeners?.put(name, listeners.sure())
|
||||||
|
}
|
||||||
|
listeners?.add(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun <T> changeProperty(name: String, oldValue: T?, newValue: T?): Unit {
|
||||||
|
if (oldValue != newValue) {
|
||||||
|
firePropertyChanged(ChangeEvent(this, name, oldValue, newValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun firePropertyChanged(event: ChangeEvent): Unit {
|
||||||
|
if (nameListeners != null) {
|
||||||
|
val listeners = nameListeners?.get(event.name)
|
||||||
|
if (listeners != null) {
|
||||||
|
for (listener in listeners) {
|
||||||
|
listener.onPropertyChange(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allListeners != null) {
|
||||||
|
for (listener in allListeners) {
|
||||||
|
listener.onPropertyChange(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onPropertyChange(fn: (ChangeEvent) -> Unit) {
|
||||||
|
// TODO
|
||||||
|
//addChangeListener(DelegateChangeListener(fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onPropertyChange(name: String, fn: (ChangeEvent) -> Unit) {
|
||||||
|
// TODO
|
||||||
|
//addChangeListener(name, DelegateChangeListener(fn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO this seems to generate a compiler barf!
|
||||||
|
|
||||||
|
protected fun createChangeListener(fn: (ChangeEvent) -> Unit): ChangeListener {
|
||||||
|
return DelegateChangeListener(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun createChangeListener(fn: (ChangeEvent) -> Unit): ChangeListener {
|
||||||
|
return ChangeListener {
|
||||||
|
override fun onPropertyChange(event: ChangeEvent): Unit {
|
||||||
|
fn(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DelegateChangeListener(val f: (ChangeEvent) -> Unit) : ChangeListener {
|
||||||
|
override fun onPropertyChange(event: ChangeEvent): Unit {
|
||||||
|
f(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package test.properties
|
||||||
|
|
||||||
|
import std.*
|
||||||
|
import std.properties.*
|
||||||
|
import std.util.*
|
||||||
|
import stdhack.test.*
|
||||||
|
import java.util.*
|
||||||
|
import junit.framework.TestCase
|
||||||
|
|
||||||
|
class Customer() : ChangeSupport() {
|
||||||
|
// TODO the setter code should be generated
|
||||||
|
// via KT-1299
|
||||||
|
var name: String? = null
|
||||||
|
set(value) {
|
||||||
|
changeProperty("name", $name, value)
|
||||||
|
$name = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var city: String? = null
|
||||||
|
set(value) {
|
||||||
|
changeProperty("city", $city, value)
|
||||||
|
$city = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toString() = "Customer($name, $city)"
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyChangeListener() : ChangeListener {
|
||||||
|
val events = ArrayList<ChangeEvent>()
|
||||||
|
|
||||||
|
override fun onPropertyChange(event: ChangeEvent): Unit {
|
||||||
|
println("Property changed: $event")
|
||||||
|
events.add(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PropertiesTest() : TestCase() {
|
||||||
|
|
||||||
|
fun testModel() {
|
||||||
|
val c = Customer()
|
||||||
|
c.name = "James"
|
||||||
|
c.city = "Mells"
|
||||||
|
|
||||||
|
val listener = MyChangeListener()
|
||||||
|
c.addChangeListener(listener)
|
||||||
|
c.name = "Andrey"
|
||||||
|
println("Customer $c and raised change events ${listener.events}")
|
||||||
|
|
||||||
|
assertEquals(1, listener.events.size(), "Should have received a change event ${listener.events}")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user