Как реализовать функцию отмены / поворота для вращения группы?
Благодаря James_D, у меня есть отлично работающая функция отмены / возврата, когда я перемещаю или изменяю размер моей группы. К сожалению, я не могу заставить его работать с вращением тоже.
РЕДАКТИРОВАТЬ: я сделал пользовательский ограничивающий прямоугольник, и отмена / повтор работает также для поворота. Но сообщение об исключении выдается каждый раз, когда я отменяю любые изменения:
Исключение в потоке "Поток приложений JavaFX"
java.lang.IllegalArgumentException: неожиданное изменение получено.
Ожидается: test.Model.Undo.UndoChange@8c4318ec Получено:
test.Model.Undo.UndoChange@35c7d8eb в
org.fxmisc.undo.impl.UndoManagerImpl.changeObserved (UndoManagerImpl.java:185)
public class CustomBoundingBox {
private double minX;
private double minY;
private double width;
private double height;
private double rotation;
private Paint fill;
public CustomBoundingBox(double minX, double minY, double width, double height, double rotation, Paint fill) {
this.minX=minX;
this.minY=minY;
this.width=width;
this.height=height;
this.rotation=rotation;
this.fill=fill;
}
public double getMinX() {
return minX;
}
public void setMinX(double minX) {
this.minX = minX;
}
public double getMinY() {
return minY;
}
public void setMinY(double minY) {
this.minY = minY;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getRotation() {
return rotation;
}
public void setRotation(double rotation) {
this.rotation = rotation;
}
public Paint getFill() {
return fill;
}
public void setColor(Paint fill) {
this.fill = fill;
}
}
EventStreamers:
{
...
EventStream<UndoChange<CustomBoundingBox>> rotationChanges = makeEventStream(rect.rotateProperty(),
rRect -> new CustomBoundingBox(rect.getRect().getX(), rect.getRect().getY(), rect.getRect().getWidth(), rect.getRect().getHeight(), rRect.doubleValue(), rect.getRect().getFill()));
EventStream<UndoChange<CustomBoundingBox>> boundsChanges = EventStreams
.merge(xChanges, yChanges, widthChanges, heightChanges, rotationChanges).reducible(UndoChange::merge)
.suspendWhen(animationRunning);
rect.undoManager = UndoManagerFactory.unlimitedHistoryUndoManager(boundsChanges, UndoChange::invert, c -> {
rect.getRedoAnimation().getKeyFrames()
.setAll(new KeyFrame(RectangleModel.getRedoAnimationTime(),
new KeyValue(rect.getRect().xProperty(), c.getNewValue().getMinX()),
new KeyValue(rect.getRect().yProperty(), c.getNewValue().getMinY()),
new KeyValue(rect.getRect().widthProperty(), c.getNewValue().getWidth()),
new KeyValue(rect.getRect().heightProperty(), c.getNewValue().getHeight()),
new KeyValue(rect.rotateProperty(), c.getNewValue().getRotation())));
rect.getRedoAnimation().play();
}, (c1, c2) -> Optional.of(c1.merge(c2)));
}
private <S, T> EventStream<UndoChange<T>> makeEventStream(ObservableValue<S> property, Function<S, T> objectSupplier) {
return EventStreams.changesOf(property).map(
c -> new UndoChange<>(objectSupplier.apply(c.getOldValue()), objectSupplier.apply(c.getNewValue())));
}
1 ответ
Я нашел проблему, мне пришлось реализовать метод equals():
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof CustomBoundingBox) {
CustomBoundingBox other = (CustomBoundingBox) obj;
return getMinX() == other.getMinX()
&& getMinY() == other.getMinY()
&& getWidth() == other.getWidth()
&& getHeight() == other.getHeight()
&& getRotation() == other.getRotation()
&& getFill() == other.getFill();
} else return false;
}