org.fxmisc.wellbehaved.event.template.InputHandlerTemplateMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richtextfx Show documentation
Show all versions of richtextfx Show documentation
FX-Text-Area for formatted text and other special effects.
package org.fxmisc.wellbehaved.event.template;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import javafx.event.Event;
import javafx.event.EventType;
import org.fxmisc.wellbehaved.event.InputHandler.Result;
import org.fxmisc.wellbehaved.event.internal.PrefixTree;
import org.fxmisc.wellbehaved.event.internal.PrefixTree.Ops;
import org.fxmisc.wellbehaved.event.template.InputMapTemplate.HandlerTemplateConsumer;
class InputHandlerTemplateMap {
private static InputHandlerTemplate sequence(
InputHandlerTemplate h1,
InputHandlerTemplate h2) {
return (s, evt) -> {
switch(h1.process(s, evt)) {
case PROCEED: return h2.process(s, evt);
case CONSUME: return Result.CONSUME;
case IGNORE: return Result.IGNORE;
default: throw new AssertionError("unreachable code");
}
};
}
private static Ops, InputHandlerTemplate> ops() {
return new Ops, InputHandlerTemplate>() {
@Override
public boolean isPrefixOf(EventType extends E> t1, EventType extends E> t2) {
EventType> t = t2;
while(t != null) {
if(t.equals(t1)) {
return true;
} else {
t = t.getSuperType();
}
}
return false;
}
@Override
public EventType extends E> commonPrefix(
EventType extends E> t1, EventType extends E> t2) {
Iterator> i1 = toList(t1).iterator();
Iterator> i2 = toList(t2).iterator();
EventType> common = null;
while(i1.hasNext() && i2.hasNext()) {
EventType> c1 = i1.next();
EventType> c2 = i2.next();
if(Objects.equals(c1, c2)) {
common = c1;
}
}
return (EventType extends E>) common;
}
@Override
public InputHandlerTemplate promote(InputHandlerTemplate h,
EventType extends E> subTpe, EventType extends E> supTpe) {
if(Objects.equals(subTpe, supTpe)) {
return h;
}
return (s, evt) -> {
if(isPrefixOf(subTpe, (EventType extends E>) evt.getEventType())) {
return h.process(s, evt);
} else {
return Result.PROCEED;
}
};
}
@Override
public InputHandlerTemplate squash(InputHandlerTemplate v1, InputHandlerTemplate v2) {
return sequence(v1, v2);
}
};
}
private static final List> toList(EventType> t) {
List> l = new ArrayList<>();
while(t != null) {
l.add(t);
t = t.getSuperType();
}
Collections.reverse(l);
return l;
}
private PrefixTree, InputHandlerTemplate> handlerTree;
public InputHandlerTemplateMap() {
this(PrefixTree.empty(ops()));
}
private InputHandlerTemplateMap(PrefixTree, InputHandlerTemplate> handlerTree) {
this.handlerTree = handlerTree;
}
public void insertAfter(EventType extends F> t, InputHandlerTemplate h) {
InputHandlerTemplate handler = (InputHandlerTemplate) h;
handlerTree = handlerTree.insert(t, handler, (h1, h2) -> sequence(h1, h2));
}
public InputHandlerTemplateMap map(
Function super InputHandlerTemplate, ? extends InputHandlerTemplate> f) {
return new InputHandlerTemplateMap<>(handlerTree.map(f, ops()));
}
void forEach(HandlerTemplateConsumer f) {
handlerTree.entries().forEach(th -> f.accept(th.getKey(), th.getValue()));
}
}