diff -r 000000000000 -r 9f8b07dcbe79 ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/KOList.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko-bck2brwsr/src/main/java/org/apidesign/html/ko2brwsr/KOList.java Mon Apr 29 12:50:19 2013 +0200 @@ -0,0 +1,170 @@ +/** + * HTML via Java(tm) Language Bindings + * Copyright (C) 2013 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. apidesign.org + * designates this particular file as subject to the + * "Classpath" exception as provided by apidesign.org + * in the License file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException + */ +package org.apidesign.html.ko2brwsr; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import org.apidesign.bck2brwsr.core.JavaScriptOnly; + +/** + * + * @author Jaroslav Tulach + */ +public final class KOList extends ArrayList { + private final String name; + private final String[] deps; + private Knockout model; + private Runnable onchange; + + public KOList(String name, String... deps) { + this.name = name; + this.deps = deps; + } + + public void assign(Knockout model) { + if (this.model != model) { + this.model = model; + notifyChange(); + } + } + + public KOList onChange(Runnable r) { + if (this.onchange != null) { + throw new IllegalStateException(); + } + this.onchange = r; + return this; + } + + @Override + public boolean add(T e) { + boolean ret = super.add(e); + notifyChange(); + return ret; + } + + @Override + public boolean addAll(Collection c) { + boolean ret = super.addAll(c); + notifyChange(); + return ret; + } + + @Override + public boolean addAll(int index, Collection c) { + boolean ret = super.addAll(index, c); + notifyChange(); + return ret; + } + + @Override + public boolean remove(Object o) { + boolean ret = super.remove(o); + notifyChange(); + return ret; + } + + @Override + public void clear() { + super.clear(); + notifyChange(); + } + + @Override + public boolean removeAll(Collection c) { + boolean ret = super.removeAll(c); + notifyChange(); + return ret; + } + + @Override + public boolean retainAll(Collection c) { + boolean ret = super.retainAll(c); + notifyChange(); + return ret; + } + + @Override + public T set(int index, T element) { + T ret = super.set(index, element); + notifyChange(); + return ret; + } + + @Override + public void add(int index, T element) { + super.add(index, element); + notifyChange(); + } + + @Override + public T remove(int index) { + T ret = super.remove(index); + notifyChange(); + return ret; + } + + @Override + public String toString() { + Iterator it = iterator(); + if (!it.hasNext()) { + return "[]"; + } + String sep = ""; + StringBuilder sb = new StringBuilder(); + sb.append('['); + while (it.hasNext()) { + T t = it.next(); + sb.append(sep); + sb.append(ConvertTypes.toJSON(t)); + sep = ","; + } + sb.append(']'); + return sb.toString(); + } + + + @JavaScriptOnly(name = "koArray", value = "function() { return this.toArray___3Ljava_lang_Object_2(); }") + private static native int koArray(); + + private void notifyChange() { + Knockout m = model; + if (m != null) { + m.valueHasMutated(name); + for (String dependant : deps) { + m.valueHasMutated(dependant); + } + } + Runnable r = onchange; + if (r != null) { + r.run(); + } + } + + @Override + public KOList clone() { + KOList ko = (KOList)super.clone(); + ko.model = null; + return ko; + } + +}