/******************************************************************************
 *                                                                            *
 *                    Copyright 2018 Subterranean Security                    *
 *                                                                            *
 *  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 com.sandpolis.viewer.jfx.attribute;

import java.util.LinkedList;
import java.util.List;

import com.sandpolis.core.attribute.Attribute;
import com.sandpolis.core.attribute.UntrackedAttribute;

import javafx.beans.InvalidationListener;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

/**
 * This {@link Attribute} is intended to be bound to a JavaFX {@link Property}
 * for extremely easy updates.
 * 
 * @author cilki
 * @since 5.0.0
 */
public class ObservableAttribute<E> extends UntrackedAttribute<E> implements ObservableValue<E> {

	private List<ChangeListener<? super E>> listeners = new LinkedList<>();

	@Override
	public void addListener(InvalidationListener listener) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void removeListener(InvalidationListener listener) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void addListener(ChangeListener<? super E> listener) {
		listeners.add(listener);
	}

	@Override
	public void removeListener(ChangeListener<? super E> listener) {
		listeners.remove(listener);
	}

	@Override
	public void set(E value) {
		listeners.forEach(listener -> listener.changed(this, get(), value));
		super.set(value);
	}

	@Override
	public void set(E value, long time) {
		listeners.forEach(listener -> listener.changed(this, get(), value));
		super.set(value, time);
	}

	@Override
	public E getValue() {
		return get();
	}

}

@@ -1498,16 +1498,66 @@
 ribute;%0A
+import com.sandpolis.core.attribute.AttributeKey;%0A
 import c
@@ -2031,79 +2031,403 @@
 %7B%0A%0A%09
-private List%3CChangeListener%3C? super E%3E%3E listeners = new LinkedList%3C%3E();
+/**%0A%09 * The list of change listeners for this %7B@link ObservableAttribute%7D.%0A%09 */%0A%09private List%3CChangeListener%3C? super E%3E%3E changeListeners = new LinkedList%3C%3E();%0A%0A%09/**%0A%09 * The list of invalidation listeners for this %7B@link ObservableAttribute%7D.%0A%09 */%0A%09private List%3CInvalidationListener%3E invalidationListeners = new LinkedList%3C%3E();%0A%0A%09public ObservableAttribute(AttributeKey%3CE%3E key) %7B%0A%09%09super(key);%0A%09%7D
 %0A%0A%09@
@@ -2499,48 +2499,42 @@
 %7B%0A%09%09
-throw new UnsupportedOperationException(
+invalidationListeners.add(listener
 );%0A%09
@@ -2614,48 +2614,45 @@
 %7B%0A%09%09
-throw new UnsupportedOperationException(
+invalidationListeners.remove(listener
 );%0A%09
@@ -2722,33 +2722,39 @@
 %3E listener) %7B%0A%09%09
-l
+changeL
 isteners.add(lis
@@ -2840,25 +2840,31 @@
 stener) %7B%0A%09%09
-l
+changeL
 isteners.rem
@@ -2919,25 +2919,104 @@
  value) %7B%0A%09%09
-l
+invalidationListeners.forEach(listener -%3E listener.invalidated(this));%0A%09%09changeL
 isteners.for
@@ -3147,17 +3147,96 @@
 me) %7B%0A%09%09
-l
+invalidationListeners.forEach(listener -%3E listener.invalidated(this));%0A%09%09changeL
 isteners

Add basic support for InvalidationListeners