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:
James Strachan
2012-02-20 15:38:34 +00:00
parent 8597188bcc
commit 094d5d2e70
3 changed files with 185 additions and 0 deletions
@@ -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);
}
}
+106
View File
@@ -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)
}
}
+51
View File
@@ -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}")
}
}