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