/*
* This file is part of LaTeXDraw.
* Copyright (c) 2005-2017 Arnaud BLOUIN
* LaTeXDraw is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
* LaTeXDraw is distributed without any warranty; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package net.sf.latexdraw.actions.shape;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import net.sf.latexdraw.actions.DrawingAction;
import net.sf.latexdraw.actions.Modifying;
import net.sf.latexdraw.actions.ShapeActionImpl;
import net.sf.latexdraw.models.interfaces.shape.IDrawing;
import net.sf.latexdraw.models.interfaces.shape.IGroup;
import net.sf.latexdraw.models.interfaces.shape.IShape;
import net.sf.latexdraw.util.LangTool;
import org.malai.undo.Undoable;
/**
* This action puts in background / foreground shapes.
* @author Arnaud Blouin
*/
public class MoveBackForegroundShapes extends ShapeActionImpl<IGroup> implements DrawingAction, Undoable, Modifying {
/** Defines whether the shapes must be placed in the foreground. */
private boolean foreground;
/** The former position of the shapes. */
private int[] formerId;
/** The shapes sorted by their position. */
private List<IShape> sortedSh;
/** The drawing that will be handled by the action. */
private Optional<IDrawing> drawing;
public MoveBackForegroundShapes() {
super();
drawing = Optional.empty();
foreground = false;
}
@Override
protected void doActionBody() {
if(foreground) {
moveForeground();
}else {
moveBackground();
}
}
/** Puts the shapes in the foreground. */
private void moveForeground() {
shape.ifPresent(gp -> {
final int size = gp.size();
formerId = new int[size];
drawing.ifPresent(dr -> {
final List<IShape> drshapes = dr.getShapes();
sortedSh = gp.getShapes().stream().sorted((a, b) -> drshapes.indexOf(a) < drshapes.indexOf(b) ? -1 : 1).collect(Collectors.toList());
for(int i = 0; i < size; i++) {
IShape sh = sortedSh.get(i);
formerId[i] = drshapes.indexOf(sh);
dr.removeShape(sh);
dr.addShape(sh);
}
dr.setModified(true);
});
});
}
/** Puts the shapes in the background. */
private void moveBackground() {
shape.ifPresent(gp -> {
final int size = gp.size();
formerId = new int[size];
drawing.ifPresent(dr -> {
final List<IShape> drshapes = dr.getShapes();
sortedSh = gp.getShapes().stream().sorted((a, b) -> drshapes.indexOf(a) < drshapes.indexOf(b) ? -1 : 1).collect(Collectors.toList());
for(int i = size - 1; i >= 0; i--) {
IShape sh = sortedSh.get(i);
formerId[i] = drshapes.indexOf(sh);
dr.removeShape(sh);
dr.addShape(sh, 0);
}
dr.setModified(true);
});
});
}
/*
val size = _shape.get.size
formerId = Array.ofDim[Int](size)
var sh : IShape = null
val drawing = _drawing.get
val drawingShapes = drawing.getShapes
sortedSh = _shape.get.getShapes.sortBy(drawingShapes.indexOf(_))
for(i <- size-1 to 0 by -1) {
sh = sortedSh(i)
formerId(i) = drawingShapes.indexOf(sh)
drawing.removeShape(sh)
drawing.addShape(sh, 0)
}
drawing.setModified(true)
*/
@Override
public boolean canDo() {
return super.canDo() && !shape.get().isEmpty() && drawing.isPresent();
}
@Override
public void undo() {
drawing.ifPresent(dr -> {
if(foreground) {
final IntegerProperty i = new SimpleIntegerProperty(formerId.length - 1);
sortedSh.stream().sorted(Collections.reverseOrder()).forEach(sh -> {
dr.removeShape(sh);
dr.addShape(sh, formerId[i.get()]);
i.set(i.get() - 1);
});
}else {
final IntegerProperty i = new SimpleIntegerProperty(0);
sortedSh.forEach(sh -> {
dr.removeShape(sh);
dr.addShape(sh, formerId[i.get()]);
i.set(i.get() + 1);
});
}
dr.setModified(true);
});
}
@Override
public void redo() {
doActionBody();
}
@Override
public String getUndoName() {
return LangTool.INSTANCE.getBundle().getString("Actions.8");
}
@Override
public RegistrationPolicy getRegistrationPolicy() {
return RegistrationPolicy.LIMITED;
}
/** Defines whether the shapes must be placed in the foreground. */
public void setIsForeground(final boolean fore) {
foreground = fore;
}
@Override
public void setDrawing(final IDrawing dr) {
drawing = Optional.ofNullable(dr);
}
@Override
public Optional<IDrawing> getDrawing() {
return drawing;
}
}