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