diff --git a/core/src/main/java/dk/gtz/graphedit/util/RetryUtils.java b/core/src/main/java/dk/gtz/graphedit/util/RetryUtils.java index e375ad3e..6f749374 100644 --- a/core/src/main/java/dk/gtz/graphedit/util/RetryUtils.java +++ b/core/src/main/java/dk/gtz/graphedit/util/RetryUtils.java @@ -26,7 +26,7 @@ public static T tryTimes(int maxAttempts, int sleepMillis, Supplier f) { try { return f.get(); } catch(Exception e) { - logger.warn("'{}' {}/{} attempts left", e.getMessage(), attempts+1, maxAttempts); + logger.trace("'{}' {}/{} attempts left", e.getMessage(), attempts+1, maxAttempts); sleep(sleepMillis); } } diff --git a/core/src/main/java/dk/gtz/graphedit/view/ModelEditorToolbar.java b/core/src/main/java/dk/gtz/graphedit/view/ModelEditorToolbar.java index 3c0440da..5fda8bf0 100644 --- a/core/src/main/java/dk/gtz/graphedit/view/ModelEditorToolbar.java +++ b/core/src/main/java/dk/gtz/graphedit/view/ModelEditorToolbar.java @@ -28,6 +28,7 @@ public class ModelEditorToolbar extends ToolBar { private final IToolbox toolbox; private final ObjectProperty selectedTool; private final ViewModelProjectResource resource; + private ComboBox syntaxSelector; /** * Create a new instance @@ -47,8 +48,15 @@ public ModelEditorToolbar(IToolbox toolbox, ObjectProperty selectedTool, * @return Builder-pattern style reference to this */ public ModelEditorToolbar withSyntaxSelector() { - if(resource.metadata().containsKey("graphedit_syntax")) - addSyntaxSelector(); + if(resource.metadata().containsKey("graphedit_syntax")) { + var factories = DI.get(SyntaxFactoryCollection.class); + syntaxSelector = addSyntaxSelector(factories); + factories.addChangeListener(e -> { + getItems().remove(syntaxSelector); + syntaxSelector = addSyntaxSelector(factories); + }); + } + addSeparator(); return this; } @@ -74,8 +82,7 @@ private void setupContent() { } } - private void addSyntaxSelector() { - var factories = DI.get(SyntaxFactoryCollection.class); + private ComboBox addSyntaxSelector(SyntaxFactoryCollection factories) { ObservableList list = FXCollections.observableArrayList(); for(var factory : factories.entrySet()) list.add(factory.getKey()); @@ -98,6 +105,7 @@ protected void onChanged(String oldValue, String newValue) { } }; cmb.getSelectionModel().selectedItemProperty().addListener(listener); + return cmb; } private void addButton(ITool tool) { diff --git a/core/src/main/java/dk/gtz/graphedit/view/StatusBarController.java b/core/src/main/java/dk/gtz/graphedit/view/StatusBarController.java index 74bd2049..ed2f86dc 100644 --- a/core/src/main/java/dk/gtz/graphedit/view/StatusBarController.java +++ b/core/src/main/java/dk/gtz/graphedit/view/StatusBarController.java @@ -2,11 +2,13 @@ import java.util.List; +import dk.gtz.graphedit.spi.ILanguageServer; import dk.gtz.graphedit.viewmodel.LanguageServerCollection; import dk.yalibs.yadi.DI; import javafx.application.Platform; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.collections.MapChangeListener; import javafx.geometry.Insets; import javafx.scene.control.Label; import javafx.scene.input.MouseEvent; @@ -57,6 +59,8 @@ public StatusBarController() { // debugMouseHover(); } + // NOTE: kept for future use + @SuppressWarnings("unused") private void debugMouseHover() { Platform.runLater(() -> { var w = DI.get(Window.class); @@ -78,37 +82,44 @@ private void initializeLabels() { private void initializeLSPs() { var lsps = DI.get(LanguageServerCollection.class); - for(var server : lsps.values()) { - server.addProgressCallback(p -> { - Platform.runLater(() -> { - lspLabel.setText(p.title()+":"); - messageLabel.setText(p.message()); - }); - switch(p.type()) { - case PROGRESS: - case BEGIN: - if(!spinnerThread.isAlive()) - startSpinnerThread(); - break; - case END: - if(spinnerThread.isAlive()) - spinnerThread.interrupt(); - Platform.runLater(() -> spinnerString.set("\u2714")); // checkmark unicode character - break; - case END_FAIL: - if(spinnerThread.isAlive()) - spinnerThread.interrupt(); - Platform.runLater(() -> spinnerString.set("\u2717")); // x mark unicode character - break; - default: - if(spinnerThread.isAlive()) - spinnerThread.interrupt(); - Platform.runLater(() -> spinnerString.set("?")); - break; - - } + for(var lsp : lsps.values()) + addSpinner(lsp); + lsps.addListener((MapChangeListener)e -> { + if(e.wasAdded()) + addSpinner(e.getValueAdded()); + }); + } + + private void addSpinner(ILanguageServer server) { + server.addProgressCallback(p -> { + Platform.runLater(() -> { + lspLabel.setText(p.title()+":"); + messageLabel.setText(p.message()); }); - } + switch(p.type()) { + case PROGRESS: + case BEGIN: + if(!spinnerThread.isAlive()) + startSpinnerThread(); + break; + case END: + if(spinnerThread.isAlive()) + spinnerThread.interrupt(); + Platform.runLater(() -> spinnerString.set("\u2714")); // checkmark unicode character + break; + case END_FAIL: + if(spinnerThread.isAlive()) + spinnerThread.interrupt(); + Platform.runLater(() -> spinnerString.set("\u2717")); // x mark unicode character + break; + default: + if(spinnerThread.isAlive()) + spinnerThread.interrupt(); + Platform.runLater(() -> spinnerString.set("?")); + break; + + } + }); } private void startSpinnerThread() { diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/AutoProperty.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/AutoProperty.java new file mode 100644 index 00000000..7eeb8eee --- /dev/null +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/AutoProperty.java @@ -0,0 +1,213 @@ +package dk.gtz.graphedit.viewmodel; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javafx.beans.InvalidationListener; +import javafx.beans.property.Property; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.beans.value.WritableObjectValue; + +public abstract class AutoProperty> implements Property { + private static Logger logger = LoggerFactory.getLogger(AutoProperty.class); + private T value; + private List fields; + private final Map> changeListeners; + private final Map invalidationListeners; + + protected AutoProperty() { + this.changeListeners = new HashMap<>(); + this.invalidationListeners = new HashMap<>(); + } + + protected void loadFields(Class clazz, T value) { + this.value = value; + fields = new ArrayList<>(); + for(var field : clazz.getFields()) + if(List.of(field.getAnnotations()) + .stream() + .anyMatch(a -> a + .annotationType() + .getSimpleName() + .equals(Autolisten.class.getSimpleName()))) + fields.add(field); + } + + @Override + public void addListener(ChangeListener listener) { + for(var field : fields) { + var isObservable = ObservableValue.class.isAssignableFrom(field.getType()); + if(!isObservable) + continue; + try { + var observable = (ObservableValue)field.get(value); + if(!changeListeners.containsKey(field)) + changeListeners.put(field, (e,o,n) -> listener.changed(value, value, value)); + observable.addListener(changeListeners.get(field)); + } catch (IllegalAccessException e) { + logger.error("error adding listener '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + public void removeListener(ChangeListener listener) { + for(var field : fields) { + var isObservable = ObservableValue.class.isAssignableFrom(field.getType()); + if(!isObservable) + continue; + try { + var observable = (ObservableValue)field.get(value); + if(changeListeners.containsKey(field)) + observable.addListener(changeListeners.get(field)); + else // BUG: This probably doesnt work, but it doesn't hurt to try + observable.addListener((e,o,n) -> listener.changed(value, value, value)); + } catch (IllegalAccessException e) { + logger.error("error removing listener '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + public void addListener(InvalidationListener listener) { + for(var field : fields) { + if(!field.getType().isAssignableFrom(ObservableValue.class)) + continue; + try { + var observable = (ObservableValue)field.get(value); + if(!invalidationListeners.containsKey(field)) + invalidationListeners.put(field, listener); + observable.addListener(invalidationListeners.get(field)); + } catch (IllegalAccessException e) { + logger.error("error adding invalidation listener '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + public void removeListener(InvalidationListener listener) { + for(var field : fields) { + var isObservable = ObservableValue.class.isAssignableFrom(field.getType()); + if(!isObservable) + continue; + try { + var observable = (ObservableValue)field.get(value); + if(invalidationListeners.containsKey(field)) + observable.addListener(invalidationListeners.get(field)); + else // BUG: This probably doesnt work, but it doesn't hurt to try + observable.addListener(listener); + } catch (IllegalAccessException e) { + logger.error("error removing invalidation listener '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void bind(ObservableValue observable) { + for(var field : fields) { + if(!field.getType().isAssignableFrom(Property.class)) + continue; + try { + var thisObservable = (Property)field.get(value); + var thatObservable = (Property)field.get(observable.getValue()); + thisObservable.bind(thatObservable); + } catch (IllegalAccessException e) { + logger.error("error binding '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + public void unbind() { + for(var field : fields) { + var isProperty = Property.class.isAssignableFrom(field.getType()); + if(!isProperty) + continue; + try { + ((Property)field.get(value)).unbind(); + } catch (IllegalAccessException e) { + logger.error("error binding '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + public boolean isBound() { + for(var field : fields) { + var isProperty = Property.class.isAssignableFrom(field.getType()); + if(!isProperty) + continue; + try { + if(((Property)field.get(value)).isBound()) + return true; + } catch (IllegalAccessException e) { + logger.error("isBound error '{}': {}", field.getName(), e.getMessage(), e); + } + } + return false; + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void bindBidirectional(Property other) { + for(var field : fields) { + var isProperty = Property.class.isAssignableFrom(field.getType()); + if(!isProperty) + continue; + try { + var thisObservable = (Property)field.get(value); + var thatObservable = (Property)field.get(other); + thisObservable.bindBidirectional(thatObservable); + } catch (IllegalAccessException e) { + logger.error("error binding bidirectionally '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void unbindBidirectional(Property other) { + for(var field : fields) { + var isProperty = Property.class.isAssignableFrom(field.getType()); + if(!isProperty) + continue; + try { + var thisObservable = (Property)field.get(value); + var thatObservable = (Property)field.get(other); + thisObservable.unbindBidirectional(thatObservable); + } catch (IllegalAccessException e) { + logger.error("error unbinding bidirectionally '{}': {}", field.getName(), e.getMessage(), e); + } + } + } + + @Override + public Object getBean() { + return null; + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void setValue(T value) { + for(var field : fields) { + var isWritable = WritableObjectValue.class.isAssignableFrom(field.getType()); + if(!isWritable) + continue; + try { + var thisObservable = (WritableObjectValue)field.get(this.value); + var thatObservable = (WritableObjectValue)field.get(value); + thisObservable.set(thatObservable.get()); + } catch (IllegalAccessException e) { + logger.error("error setting value '{}': {}", field.getName(), e.getMessage(), e); + } + } + } +} diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/Autolisten.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/Autolisten.java new file mode 100644 index 00000000..4650cbf5 --- /dev/null +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/Autolisten.java @@ -0,0 +1,7 @@ +package dk.gtz.graphedit.viewmodel; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Autolisten {} diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/LanguageServerCollection.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/LanguageServerCollection.java index 0530e930..61d9dac5 100644 --- a/core/src/main/java/dk/gtz/graphedit/viewmodel/LanguageServerCollection.java +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/LanguageServerCollection.java @@ -1,19 +1,25 @@ package dk.gtz.graphedit.viewmodel; import java.util.Collection; -import java.util.HashMap; +import java.util.Map; +import java.util.Set; import dk.gtz.graphedit.spi.ILanguageServer; +import javafx.beans.InvalidationListener; +import javafx.collections.FXCollections; +import javafx.collections.MapChangeListener; +import javafx.collections.ObservableMap; /** * A container that holds {@link ILanguageServer} instances. */ -public class LanguageServerCollection extends HashMap { +public class LanguageServerCollection implements ObservableMap { + private final ObservableMap servers; /** * Constructs a new language server collection instance. */ public LanguageServerCollection() { - super(); + servers = FXCollections.observableHashMap(); } /** @@ -21,7 +27,7 @@ public LanguageServerCollection() { * @param server The server instance to add */ public void add(ILanguageServer server) { - put(server.getLanguageName(), server); + put(server.getLanguageName(), server); } /** @@ -29,8 +35,8 @@ public void add(ILanguageServer server) { * @param servers A collection of servers to add */ public void add(Collection servers) { - for(var factory : servers) - add(factory); + for(var factory : servers) + add(factory); } /** @@ -38,7 +44,87 @@ public void add(Collection servers) { * @param servers Varargs list of servers to add */ public void add(ILanguageServer... servers) { - for(var factory : servers) - add(factory); + for(var factory : servers) + add(factory); + } + + @Override + public int size() { + return servers.size(); + } + + @Override + public boolean isEmpty() { + return servers.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return servers.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return servers.containsValue(value); + } + + @Override + public ILanguageServer get(Object key) { + return servers.get(key); + } + + @Override + public ILanguageServer put(String key, ILanguageServer value) { + return servers.put(key, value); + } + + @Override + public ILanguageServer remove(Object key) { + return servers.remove(key); + } + + @Override + public void putAll(Map m) { + servers.putAll(m); + } + + @Override + public void clear() { + servers.clear(); + } + + @Override + public Set keySet() { + return servers.keySet(); + } + + @Override + public Collection values() { + return servers.values(); + } + + @Override + public Set> entrySet() { + return servers.entrySet(); + } + + @Override + public void addListener(InvalidationListener listener) { + servers.addListener(listener); + } + + @Override + public void removeListener(InvalidationListener listener) { + servers.removeListener(listener); + } + + @Override + public void addListener(MapChangeListener listener) { + servers.addListener(listener); + } + + @Override + public void removeListener(MapChangeListener listener) { + servers.removeListener(listener); } } diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/SyntaxFactoryCollection.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/SyntaxFactoryCollection.java index 4078aaae..88582896 100644 --- a/core/src/main/java/dk/gtz/graphedit/viewmodel/SyntaxFactoryCollection.java +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/SyntaxFactoryCollection.java @@ -1,20 +1,27 @@ package dk.gtz.graphedit.viewmodel; import java.util.Collection; -import java.util.HashMap; +import java.util.Map; +import java.util.Set; import dk.gtz.graphedit.internal.DemoSyntaxFactory; import dk.gtz.graphedit.spi.ISyntaxFactory; +import javafx.beans.InvalidationListener; +import javafx.collections.FXCollections; +import javafx.collections.MapChangeListener; +import javafx.collections.ObservableMap; /** * Collection type of syntax factories. */ -public final class SyntaxFactoryCollection extends HashMap { +public final class SyntaxFactoryCollection implements ObservableMap { + private final ObservableMap factories; /** * Construct a new instance with one {@link DemoSyntaxFactory} element */ public SyntaxFactoryCollection() { - add(new DemoSyntaxFactory()); + factories = FXCollections.observableHashMap(); + add(new DemoSyntaxFactory()); } /** @@ -22,7 +29,7 @@ public SyntaxFactoryCollection() { * @param factory The factory instance to add */ public void add(ISyntaxFactory factory) { - put(factory.getSyntaxName(), factory); + put(factory.getSyntaxName(), factory); } /** @@ -30,8 +37,8 @@ public void add(ISyntaxFactory factory) { * @param factories A collection of factires to add */ public void add(Collection factories) { - for(var factory : factories) - add(factory); + for(var factory : factories) + add(factory); } /** @@ -39,7 +46,95 @@ public void add(Collection factories) { * @param factories Varargs list of factories to add */ public void add(ISyntaxFactory... factories) { - for(var factory : factories) - add(factory); + for(var factory : factories) + add(factory); + } + + @Override + public int size() { + return factories.size(); + } + + @Override + public boolean isEmpty() { + return factories.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return factories.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return factories.containsValue(value); + } + + @Override + public ISyntaxFactory get(Object key) { + return factories.get(key); + } + + @Override + public ISyntaxFactory put(String key, ISyntaxFactory value) { + return factories.put(key, value); + } + + @Override + public ISyntaxFactory remove(Object key) { + return factories.remove(key); + } + + @Override + public void putAll(Map m) { + factories.putAll(m); + } + + @Override + public void clear() { + factories.clear(); + } + + @Override + public Set keySet() { + return factories.keySet(); + } + + @Override + public Collection values() { + return factories.values(); + } + + @Override + public Set> entrySet() { + return factories.entrySet(); + } + + @Override + public void addListener(InvalidationListener listener) { + factories.addListener(listener); + } + + @Override + public void removeListener(InvalidationListener listener) { + factories.removeListener(listener); + } + + @Override + public void addListener(MapChangeListener listener) { + factories.addListener(listener); + } + + @Override + public void removeListener(MapChangeListener listener) { + factories.removeListener(listener); + } + + public void addChangeListener(MapChangeListener listener) { + factories.addListener(listener); + } + + public void removeChangeListener(MapChangeListener listener) { + factories.removeListener(listener); } } diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelEdge.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelEdge.java index e4ec6969..1ef6c6ef 100644 --- a/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelEdge.java +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelEdge.java @@ -5,21 +5,18 @@ import java.util.UUID; import dk.gtz.graphedit.model.ModelEdge; -import javafx.beans.InvalidationListener; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.scene.Node; /** * The ViewModel representation of a graph edge. * Edges connects vertices with other vertices. */ -public class ViewModelEdge implements IInspectable, ISelectable, IHoverable, IFocusable, Property { +public class ViewModelEdge extends AutoProperty implements IInspectable, ISelectable, IHoverable, IFocusable { private final UUID uuid; private final BooleanProperty isSelected; private final List focusEventHandlers; @@ -28,12 +25,14 @@ public class ViewModelEdge implements IInspectable, ISelectable, IHoverable, IFo /** * Property pointing to the source vertex id */ - protected final ObjectProperty source; + @Autolisten + public final ObjectProperty source; /** * Property pointing to the target vertex id */ - protected final ObjectProperty target; + @Autolisten + public final ObjectProperty target; /** * Constructs a new view model edge instance @@ -42,6 +41,8 @@ public class ViewModelEdge implements IInspectable, ISelectable, IHoverable, IFo * @param target the syntactic element where the edge targets */ public ViewModelEdge(UUID uuid, ObjectProperty source, ObjectProperty target) { + super(); + loadFields(getClass(), this); this.uuid = uuid; this.source = source; this.target = target; @@ -157,81 +158,16 @@ public List getInspectableObjects() { new InspectableProperty("Target ID", target)); } - @Override - public Object getBean() { - return null; - } - @Override public String getName() { return ""; } - @Override - public void addListener(ChangeListener listener) { - source.addListener((e,o,n) -> listener.changed(this,this,this)); - target.addListener((e,o,n) -> listener.changed(this,this,this)); - // NOTE: isSelected changes does not constitute a "changed" event - } - - @Override - public void removeListener(ChangeListener listener) { - source.removeListener((e,o,n) -> listener.changed(this,this,this)); - target.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - @Override public ViewModelEdge getValue() { return this; } - @Override - public void addListener(InvalidationListener listener) { - source.addListener(listener); - target.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - source.removeListener(listener); - target.removeListener(listener); - } - - @Override - public void setValue(ViewModelEdge value) { - source.set(value.source().get()); - target.set(value.target().get()); - } - - @Override - public void bind(ObservableValue observable) { - source.bind(observable.getValue().source()); - target.bind(observable.getValue().target()); - } - - @Override - public void unbind() { - source.unbind(); - target.unbind(); - } - - @Override - public boolean isBound() { - return source.isBound() || target.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - source.bindBidirectional(other.getValue().source()); - target.bindBidirectional(other.getValue().target()); - } - - @Override - public void unbindBidirectional(Property other) { - source.unbindBidirectional(other.getValue().source()); - target.unbindBidirectional(other.getValue().target()); - } - @Override public void hover(Node hoverDisplay) { hoverElement.set(hoverDisplay); diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelGraph.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelGraph.java index 2ba0c7dd..4392ee89 100644 --- a/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelGraph.java +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelGraph.java @@ -6,23 +6,23 @@ import dk.gtz.graphedit.model.ModelGraph; import dk.gtz.graphedit.spi.ISyntaxFactory; -import javafx.beans.InvalidationListener; import javafx.beans.property.MapProperty; -import javafx.beans.property.Property; import javafx.beans.property.SimpleMapProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.MapChangeListener; /** * View model representation of a graphedit graph */ -public class ViewModelGraph implements Property { +public class ViewModelGraph extends AutoProperty { + @Autolisten private StringProperty declarations; + @Autolisten private MapProperty vertices; + @Autolisten private MapProperty edges; /** @@ -70,6 +70,8 @@ public boolean isValid() { * @param edges A mapping of edge ids to model edge-values */ public ViewModelGraph(StringProperty declarations, MapProperty vertices, MapProperty edges) { + super(); + loadFields(getClass(), this); this.declarations = declarations; this.vertices = vertices; this.edges = edges; @@ -110,11 +112,6 @@ public boolean isEmpty() { return declarations.getValueSafe().trim().isEmpty() && vertices.isEmpty() && edges.isEmpty(); } - @Override - public Object getBean() { - return null; - } - @Override public String getName() { return ""; @@ -168,58 +165,4 @@ public void removeListener(ChangeListener listener) { public ViewModelGraph getValue() { return this; } - - @Override - public void addListener(InvalidationListener listener) { - declarations.addListener(listener); - vertices.addListener(listener); - edges.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - declarations.removeListener(listener); - vertices.removeListener(listener); - edges.removeListener(listener); - } - - @Override - public void setValue(ViewModelGraph value) { - declarations.setValue(value.declarations().getValue()); - vertices.setValue(value.vertices().getValue()); - edges.setValue(value.edges().getValue()); - } - - @Override - public void bind(ObservableValue observable) { - declarations.bind(observable.getValue().declarations()); - vertices.bind(observable.getValue().vertices()); - edges.bind(observable.getValue().edges()); - } - - @Override - public void unbind() { - declarations.unbind(); - vertices.unbind(); - edges.unbind(); - } - - @Override - public boolean isBound() { - return declarations.isBound() || vertices.isBound() || edges.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - declarations.bindBidirectional(other.getValue().declarations()); - vertices.bindBidirectional(other.getValue().vertices()); - edges.bindBidirectional(other.getValue().edges()); - } - - @Override - public void unbindBidirectional(Property other) { - declarations.unbindBidirectional(other.getValue().declarations()); - vertices.unbindBidirectional(other.getValue().vertices()); - edges.unbindBidirectional(other.getValue().edges()); - } } diff --git a/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelVertex.java b/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelVertex.java index c4733608..eceedf9e 100644 --- a/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelVertex.java +++ b/core/src/main/java/dk/gtz/graphedit/viewmodel/ViewModelVertex.java @@ -6,28 +6,30 @@ import dk.gtz.graphedit.model.ModelEdge; import dk.gtz.graphedit.model.ModelVertex; -import javafx.beans.InvalidationListener; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.scene.Node; /** * Viewmodel representation of a {@link ModelVertex}. * A vertex is the most basic part of a graph. It can be connected with other vertices via {@link ModelEdge}s. */ -public class ViewModelVertex implements IInspectable, IHoverable, ISelectable, IFocusable, Property { +public class ViewModelVertex extends AutoProperty implements IInspectable, IHoverable, ISelectable, IFocusable { private final UUID uuid; - private final ViewModelPoint position; private final ViewModelVertexShape shape; private final BooleanProperty isSelected; private final List focusEventHandlers; private final ObjectProperty hoverElement; + /** + * The position of the vertex + */ + @Autolisten + public final ViewModelPoint position; + /** * Constructs a new view model vertex based on a position and a shape * @param uuid The id of the vertex @@ -35,6 +37,8 @@ public class ViewModelVertex implements IInspectable, IHoverable, ISelectable, I * @param shape The shape at which edges should follow */ public ViewModelVertex(UUID uuid, ViewModelPoint position, ViewModelVertexShape shape) { + super(); + loadFields(getClass(), this); this.uuid = uuid; this.position = position; this.shape = shape; @@ -128,71 +132,16 @@ public List getInspectableObjects() { return List.of(); } - @Override - public Object getBean() { - return null; - } - @Override public String getName() { return ""; } - @Override - public void addListener(ChangeListener listener) { - position.addListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void removeListener(ChangeListener listener) { - position.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - @Override public ViewModelVertex getValue() { return this; } - @Override - public void addListener(InvalidationListener listener) { - position.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - position.removeListener(listener); - } - - @Override - public void setValue(ViewModelVertex value) { - position.setValue(value.position); - } - - @Override - public void bind(ObservableValue observable) { - position.bind(observable.getValue().position()); - } - - @Override - public void unbind() { - position.unbind(); - } - - @Override - public boolean isBound() { - return position.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - position.bindBidirectional(other.getValue().position()); - } - - @Override - public void unbindBidirectional(Property other) { - position.unbindBidirectional(other.getValue().position()); - } - @Override public void hover(Node node) { hoverElement.set(node); diff --git a/graphedit/src/main/java/dk/gtz/graphedit/Main.java b/graphedit/src/main/java/dk/gtz/graphedit/Main.java index 32358249..12c280e7 100644 --- a/graphedit/src/main/java/dk/gtz/graphedit/Main.java +++ b/graphedit/src/main/java/dk/gtz/graphedit/Main.java @@ -55,16 +55,7 @@ public static void main(String[] argv) throws Exception { logger.error("could not load syntax factories for plugin: {}", plugin.getName(), e); } } - for(var plugin : loader.getLoadedPlugins().getEnabledPlugins()) { - try { - servers.add(plugin.getLanguageServers()); - } catch (Exception e) { - logger.error("could not load language servers for plugin: {}", plugin.getName(), e); - } - } - if(servers.isEmpty()) - logger.warn("No language servers loaded. Expect a very simple experience"); if(factories.isEmpty()) throw new Exception("Refusing to start the editor without any syntaxes. Please check your plugins directory"); diff --git a/graphedit/src/main/java/dk/gtz/graphedit/view/GraphEditApplication.java b/graphedit/src/main/java/dk/gtz/graphedit/view/GraphEditApplication.java index b60a4184..68292954 100644 --- a/graphedit/src/main/java/dk/gtz/graphedit/view/GraphEditApplication.java +++ b/graphedit/src/main/java/dk/gtz/graphedit/view/GraphEditApplication.java @@ -21,6 +21,7 @@ import dk.gtz.graphedit.serialization.IModelSerializer; import dk.gtz.graphedit.serialization.JacksonModelSerializer; import dk.gtz.graphedit.serialization.TikaMimeTypeChecker; +import dk.gtz.graphedit.spi.ILanguageServer; import dk.gtz.graphedit.spi.IPluginsContainer; import dk.gtz.graphedit.tool.ClipboardTool; import dk.gtz.graphedit.tool.EdgeCreateTool; @@ -52,6 +53,7 @@ import javafx.application.Application; import javafx.application.Platform; import javafx.collections.FXCollections; +import javafx.collections.MapChangeListener; import javafx.collections.ObservableList; import javafx.fxml.FXMLLoader; import javafx.geometry.Pos; @@ -95,6 +97,17 @@ private void kickoff(Stage primaryStage) throws Exception { setupStage(primaryStage); DI.add(Window.class, primaryStage.getScene().getWindow()); DI.get(IPluginsContainer.class).getEnabledPlugins().forEach(e -> Platform.runLater(e::onStart)); + DI.get(IPluginsContainer.class).getEnabledPlugins().forEach(e -> { + var t = new Thread(() -> { + try { + DI.get(LanguageServerCollection.class).add(e.getLanguageServers()); + } catch(Exception ex) { + logger.error("could not load language servers for plugin '{}': {}", e.getName(), ex.getMessage(), ex); + } + }); + t.setName("lsp-init-" + e.getName()); + t.start(); + }); } @Override @@ -131,19 +144,25 @@ private void setupLSPs(LanguageServerCollection servers, File projectFile, IBuff logger.trace("interrupting lsp thread {}", lspThread.getName()); lspThread.interrupt(); } - for(var server : servers.entrySet()) { - var serverVal = server.getValue(); - logger.trace("initializing language server {} {}", serverVal.getServerName(), serverVal.getServerVersion()); - serverVal.initialize(projectFile, buffers); - serverVal.addNotificationCallback(this::logNotification); - serverVal.addDiagnosticsCallback(lints::replaceAll); - logger.trace("starting thread for language server {} {}", serverVal.getServerName(), serverVal.getServerVersion()); - var t = new Thread(serverVal::start); - t.setName(serverVal.getServerName()); - lspThreads.add(t); - t.start(); - lints.replaceAll(server.getValue().getDiagnostics()); - } + for(var server : servers.entrySet()) + setupServer(server.getValue(), projectFile, buffers, lints); + servers.addListener((MapChangeListener)e -> { + if(e.wasAdded()) + setupServer(e.getValueAdded(), projectFile, buffers, lints); + }); + } + + private void setupServer(ILanguageServer server, File projectFile, IBufferContainer buffers, LintContainer lints) { + logger.trace("initializing language server {} {}", server.getServerName(), server.getServerVersion()); + server.initialize(projectFile, buffers); + server.addNotificationCallback(this::logNotification); + server.addDiagnosticsCallback(lints::replaceAll); + logger.trace("starting thread for language server {} {}", server.getServerName(), server.getServerVersion()); + var t = new Thread(server::start); + t.setName(server.getServerName()); + lspThreads.add(t); + t.start(); + lints.replaceAll(server.getDiagnostics()); } private void logNotification(ModelNotification n) { diff --git a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelState.java b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelState.java index 4a7464f9..ce78d559 100644 --- a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelState.java +++ b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelState.java @@ -6,21 +6,20 @@ import dk.gtz.graphedit.model.ModelVertex; import dk.gtz.graphedit.plugins.syntaxes.lts.model.ModelState; +import dk.gtz.graphedit.viewmodel.Autolisten; import dk.gtz.graphedit.viewmodel.ISearchable; import dk.gtz.graphedit.viewmodel.InspectableProperty; import dk.gtz.graphedit.viewmodel.ViewModelVertex; -import javafx.beans.InvalidationListener; import javafx.beans.property.BooleanProperty; -import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; public class ViewModelState extends ViewModelVertex implements ISearchable { - private final StringProperty name; - private final BooleanProperty initial; + @Autolisten + public final StringProperty name; + @Autolisten + public final BooleanProperty initial; public StringProperty name() { return name; @@ -77,82 +76,6 @@ public ModelVertex toModel() { return new ModelState(position().toModel(), name.getValueSafe(), initial.get()); } - @Override - public void addListener(ChangeListener listener) { - super.addListener(listener); - name.addListener((e,o,n) -> listener.changed(this,this,this)); - initial.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void removeListener(ChangeListener listener) { - super.addListener(listener); - name.removeListener((e,o,n) -> listener.changed(this,this,this)); - initial.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void addListener(InvalidationListener listener) { - super.addListener(listener); - name.addListener(listener); - initial.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - super.addListener(listener); - name.removeListener(listener); - initial.removeListener(listener); - } - - @Override - public void setValue(ViewModelVertex value) { - super.setValue(value); - if(value instanceof ViewModelState tvalue) { - name.setValue(tvalue.name().get()); - initial.setValue(tvalue.initial().get()); - } - } - - @Override - public void bind(ObservableValue observable) { - super.bind(observable); - if(observable.getValue() instanceof ViewModelState tobs) { - name.bind(tobs.name()); - initial.bind(tobs.initial()); - } - } - - @Override - public void unbind() { - super.unbind(); - name.unbind(); - initial.unbind(); - } - - @Override - public boolean isBound() { - return super.isBound() || name.isBound() || initial.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - super.bindBidirectional(other); - if(other.getValue() instanceof ViewModelState tother) { - name.bindBidirectional(tother.name()); - initial.bindBidirectional(tother.initial()); - } - } - - @Override - public void unbindBidirectional(Property other) { - super.unbindBidirectional(other); - if(other.getValue() instanceof ViewModelState tother) { - name.unbindBidirectional(tother.name()); - initial.unbindBidirectional(tother.initial()); - } - } - @Override public boolean equals(Object other) { if(!super.equals(other)) diff --git a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelTransition.java b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelTransition.java index 75c13fce..f8c05902 100644 --- a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelTransition.java +++ b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/lts/viewmodel/ViewModelTransition.java @@ -9,19 +9,17 @@ import dk.gtz.graphedit.model.ModelEdge; import dk.gtz.graphedit.plugins.syntaxes.lts.model.ModelTransition; +import dk.gtz.graphedit.viewmodel.Autolisten; import dk.gtz.graphedit.viewmodel.ISearchable; import dk.gtz.graphedit.viewmodel.InspectableProperty; import dk.gtz.graphedit.viewmodel.ViewModelEdge; -import javafx.beans.InvalidationListener; -import javafx.beans.property.Property; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; public class ViewModelTransition extends ViewModelEdge implements ISearchable { private final Logger logger = LoggerFactory.getLogger(ViewModelTransition.class); - private StringProperty action; + @Autolisten + public final StringProperty action; public StringProperty action() { return action; @@ -66,69 +64,6 @@ public ModelEdge toModel() { return new ModelTransition(source().get(), target().get(), action.getValueSafe()); } - @Override - public void addListener(ChangeListener listener) { - super.addListener(listener); - action.addListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void removeListener(ChangeListener listener) { - super.addListener(listener); - action.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void addListener(InvalidationListener listener) { - super.addListener(listener); - action.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - super.addListener(listener); - action.removeListener(listener); - } - - @Override - public void setValue(ViewModelEdge value) { - super.setValue(value); - if(value instanceof ViewModelTransition tvalue) - action.setValue(tvalue.action().get()); - } - - @Override - public void bind(ObservableValue observable) { - super.bind(observable); - if(observable.getValue() instanceof ViewModelTransition tobs) - action.bind(tobs.action()); - } - - @Override - public void unbind() { - super.unbind(); - action.unbind(); - } - - @Override - public boolean isBound() { - return super.isBound() && action.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - super.bindBidirectional(other); - if(other.getValue() instanceof ViewModelTransition tother) - action.bindBidirectional(tother.action()); - } - - @Override - public void unbindBidirectional(Property other) { - super.unbindBidirectional(other); - if(other.getValue() instanceof ViewModelTransition tother) - action.unbindBidirectional(tother.action()); - } - @Override public boolean equals(Object other) { if(!super.equals(other)) diff --git a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelArc.java b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelArc.java index c0a24912..26f45c6f 100644 --- a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelArc.java +++ b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelArc.java @@ -9,20 +9,18 @@ import dk.gtz.graphedit.model.ModelEdge; import dk.gtz.graphedit.plugins.syntaxes.petrinet.model.ModelArc; +import dk.gtz.graphedit.viewmodel.Autolisten; import dk.gtz.graphedit.viewmodel.ISearchable; import dk.gtz.graphedit.viewmodel.InspectableProperty; import dk.gtz.graphedit.viewmodel.ViewModelEdge; import dk.gtz.graphedit.viewmodel.ViewModelGraph; -import javafx.beans.InvalidationListener; import javafx.beans.property.IntegerProperty; -import javafx.beans.property.Property; import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; public class ViewModelArc extends ViewModelEdge implements ISearchable { private static final Logger logger = LoggerFactory.getLogger(ViewModelArc.class); - private final IntegerProperty weight; + @Autolisten + public final IntegerProperty weight; public ViewModelArc(UUID uuid, ModelEdge edge) { super(uuid, edge); @@ -76,69 +74,6 @@ public List getSearchValues() { return List.of("weight: " + weight.get()); } - @Override - public void addListener(ChangeListener listener) { - super.addListener(listener); - weight.addListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void removeListener(ChangeListener listener) { - super.addListener(listener); - weight.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void addListener(InvalidationListener listener) { - super.addListener(listener); - weight.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - super.addListener(listener); - weight.removeListener(listener); - } - - @Override - public void setValue(ViewModelEdge value) { - super.setValue(value); - if(value instanceof ViewModelArc tvalue) - weight.setValue(tvalue.weight().get()); - } - - @Override - public void bind(ObservableValue observable) { - super.bind(observable); - if(observable.getValue() instanceof ViewModelArc tobs) - weight.bind(tobs.weight()); - } - - @Override - public void unbind() { - super.unbind(); - weight.unbind(); - } - - @Override - public boolean isBound() { - return super.isBound() && weight.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - super.bindBidirectional(other); - if(other.getValue() instanceof ViewModelArc tother) - weight.bindBidirectional(tother.weight()); - } - - @Override - public void unbindBidirectional(Property other) { - super.unbindBidirectional(other); - if(other.getValue() instanceof ViewModelArc tother) - weight.unbindBidirectional(tother.weight()); - } - @Override public boolean equals(Object other) { if(!super.equals(other)) diff --git a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelPlace.java b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelPlace.java index 3e193968..5d3546bd 100644 --- a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelPlace.java +++ b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelPlace.java @@ -6,20 +6,18 @@ import dk.gtz.graphedit.model.ModelVertex; import dk.gtz.graphedit.plugins.syntaxes.petrinet.model.ModelPlace; +import dk.gtz.graphedit.viewmodel.Autolisten; import dk.gtz.graphedit.viewmodel.ISearchable; import dk.gtz.graphedit.viewmodel.InspectableProperty; import dk.gtz.graphedit.viewmodel.ViewModelShapeType; import dk.gtz.graphedit.viewmodel.ViewModelVertex; import dk.gtz.graphedit.viewmodel.ViewModelVertexShape; -import javafx.beans.InvalidationListener; import javafx.beans.property.IntegerProperty; -import javafx.beans.property.Property; import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; public class ViewModelPlace extends ViewModelVertex implements ISearchable { - private final IntegerProperty initialTokenCount; + @Autolisten + public final IntegerProperty initialTokenCount; public IntegerProperty initialTokenCount() { return initialTokenCount; @@ -57,69 +55,6 @@ public List getInspectableObjects() { return inspectables; } - @Override - public void addListener(ChangeListener listener) { - super.addListener(listener); - initialTokenCount.addListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void removeListener(ChangeListener listener) { - super.addListener(listener); - initialTokenCount.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void addListener(InvalidationListener listener) { - super.addListener(listener); - initialTokenCount.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - super.addListener(listener); - initialTokenCount.removeListener(listener); - } - - @Override - public void setValue(ViewModelVertex value) { - super.setValue(value); - if(value instanceof ViewModelPlace tvalue) - initialTokenCount.setValue(tvalue.initialTokenCount().get()); - } - - @Override - public void bind(ObservableValue observable) { - super.bind(observable); - if(observable.getValue() instanceof ViewModelPlace tobs) - initialTokenCount.bind(tobs.initialTokenCount()); - } - - @Override - public void unbind() { - super.unbind(); - initialTokenCount.unbind(); - } - - @Override - public boolean isBound() { - return super.isBound() && initialTokenCount.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - super.bindBidirectional(other); - if(other.getValue() instanceof ViewModelPlace tother) - initialTokenCount.bindBidirectional(tother.initialTokenCount()); - } - - @Override - public void unbindBidirectional(Property other) { - super.unbindBidirectional(other); - if(other.getValue() instanceof ViewModelPlace tother) - initialTokenCount.unbindBidirectional(tother.initialTokenCount()); - } - @Override public boolean equals(Object other) { if(!super.equals(other)) diff --git a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelTransition.java b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelTransition.java index 76c5ced4..306c170e 100644 --- a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelTransition.java +++ b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/petrinet/viewmodel/ViewModelTransition.java @@ -27,7 +27,7 @@ public ModelTransition toModel() { public boolean equals(Object other) { if(!super.equals(other)) return false; - if(!(other instanceof ViewModelTransition vother)) + if(!(other instanceof ViewModelTransition)) return false; return true; } diff --git a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/text/viewmodel/ViewModelTextVertex.java b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/text/viewmodel/ViewModelTextVertex.java index 001649a3..9573f252 100644 --- a/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/text/viewmodel/ViewModelTextVertex.java +++ b/std/src/main/java/dk/gtz/graphedit/plugins/syntaxes/text/viewmodel/ViewModelTextVertex.java @@ -6,21 +6,19 @@ import dk.gtz.graphedit.model.ModelVertex; import dk.gtz.graphedit.plugins.syntaxes.text.model.ModelTextVertex; +import dk.gtz.graphedit.viewmodel.Autolisten; import dk.gtz.graphedit.viewmodel.ISearchable; import dk.gtz.graphedit.viewmodel.InspectableProperty; import dk.gtz.graphedit.viewmodel.ViewModelPoint; import dk.gtz.graphedit.viewmodel.ViewModelShapeType; import dk.gtz.graphedit.viewmodel.ViewModelVertex; import dk.gtz.graphedit.viewmodel.ViewModelVertexShape; -import javafx.beans.InvalidationListener; -import javafx.beans.property.Property; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; public class ViewModelTextVertex extends ViewModelVertex implements ISearchable { - private final StringProperty text; + @Autolisten + public final StringProperty text; public StringProperty text() { return text; @@ -67,69 +65,6 @@ public ModelVertex toModel() { return new ModelTextVertex(position().toModel(), text.getValueSafe()); } - @Override - public void addListener(ChangeListener listener) { - super.addListener(listener); - text.addListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void removeListener(ChangeListener listener) { - super.addListener(listener); - text.removeListener((e,o,n) -> listener.changed(this,this,this)); - } - - @Override - public void addListener(InvalidationListener listener) { - super.addListener(listener); - text.addListener(listener); - } - - @Override - public void removeListener(InvalidationListener listener) { - super.addListener(listener); - text.removeListener(listener); - } - - @Override - public void setValue(ViewModelVertex value) { - super.setValue(value); - if(value instanceof ViewModelTextVertex tvalue) - text.setValue(tvalue.text().get()); - } - - @Override - public void bind(ObservableValue observable) { - super.bind(observable); - if(observable.getValue() instanceof ViewModelTextVertex tobs) - text.bind(tobs.text()); - } - - @Override - public void unbind() { - super.unbind(); - text.unbind(); - } - - @Override - public boolean isBound() { - return super.isBound() || text.isBound(); - } - - @Override - public void bindBidirectional(Property other) { - super.bindBidirectional(other); - if(other.getValue() instanceof ViewModelTextVertex tother) - text.bindBidirectional(tother.text()); - } - - @Override - public void unbindBidirectional(Property other) { - super.unbindBidirectional(other); - if(other.getValue() instanceof ViewModelTextVertex tother) - text.unbindBidirectional(tother.text()); - } - @Override public boolean equals(Object other) { if(!super.equals(other))