Refactor caret positioning

This commit is contained in:
Andrea Cavalli 2023-08-23 16:47:55 +02:00
parent 3031966145
commit 7ae4315837
24 changed files with 622 additions and 512 deletions

View File

@ -50,7 +50,13 @@
<artifactId>flow-nbt</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -1,23 +1,28 @@
package it.cavallium.warppi.gui.expression;
import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockOrContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockPosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
public class Caret {
private int pos;
private int remaining;
@NotNull
private BlockPosition pos;
private CaretState state;
private final int[] lastSize;
private final int[] lastLocation;
public Caret(final CaretState state, final int pos) {
public Caret(final CaretState state, final BlockPosition pos) {
this(state, pos, new int[] { 0, 0 }, new int[] { 2, 5 });
}
public Caret(final CaretState state, final int pos, final int[] lastLocation, final int[] lastSize) {
public Caret(final CaretState state, final @NotNull BlockPosition pos, final int[] lastLocation, final int[] lastSize) {
this.state = state;
this.pos = pos;
remaining = pos;
this.lastLocation = lastLocation;
this.lastSize = lastSize;
}
@ -26,26 +31,27 @@ public class Caret {
* Copy
* @param old
*/
public Caret(Caret old) {
this.pos = old.pos;
this.remaining = old.remaining;
public Caret(Caret old, BlockContainer newRoot) {
this.pos = clonePosition(old.pos, newRoot);
this.state = old.state;
this.lastSize = Arrays.copyOf(old.lastSize, old.lastSize.length);
this.lastLocation = Arrays.copyOf(old.lastLocation, old.lastLocation.length);
}
public void skip(final int i) {
remaining -= i;
private BlockPosition clonePosition(BlockPosition pos, BlockContainer newRoot) {
BlockOrContainer el = newRoot;
var url = pos.getURL();
for (int i : url) {
el = el.getAt(i);
}
return new BlockPosition(el);
}
public int getPosition() {
@NotNull
public BlockPosition getPos() {
return pos;
}
public int getRemaining() {
return remaining;
}
public CaretState getState() {
return state;
}
@ -64,12 +70,8 @@ public class Caret {
}
}
public void setPosition(final int i) {
pos = i;
}
public void resetRemaining() {
remaining = pos;
public void setPosition(final BlockPosition pos) {
this.pos = pos;
}
public void setLastLocation(final int x, final int y) {
@ -90,4 +92,7 @@ public class Caret {
return new int[] { lastSize[0], lastSize[1] };
}
public boolean isHere(BlockOrContainer pos) {
return getPos().get() == pos;
}
}

View File

@ -5,6 +5,7 @@ import java.util.Arrays;
import it.cavallium.warppi.device.display.DisplayOutputDevice;
import it.cavallium.warppi.event.KeyboardEventListener;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockVariable;
import it.cavallium.warppi.gui.expression.blocks.TreeContainer;
import it.cavallium.warppi.gui.graphicengine.Renderer;
@ -46,7 +47,7 @@ public abstract class ExtraMenu<T extends Block> implements KeyboardEventListene
return false;
}
public abstract ExtraMenu<T> clone(final TreeContainer parent, InputContext ic);
public abstract ExtraMenu<T> clone(final BlockContainer parent, InputContext ic);
public abstract ExtraMenu<T> clone(T newBlockVariable);

View File

@ -11,13 +11,13 @@ import it.cavallium.warppi.math.parser.features.interfaces.Feature;
import it.cavallium.warppi.util.Error;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public abstract class Block implements TreeBlock, GraphicalElement {
public abstract class Block implements TreeBlock, BlockOrContainer, GraphicalElement {
protected boolean small;
protected int width;
protected int height;
protected int line;
protected TreeContainer parent;
protected BlockContainer parent;
public Block() {
@ -27,7 +27,7 @@ public abstract class Block implements TreeBlock, GraphicalElement {
* Copy
* @param b
*/
public Block(TreeContainer parent, Block b) {
public Block(BlockContainer parent, Block b) {
this.small = b.small;
this.width = b.width;
this.height = b.height;
@ -43,15 +43,10 @@ public abstract class Block implements TreeBlock, GraphicalElement {
* Position relative to the window.
* @param y
* Position relative to the window.
* @param small
*/
public abstract void draw(DisplayOutputDevice ge, Renderer r, int x, int y, Caret caret);
public abstract boolean appendBlock(Caret caret, Block newBlock, boolean splitAdjacent);
public abstract boolean deleteBlock(Caret caret);
public abstract BlockReference<?> getBlock(Caret caret);
public abstract boolean appendBlock(Caret caret, Block newBlock);
/**
* Used only to get inner blocks when deleting the parent block.
@ -64,8 +59,6 @@ public abstract class Block implements TreeBlock, GraphicalElement {
@Override
public abstract void recomputeDimensions();
public abstract int computeCaretMaxBound();
@Override
public int getWidth() {
return width;
@ -81,10 +74,6 @@ public abstract class Block implements TreeBlock, GraphicalElement {
return line;
}
public int getCaretDeltaPositionAfterCreation() {
return 1;
}
public boolean isSmall() {
return small;
}
@ -98,18 +87,66 @@ public abstract class Block implements TreeBlock, GraphicalElement {
public abstract Feature toFeature(MathContext context) throws Error;
@Override
public TreeContainer getParentContainer() {
public BlockContainer getParentContainer() {
return parent;
}
@Override
public BlockContainer getParent() {
return parent;
}
@Override
public BlockOrContainer getAt(int index) {
var ic = getInnerContainers();
return ic.get(index);
}
@Override
public int getIndex() {
return parent != null ? parent.getContentUnsafe().indexOf(this) : -1;
}
@Override
public boolean hasParent() {
return parent != null;
}
public void setParent(final TreeContainer parent) {
public void setParent(final BlockContainer parent) {
this.parent = parent;
}
public abstract Block clone(TreeContainer parent, InputContext ic);
public abstract Block clone(BlockContainer parent, InputContext ic);
public BlockReference<?> getReference() {
if (this.hasParent()) {
return this.parent.getReference(this);
} else {
return null;
}
}
public BlockPosition getLastInnerPosition() {
var innerContainers = getInnerContainers();
if (innerContainers != null && !innerContainers.isEmpty()) {
var lastContainer = innerContainers.get(innerContainers.size() - 1);
var content = lastContainer.getContent();
if (content.isEmpty()) {
return new BlockPosition(lastContainer);
} else {
return new BlockPosition(content.get(content.size() - 1));
}
} else {
return null;
}
}
public BlockPosition getFirstInnerPosition() {
var innerContainers = getInnerContainers();
if (innerContainers != null && !innerContainers.isEmpty()) {
return new BlockPosition(innerContainers.get(0));
} else {
return null;
}
}
}

View File

@ -23,7 +23,7 @@ public class BlockChar extends Block {
* @param b
* @param ic
*/
protected BlockChar(final TreeContainer parent, final BlockChar b, InputContext ic) {
protected BlockChar(final BlockContainer parent, final BlockChar b, InputContext ic) {
super(parent, b);
this.ch = b.ch;
}
@ -36,20 +36,10 @@ public class BlockChar extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
return false;
}
@Override
public boolean deleteBlock(final Caret caret) {
return false;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return null;
}
@Override
public void recomputeDimensions() {
width = BlockContainer.getDefaultCharWidth(small) - 1;
@ -67,11 +57,6 @@ public class BlockChar extends Block {
return ch;
}
@Override
public int computeCaretMaxBound() {
return 0;
}
@Override
public Feature toFeature(final MathContext context) {
return new FeatureChar(getChar());
@ -88,7 +73,7 @@ public class BlockChar extends Block {
}
@Override
public BlockChar clone(final TreeContainer parent, InputContext ic) {
public BlockChar clone(final BlockContainer parent, InputContext ic) {
return new BlockChar(parent, this, ic);
}

View File

@ -15,9 +15,8 @@ import it.cavallium.warppi.math.parser.features.interfaces.Feature;
import it.cavallium.warppi.util.Error;
import it.cavallium.warppi.util.Errors;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
public class BlockContainer implements TreeContainer, GraphicalElement {
public class BlockContainer implements TreeContainer, BlockOrContainer, GraphicalElement {
private static boolean initialized = false;
@ -30,39 +29,39 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
private int line;
public final boolean withBorder;
private boolean autoMinimums;
private final TreeBlock parent;
private final Block parent;
public BlockContainer() {
this(null, false, BlockContainer.getDefaultCharWidth(false), BlockContainer.getDefaultCharHeight(false), true);
autoMinimums = true;
}
public BlockContainer(final TreeBlock parent) {
public BlockContainer(final Block parent) {
this(parent, false, BlockContainer.getDefaultCharWidth(false), BlockContainer.getDefaultCharHeight(false), true);
autoMinimums = true;
}
public BlockContainer(final TreeBlock parent, final boolean small) {
public BlockContainer(final Block parent, final boolean small) {
this(parent, small, BlockContainer.getDefaultCharWidth(small), BlockContainer.getDefaultCharHeight(small), true);
autoMinimums = true;
}
public BlockContainer(final TreeBlock parent, final boolean small, final ObjectArrayList<Block> content) {
public BlockContainer(final Block parent, final boolean small, final ObjectArrayList<Block> content) {
this(parent, small, BlockContainer.getDefaultCharWidth(small), BlockContainer.getDefaultCharHeight(small), content, true);
autoMinimums = true;
}
public BlockContainer(final TreeBlock parent, final boolean small, final boolean withBorder) {
public BlockContainer(final Block parent, final boolean small, final boolean withBorder) {
this(parent, small, BlockContainer.getDefaultCharWidth(small), BlockContainer.getDefaultCharHeight(small), withBorder);
autoMinimums = true;
}
public BlockContainer(final TreeBlock parent, final boolean small, final int minWidth, final int minHeight, final boolean withBorder) {
public BlockContainer(final Block parent, final boolean small, final int minWidth, final int minHeight, final boolean withBorder) {
this(parent, small, minWidth, minHeight, new ObjectArrayList<>(), withBorder);
autoMinimums = false;
}
public BlockContainer(final TreeBlock parent, final boolean small, final int minWidth, final int minHeight, final ObjectArrayList<Block> content, final boolean withBorder) {
public BlockContainer(final Block parent, final boolean small, final int minWidth, final int minHeight, final ObjectArrayList<Block> content, final boolean withBorder) {
this.parent = parent;
this.small = small;
this.minWidth = minWidth;
@ -77,7 +76,7 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
recomputeDimensions();
}
private BlockContainer(final TreeBlock parent, BlockContainer old, InputContext ic) {
private BlockContainer(final Block parent, BlockContainer old, InputContext ic) {
this.autoMinimums = old.autoMinimums;
this.content = new ObjectArrayList<>();
for (Block b : old.content) {
@ -94,15 +93,30 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
this.withBorder = old.withBorder;
}
public BlockContainer clone(final TreeBlock parent, InputContext ic) {
public BlockContainer clone(final Block parent, InputContext ic) {
return new BlockContainer(parent, this, ic);
}
@Override
public TreeBlock getParentBlock() {
public Block getParentBlock() {
return parent;
}
@Override
public Block getParent() {
return parent;
}
@Override
public BlockOrContainer getAt(int index) {
return content.get(index);
}
@Override
public int getIndex() {
return parent != null ? parent.getInnerContainers().indexOf(this) : -1;
}
@Override
public boolean hasParent() {
return parent != null;
@ -155,7 +169,7 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
public BlockReference<?> getBlockAt(final int i) {
final Block b = content.get(i);
return new BlockReference<>(b, i, this);
return new BlockReference<>(b, i, content, this);
}
public int getSize() {
@ -183,7 +197,7 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
public void draw(final DisplayOutputDevice ge, final Renderer r, final int x, final int y, final Caret caret) {
int paddingX = 1;
if (caret.getRemaining() == 0) {
if (caret.isHere(this)) {
if (content.size() > 0) {
BlockContainer.drawCaret(ge, r, caret, small, x, y + line - content.get(0).line, content.get(0).height);
} else {
@ -199,113 +213,39 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
r.glDrawLine(x + paddingX, y + height - 1, x + paddingX + width - 1, y + height - 1);
} else {
for (final Block b : content) {
caret.skip(1);
b.draw(ge, r, x + paddingX, y + line - b.line, caret);
paddingX += b.getWidth();
if (caret.getRemaining() == 0) {
if (caret.isHere(b)) {
BlockContainer.drawCaret(ge, r, caret, small, x + paddingX, y + line - b.line, b.height);
}
paddingX += 1;
}
}
caret.skip(1);
}
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
if (caret.getRemaining() == 0) {
if (caret.isHere(this)) {
addBlock(0, newBlock);
added = true;
}
int pos = 0;
for (final Block b : content) {
caret.skip(1);
pos++;
added = added | b.appendBlock(caret, newBlock, splitAdjacent);
if (caret.getRemaining() == 0) {
added = added | b.appendBlock(caret, newBlock);
if (caret.isHere(b)) {
addBlock(pos, newBlock);
added = true;
}
}
caret.skip(1);
if (added) {
recomputeDimensions();
}
return added;
}
public boolean deleteBlock(final Caret caret) {
boolean removed = false;
int pos = 0;
for (final Block b : content) {
caret.skip(1);
pos++;
final int deltaCaret = caret.getRemaining();
final int caretOldPos = caret.getPosition();
removed = removed | b.deleteBlock(caret);
if (caret.getRemaining() == 0 || removed == false && deltaCaret >= 0 && caret.getRemaining() < 0) {
ObjectArrayList<Block> blocks = this.getBlockAt(pos - 1).get().getInnerBlocks();
ObjectArrayList<BlockContainer> innerContainers = this.getBlockAt(pos - 1).get().getInnerContainers();
int innerContainersBeforeCaret = 0;
int currentBlockIndex = 0;
if (innerContainers != null) {
for (BlockContainer c : innerContainers) {
currentBlockIndex += c.computeCaretMaxBound();
if (currentBlockIndex > deltaCaret) {
break;
}
innerContainersBeforeCaret++;
}
}
// If the caret is at the end of a block with inner containers don't delete anything and enter into that block.
if (innerContainers == null || (innerContainers.size() - innerContainersBeforeCaret != 0)) {
removeAt(pos - 1);
if (blocks != null) {
ObjectListIterator<Block> blocksIterator = blocks.iterator();
int blockNum = 0;
while (blocksIterator.hasNext()) {
Block block = blocksIterator.next();
addBlockUnsafe(pos - 1 + blockNum, block);
blockNum++;
}
}
caret.setPosition(caretOldPos - innerContainersBeforeCaret);
removed = true;
}
}
}
caret.skip(1);
if (removed) {
recomputeDimensions();
}
return removed;
}
public BlockReference<?> getBlock(final Caret caret) {
BlockReference<?> block = null;
int pos = 0;
for (final Block b : content) {
caret.skip(1);
pos++;
final int deltaCaret = caret.getRemaining();
block = b.getBlock(caret);
if (block != null) {
return block;
}
if (caret.getRemaining() == 0 || deltaCaret >= 0 && caret.getRemaining() < 0) {
block = getBlockAt(pos - 1);
return block;
}
}
caret.skip(1);
return block;
}
@Override
public void recomputeDimensions() {
int l = 0; //Line
@ -430,14 +370,6 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
}
}
public int computeCaretMaxBound() {
int maxpos = 0;
for (final Block b : content) {
maxpos += 1 + b.computeCaretMaxBound();
}
return maxpos + 1;
}
public Function toFunction(final MathContext context) throws Error {
final ObjectArrayList<Block> blocks = getContent();
final ObjectArrayList<Feature> blockFeatures = new ObjectArrayList<>();
@ -454,4 +386,22 @@ public class BlockContainer implements TreeContainer, GraphicalElement {
return result;
}
public <T extends Block> BlockReference<T> getReference(T block) {
var i = content.indexOf(block);
if (i < 0) return null;
return new BlockReference<>(block, i, content, this);
}
public ObjectArrayList<Block> getContentUnsafe() {
return content;
}
public Block getLastBlock() {
return content.isEmpty() ? null : content.get(content.size() - 1);
}
public BlockPosition getLastPosition() {
var lastBlock = getLastBlock();
return lastBlock != null ? new BlockPosition(lastBlock) : new BlockPosition(this);
}
}

View File

@ -19,14 +19,19 @@ public class BlockDivision extends Block {
private int paddingLeftUpper;
private int paddingLeftLower;
private int h1;
private ObjectArrayList<BlockContainer> innerContainers;
public BlockDivision() {
containerUp = new BlockContainer(this, false);
containerDown = new BlockContainer(this, false);
recomputeDimensions();
innerContainers = new ObjectArrayList<>(2);
innerContainers.add(containerUp);
innerContainers.add(containerDown);
}
private BlockDivision(final TreeContainer parent, BlockDivision old, InputContext ic) {
private BlockDivision(final BlockContainer parent, BlockDivision old, InputContext ic) {
super(parent, old);
containerUp = old.containerUp.clone(this, ic);
containerDown = old.containerDown.clone(this, ic);
@ -34,6 +39,10 @@ public class BlockDivision extends Block {
paddingLeftUpper = old.paddingLeftUpper;
h1 = old.h1;
System.out.println(String.join(",", ""+h1, ""+old.h1, ""+line, ""+old.line));
innerContainers = new ObjectArrayList<>(2);
innerContainers.add(containerUp);
innerContainers.add(containerDown);
}
@Override
@ -47,38 +56,16 @@ public class BlockDivision extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
added = added | containerUp.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerDown.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerUp.appendBlock(caret, newBlock);
added = added | containerDown.appendBlock(caret, newBlock);
if (added) {
recomputeDimensions();
}
return added;
}
@Override
public boolean deleteBlock(final Caret caret) {
boolean removed = false;
removed = removed | containerUp.deleteBlock(caret);
removed = removed | containerDown.deleteBlock(caret);
if (removed) {
recomputeDimensions();
}
return removed;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
BlockReference<?> bl = null;
bl = containerUp.getBlock(caret);
if (bl != null) {
return bl;
}
bl = containerDown.getBlock(caret);
return bl;
}
@Override
public void recomputeDimensions() {
final int w1 = containerUp.getWidth();
@ -119,11 +106,6 @@ public class BlockDivision extends Block {
return containerDown;
}
@Override
public int computeCaretMaxBound() {
return containerUp.computeCaretMaxBound() + containerDown.computeCaretMaxBound();
}
@Override
public Feature toFeature(final MathContext context) throws Error {
final Function upper = getUpperContainer().toFunction(context);
@ -140,14 +122,11 @@ public class BlockDivision extends Block {
@Override
public ObjectArrayList<BlockContainer> getInnerContainers() {
ObjectArrayList<BlockContainer> output = new ObjectArrayList<>();
output.add(containerUp);
output.add(containerDown);
return output;
return innerContainers;
}
@Override
public BlockDivision clone(final TreeContainer parent, InputContext ic) {
public BlockDivision clone(final BlockContainer parent, InputContext ic) {
return new BlockDivision(parent, this, ic);
}
}

View File

@ -18,7 +18,7 @@ public class BlockExponentialNotation extends BlockPower {
* @param old
* @param ic
*/
private BlockExponentialNotation(final TreeContainer parent, BlockExponentialNotation old, InputContext ic) {
private BlockExponentialNotation(final BlockContainer parent, BlockExponentialNotation old, InputContext ic) {
super(parent, old, ic);
this.bw = old.bw;
this.bh = old.bh;
@ -41,7 +41,7 @@ public class BlockExponentialNotation extends BlockPower {
}
@Override
public BlockExponentialNotation clone(final TreeContainer parent, InputContext ic) {
public BlockExponentialNotation clone(final BlockContainer parent, InputContext ic) {
return new BlockExponentialNotation(parent, this, ic);
}
}

View File

@ -27,11 +27,16 @@ public class BlockLogarithm extends Block implements IParenthesis {
private int schh;
private int nmbh;
private int toph;
private ObjectArrayList<BlockContainer> innerContainers;
public BlockLogarithm() {
containerBase = new BlockContainer(this, true);
containerNumber = new BlockContainer(this, false);
recomputeDimensions();
innerContainers = new ObjectArrayList<>(2);
innerContainers.add(containerBase);
innerContainers.add(containerNumber);
}
public BlockLogarithm(final ObjectArrayList<Block> blocks) {
@ -40,7 +45,7 @@ public class BlockLogarithm extends Block implements IParenthesis {
recomputeDimensions();
}
private BlockLogarithm(final TreeContainer parent, BlockLogarithm old, InputContext ic) {
private BlockLogarithm(final BlockContainer parent, BlockLogarithm old, InputContext ic) {
super(parent, old);
containerBase = old.containerBase.clone(this, ic);
containerNumber = old.containerNumber.clone(this, ic);
@ -80,38 +85,16 @@ public class BlockLogarithm extends Block implements IParenthesis {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
added = added | containerBase.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerNumber.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerBase.appendBlock(caret, newBlock);
added = added | containerNumber.appendBlock(caret, newBlock);
if (added) {
recomputeDimensions();
}
return added;
}
@Override
public boolean deleteBlock(final Caret caret) {
boolean removed = false;
removed = removed | containerBase.deleteBlock(caret);
removed = removed | containerNumber.deleteBlock(caret);
if (removed) {
recomputeDimensions();
}
return removed;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
BlockReference<?> bl = null;
bl = containerBase.getBlock(caret);
if (bl != null) {
return bl;
}
bl = containerNumber.getBlock(caret);
return bl;
}
@Override
public void recomputeDimensions() {
if (prefix == null) {
@ -163,11 +146,6 @@ public class BlockLogarithm extends Block implements IParenthesis {
return containerNumber;
}
@Override
public int computeCaretMaxBound() {
return containerBase.computeCaretMaxBound() + containerNumber.computeCaretMaxBound();
}
@Override
public Feature toFeature(final MathContext context) throws Error {
final Function base = getBaseContainer().toFunction(context);
@ -185,14 +163,11 @@ public class BlockLogarithm extends Block implements IParenthesis {
@Override
public ObjectArrayList<BlockContainer> getInnerContainers() {
ObjectArrayList<BlockContainer> output = new ObjectArrayList<>();
output.add(containerBase);
output.add(containerNumber);
return output;
return innerContainers;
}
@Override
public BlockLogarithm clone(final TreeContainer parent, InputContext ic) {
public BlockLogarithm clone(final BlockContainer parent, InputContext ic) {
return new BlockLogarithm(parent, this, ic);
}

View File

@ -8,12 +8,12 @@ public class BlockNumericChar extends BlockChar {
super(ch);
}
private BlockNumericChar(final TreeContainer parent, BlockNumericChar old, InputContext ic) {
private BlockNumericChar(final BlockContainer parent, BlockNumericChar old, InputContext ic) {
super(parent, old, ic);
}
@Override
public BlockNumericChar clone(final TreeContainer parent, InputContext ic) {
public BlockNumericChar clone(final BlockContainer parent, InputContext ic) {
return new BlockNumericChar(parent, this, ic);
}
}

View File

@ -0,0 +1,26 @@
package it.cavallium.warppi.gui.expression.blocks;
import it.cavallium.warppi.gui.GraphicalElement;
public interface BlockOrContainer extends GraphicalElement {
BlockOrContainer getParent();
BlockOrContainer getAt(int index);
default void recomputeDimensionsToRoot() {
var parent = this;
while (parent != null) {
parent.recomputeDimensions();
parent = parent.getParent();
}
}
default BlockContainer getRootContainer() {
var parent = this;
while (parent != null) {
parent = parent.getParent();
}
return (BlockContainer) parent;
}
int getIndex();
}

View File

@ -9,13 +9,15 @@ import it.cavallium.warppi.util.Error;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class BlockParenthesis extends BlockParenthesisAbstract {
private ObjectArrayList<BlockContainer> innerContainersCached;
public BlockParenthesis() {}
public BlockParenthesis(final ObjectArrayList<Block> blocks) {
super(blocks);
}
private BlockParenthesis(final TreeContainer parent, BlockParenthesis old, InputContext ic) {
private BlockParenthesis(final BlockContainer parent, BlockParenthesis old, InputContext ic) {
super(parent, old, ic);
}
@ -31,14 +33,7 @@ public class BlockParenthesis extends BlockParenthesisAbstract {
}
@Override
public ObjectArrayList<BlockContainer> getInnerContainers() {
ObjectArrayList<BlockContainer> output = new ObjectArrayList<>();
output.add(getNumberContainer());
return output;
}
@Override
public BlockParenthesis clone(final TreeContainer parent, InputContext ic) {
public BlockParenthesis clone(final BlockContainer parent, InputContext ic) {
return new BlockParenthesis(parent, this, ic);
}

View File

@ -14,6 +14,7 @@ public abstract class BlockParenthesisAbstract extends Block implements IParenth
private final BlockContainer containerNumber;
private final String prefix;
private final ObjectArrayList<BlockContainer> innerContainers;
private int prw;
private int chw;
private int chh;
@ -23,12 +24,18 @@ public abstract class BlockParenthesisAbstract extends Block implements IParenth
this.prefix = prefix;
recomputeDimensions();
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerNumber);
}
public BlockParenthesisAbstract() {
containerNumber = new BlockContainer(this, false);
prefix = null;
recomputeDimensions();
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerNumber);
}
/**
@ -36,19 +43,25 @@ public abstract class BlockParenthesisAbstract extends Block implements IParenth
* @param old
* @param ic
*/
BlockParenthesisAbstract(final TreeContainer parent, BlockParenthesisAbstract old, InputContext ic) {
BlockParenthesisAbstract(final BlockContainer parent, BlockParenthesisAbstract old, InputContext ic) {
super(parent, old);
containerNumber = old.containerNumber.clone(this, ic);
prefix = old.prefix;
prw = old.prw;
chw = old.chw;
chh = old.chh;
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerNumber);
}
public BlockParenthesisAbstract(final ObjectArrayList<Block> blocks) {
containerNumber = new BlockContainer(this, false, blocks);
prefix = null;
recomputeDimensions();
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerNumber);
}
@Override
@ -73,30 +86,15 @@ public abstract class BlockParenthesisAbstract extends Block implements IParenth
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
added = added | containerNumber.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerNumber.appendBlock(caret, newBlock);
if (added) {
recomputeDimensions();
}
return added;
}
@Override
public boolean deleteBlock(final Caret caret) {
boolean removed = false;
removed = removed | containerNumber.deleteBlock(caret);
if (removed) {
recomputeDimensions();
}
return removed;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return containerNumber.getBlock(caret);
}
@Override
public void recomputeDimensions() {
if (prefix == null) {
@ -122,11 +120,6 @@ public abstract class BlockParenthesisAbstract extends Block implements IParenth
return containerNumber;
}
@Override
public int computeCaretMaxBound() {
return containerNumber.computeCaretMaxBound();
}
@Override
public abstract Feature toFeature(MathContext context) throws Error;
@ -139,9 +132,7 @@ public abstract class BlockParenthesisAbstract extends Block implements IParenth
@Override
public ObjectArrayList<BlockContainer> getInnerContainers() {
ObjectArrayList<BlockContainer> output = new ObjectArrayList<>();
output.add(containerNumber);
return output;
return innerContainers;
}
}

View File

@ -0,0 +1,196 @@
package it.cavallium.warppi.gui.expression.blocks;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntCollections;
import org.apache.commons.lang3.NotImplementedException;
import java.util.Collections;
import java.util.Objects;
public final class BlockPosition {
private final BlockOrContainer pos;
public BlockPosition(BlockOrContainer pos) {
this.pos = pos;
}
public BlockPosition(Block block) {
this.pos = block;
}
public BlockPosition(BlockContainer container) {
this.pos = container;
}
public boolean isBlock() {
return pos instanceof Block;
}
public boolean isContainer() {
return pos instanceof BlockContainer;
}
public Block getBlock() {
return (Block) pos;
}
public BlockContainer getContainer() {
return (BlockContainer) pos;
}
public BlockOrContainer get() {
return pos;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (BlockPosition) obj;
return Objects.equals(this.pos, that.pos);
}
@Override
public int hashCode() {
return Objects.hash(pos);
}
@Override
public String toString() {
return "BlockPosition[" +
"pos=" + pos + ']';
}
public BlockPosition getNext() {
if (pos instanceof BlockContainer) {
var container = (BlockContainer) pos;
var content = container.getContent();
if (content.isEmpty()) {
BlockContainer nextContainer;
if (container.hasParent()) {
var containers = container.getParentBlock().getInnerContainers();
var it = containers.listIterator(containers.indexOf(container) + 1);
nextContainer = it.hasNext() ? it.next() : null;
} else {
nextContainer = null;
}
if (nextContainer != null) {
return new BlockPosition(nextContainer);
} else {
var parentBlock = container.getParentBlock();
return parentBlock != null ? new BlockPosition(parentBlock) : null;
}
} else {
var targetBlock = content.get(0);
var innerContainers = targetBlock.getInnerContainers();
if (innerContainers != null && !innerContainers.isEmpty()) {
return new BlockPosition(innerContainers.get(0));
} else {
return new BlockPosition(targetBlock);
}
}
} else if (pos instanceof Block) {
var block = (Block) pos;
var ref = block.getReference();
var nextBlock = ref.getNextBlock();
if (nextBlock == null) {
var container = block.getParentContainer();
BlockContainer nextContainer;
if (container.hasParent()) {
var containers = container.getParentBlock().getInnerContainers();
var it = containers.listIterator(containers.indexOf(container) + 1);
nextContainer = it.hasNext() ? it.next() : null;
} else {
nextContainer = null;
}
if (nextContainer != null) {
return new BlockPosition(nextContainer);
} else {
var parentBlock = container.getParentBlock();
return parentBlock != null ? new BlockPosition(parentBlock) : null;
}
} else {
var targetBlock = nextBlock.get();
var innerContainers = targetBlock.getInnerContainers();
if (innerContainers != null && !innerContainers.isEmpty()) {
return new BlockPosition(innerContainers.get(0));
} else {
return new BlockPosition(targetBlock);
}
}
} else {
throw new UnsupportedOperationException();
}
}
public BlockPosition getPrevious() {
if (pos instanceof BlockContainer) {
var container = (BlockContainer) pos;
if (container.hasParent()) {
var parentBlock = container.getParentBlock();
var innerContainers = parentBlock.getInnerContainers();
if (innerContainers != null) {
var it = innerContainers.listIterator(innerContainers.indexOf(container));
if (it.hasPrevious()) {
var prevContainer = it.previous();
var prevContainerLastBlock = prevContainer.getLastBlock();
if (prevContainerLastBlock != null) {
return new BlockPosition(prevContainerLastBlock);
} else {
return new BlockPosition(prevContainer);
}
} else {
var parentContainer = parentBlock.getParentContainer();
var blocks = parentContainer.getContentUnsafe();
var bIt = blocks.listIterator(blocks.indexOf(parentBlock));
if (bIt.hasPrevious()) {
return new BlockPosition(bIt.previous());
} else {
return new BlockPosition(parentContainer);
}
}
} else {
throw new UnsupportedOperationException();
}
} else {
return null;
}
} else if (pos instanceof Block) {
var block = (Block) pos;
var innerContainers = block.getInnerContainers();
if (innerContainers != null) {
var lastContainer = innerContainers.get(innerContainers.size() - 1);
var lastBlock = lastContainer.getLastBlock();
if (lastBlock != null) {
return new BlockPosition(lastBlock);
} else {
return new BlockPosition(lastContainer);
}
}
var ref = block.getReference();
var prevBlock = ref.getPreviousBlock();
if (prevBlock == null) {
var container = block.getParentContainer();
return new BlockPosition(container);
} else {
var targetBlock = prevBlock.get();
return new BlockPosition(targetBlock);
}
} else {
throw new UnsupportedOperationException();
}
}
public IntArrayList getURL() {
var url = new IntArrayList();
var parent = pos;
while (parent != null) {
var index = parent.getIndex();
if (index == -1) break;
url.add(index);
parent = parent.getParent();
}
Collections.reverse(url);
return url;
}
}

View File

@ -14,15 +14,22 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class BlockPower extends Block {
private final BlockContainer containerExponent;
private final ObjectArrayList<BlockContainer> innerContainers;
public BlockPower() {
containerExponent = new BlockContainer(this, true);
recomputeDimensions();
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerExponent);
}
protected BlockPower(final TreeContainer parent, BlockPower old, InputContext ic) {
protected BlockPower(final BlockContainer parent, BlockPower old, InputContext ic) {
super(parent, old);
this.containerExponent = old.containerExponent.clone(this, ic);
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerExponent);
}
@Override
@ -33,29 +40,14 @@ public class BlockPower extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
added = added | containerExponent.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerExponent.appendBlock(caret, newBlock);
if (added) {
recomputeDimensions();
}
return added;
}
@Override
public boolean deleteBlock(Caret caret) {
boolean removed = false;
removed = removed | containerExponent.deleteBlock(caret);
if (removed) {
recomputeDimensions();
}
return removed;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return containerExponent.getBlock(caret);
}
@Override
public void recomputeDimensions() {
@ -77,11 +69,6 @@ public class BlockPower extends Block {
return containerExponent;
}
@Override
public int computeCaretMaxBound() {
return containerExponent.computeCaretMaxBound();
}
@Override
public Feature toFeature(final MathContext context) throws Error {
final Function exp = getExponentContainer().toFunction(context);
@ -95,13 +82,11 @@ public class BlockPower extends Block {
@Override
public ObjectArrayList<BlockContainer> getInnerContainers() {
ObjectArrayList<BlockContainer> output = new ObjectArrayList<>();
output.add(containerExponent);
return output;
return innerContainers;
}
@Override
public BlockPower clone(final TreeContainer parent, InputContext ic) {
public BlockPower clone(final BlockContainer parent, InputContext ic) {
return new BlockPower(parent, this, ic);
}
}

View File

@ -14,21 +14,23 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class BlockPower2 extends Block {
private final BlockContainer containerExponent;
private final ObjectArrayList<BlockContainer> innerContainers;
public BlockPower2() {
containerExponent = new BlockContainer(this, true);
containerExponent.addBlock(0, new BlockNumericChar('2'));
recomputeDimensions();
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerExponent);
}
private BlockPower2(final TreeContainer parent, BlockPower2 old, InputContext ic) {
private BlockPower2(final BlockContainer parent, BlockPower2 old, InputContext ic) {
super(parent, old);
this.containerExponent = old.containerExponent.clone(this, ic);
}
@Override
public int getCaretDeltaPositionAfterCreation() {
return 3;
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerExponent);
}
@Override
@ -39,30 +41,15 @@ public class BlockPower2 extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
added = added | containerExponent.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerExponent.appendBlock(caret, newBlock);
if (added) {
recomputeDimensions();
}
return added;
}
@Override
public boolean deleteBlock(final Caret caret) {
boolean removed = false;
removed = removed | containerExponent.deleteBlock(caret);
if (removed) {
recomputeDimensions();
}
return removed;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return containerExponent.getBlock(caret);
}
@Override
public void recomputeDimensions() {
final int w2 = containerExponent.getWidth();
@ -83,11 +70,6 @@ public class BlockPower2 extends Block {
return containerExponent;
}
@Override
public int computeCaretMaxBound() {
return containerExponent.computeCaretMaxBound();
}
@Override
public Feature toFeature(final MathContext context) throws Error {
final Function exp = getExponentContainer().toFunction(context);
@ -101,13 +83,11 @@ public class BlockPower2 extends Block {
@Override
public ObjectArrayList<BlockContainer> getInnerContainers() {
ObjectArrayList<BlockContainer> output = new ObjectArrayList<>();
output.add(containerExponent);
return output;
return innerContainers;
}
@Override
public BlockPower2 clone(final TreeContainer parent, InputContext ic) {
public BlockPower2 clone(final BlockContainer parent, InputContext ic) {
return new BlockPower2(parent, this, ic);
}
}

View File

@ -1,13 +1,17 @@
package it.cavallium.warppi.gui.expression.blocks;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class BlockReference<T extends Block> {
private final T block;
private final BlockContainer container;
private final int blockPosition;
private int cachedBlockPosition;
private final ObjectArrayList<Block> containerBlocks;
public BlockReference(final T block, final int blockPosition, final BlockContainer container) {
public BlockReference(final T block, final int cachedBlockPosition, final ObjectArrayList<Block> containerBlocks, final BlockContainer container) {
this.block = block;
this.blockPosition = blockPosition;
this.cachedBlockPosition = cachedBlockPosition;
this.containerBlocks = containerBlocks;
this.container = container;
}
@ -20,23 +24,28 @@ public class BlockReference<T extends Block> {
}
public int getIndex() {
return blockPosition;
if (containerBlocks.size() > cachedBlockPosition && cachedBlockPosition >= 0
&& containerBlocks.get(cachedBlockPosition) == block) {
return cachedBlockPosition;
} else {
return cachedBlockPosition = containerBlocks.indexOf(block);
}
}
public BlockReference<?> getNextBlock() {
return getBlockAtSafe(this.blockPosition + 1);
return getBlockAtSafe(getIndex() + 1);
}
public boolean hasNextBlock() {
return isInsideBounds(this.blockPosition + 1);
return isInsideBounds(getIndex() + 1);
}
public BlockReference<?> getPreviousBlock() {
return getBlockAtSafe(this.blockPosition - 1);
return getBlockAtSafe(getIndex() - 1);
}
public boolean hasPreviousBlock() {
return isInsideBounds(this.blockPosition - 1);
return isInsideBounds(getIndex() - 1);
}
private BlockReference<?> getBlockAtSafe(final int i) {

View File

@ -13,7 +13,7 @@ public class BlockSine extends BlockParenthesisAbstract {
super("SIN");
}
private BlockSine(final TreeContainer parent, BlockSine old, InputContext ic) {
private BlockSine(final BlockContainer parent, BlockSine old, InputContext ic) {
super(parent, old, ic);
}
@ -24,7 +24,7 @@ public class BlockSine extends BlockParenthesisAbstract {
}
@Override
public BlockSine clone(final TreeContainer parent, InputContext ic) {
public BlockSine clone(final BlockContainer parent, InputContext ic) {
return new BlockSine(parent, this, ic);
}
}

View File

@ -14,18 +14,23 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class BlockSquareRoot extends Block {
private final BlockContainer containerNumber;
private final ObjectArrayList<BlockContainer> innerContainers;
private int h1;
public BlockSquareRoot() {
containerNumber = new BlockContainer(this, false);
recomputeDimensions();
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerNumber);
}
private BlockSquareRoot(final TreeContainer parent, BlockSquareRoot old, InputContext ic) {
private BlockSquareRoot(final BlockContainer parent, BlockSquareRoot old, InputContext ic) {
super(parent, old);
this.containerNumber = old.containerNumber.clone(this, ic);
this.h1 = old.h1;
innerContainers = new ObjectArrayList<>(1);
innerContainers.add(containerNumber);
}
@Override
@ -44,30 +49,15 @@ public class BlockSquareRoot extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
boolean added = false;
added = added | containerNumber.appendBlock(caret, newBlock, splitAdjacent);
added = added | containerNumber.appendBlock(caret, newBlock);
if (added) {
recomputeDimensions();
}
return added;
}
@Override
public boolean deleteBlock(final Caret caret) {
boolean removed = false;
removed = removed | containerNumber.deleteBlock(caret);
if (removed) {
recomputeDimensions();
}
return removed;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return containerNumber.getBlock(caret);
}
@Override
public void recomputeDimensions() {
final int w1 = containerNumber.getWidth();
@ -93,11 +83,6 @@ public class BlockSquareRoot extends Block {
return containerNumber;
}
@Override
public int computeCaretMaxBound() {
return containerNumber.computeCaretMaxBound();
}
@Override
public Feature toFeature(final MathContext context) throws Error {
final Function contnt = getNumberContainer().toFunction(context);
@ -119,7 +104,7 @@ public class BlockSquareRoot extends Block {
}
@Override
public BlockSquareRoot clone(final TreeContainer parent, InputContext ic) {
public BlockSquareRoot clone(final BlockContainer parent, InputContext ic) {
return new BlockSquareRoot(parent, this, ic);
}
}

View File

@ -16,7 +16,7 @@ public class BlockUndefined extends Block {
recomputeDimensions();
}
private BlockUndefined(final TreeContainer parent, BlockUndefined old, InputContext ic) {
private BlockUndefined(final BlockContainer parent, BlockUndefined old, InputContext ic) {
super(parent, old);
}
@ -28,20 +28,10 @@ public class BlockUndefined extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
return false;
}
@Override
public boolean deleteBlock(final Caret caret) {
return false;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return null;
}
@Override
public void recomputeDimensions() {
width = BlockContainer.getDefaultFont(small).getStringWidth("UNDEFINED");
@ -55,11 +45,6 @@ public class BlockUndefined extends Block {
recomputeDimensions();
}
@Override
public int computeCaretMaxBound() {
return 0;
}
@Override
public Feature toFeature(final MathContext context) {
return new FeatureChar(MathematicalSymbols.UNDEFINED);
@ -76,7 +61,7 @@ public class BlockUndefined extends Block {
}
@Override
public BlockUndefined clone(final TreeContainer parent, InputContext ic) {
public BlockUndefined clone(final BlockContainer parent, InputContext ic) {
return new BlockUndefined(parent, this, ic);
}

View File

@ -43,7 +43,7 @@ public class BlockVariable extends Block {
recomputeDimensions();
}
private BlockVariable(final TreeContainer parent, BlockVariable old, InputContext ic) {
private BlockVariable(final BlockContainer parent, BlockVariable old, InputContext ic) {
super(parent, old);
this.ic = ic;
this.ch = old.ch;
@ -106,20 +106,10 @@ public class BlockVariable extends Block {
}
@Override
public boolean appendBlock(final Caret caret, final Block newBlock, boolean splitAdjacent) {
public boolean appendBlock(final Caret caret, final Block newBlock) {
return false;
}
@Override
public boolean deleteBlock(final Caret caret) {
return false;
}
@Override
public BlockReference<?> getBlock(final Caret caret) {
return null;
}
@Override
public void recomputeDimensions() {
width = BlockContainer.getDefaultCharWidth(small);
@ -137,11 +127,6 @@ public class BlockVariable extends Block {
return ch;
}
@Override
public int computeCaretMaxBound() {
return 0;
}
@Override
public ExtraMenu<?> getExtraMenu() {
return menu;
@ -271,7 +256,7 @@ public class BlockVariable extends Block {
}
@Override
public VariableMenu clone(final TreeContainer parent, InputContext ic) {
public VariableMenu clone(final BlockContainer parent, InputContext ic) {
return new VariableMenu(this, block.clone(parent, ic));
}
@ -293,7 +278,7 @@ public class BlockVariable extends Block {
}
@Override
public BlockVariable clone(final TreeContainer parent, InputContext ic) {
public BlockVariable clone(final BlockContainer parent, InputContext ic) {
return new BlockVariable(parent, this, ic);
}
}

View File

@ -7,10 +7,7 @@ import it.cavallium.warppi.gui.expression.Caret;
import it.cavallium.warppi.gui.expression.CaretState;
import it.cavallium.warppi.gui.expression.ExtraMenu;
import it.cavallium.warppi.gui.expression.InputContext;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockDivision;
import it.cavallium.warppi.gui.expression.blocks.BlockReference;
import it.cavallium.warppi.gui.expression.blocks.*;
import it.cavallium.warppi.gui.expression.layouts.InputLayout;
import it.cavallium.warppi.gui.graphicengine.Renderer;
import it.cavallium.warppi.math.Function;
@ -23,7 +20,6 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
protected Caret caret;
private static final float CARET_DURATION = 0.5f;
private float caretTime;
private int maxPosition = 0;
private boolean parsed = false;
private ExtraMenu<?> extra;
protected InputContext inputContext;
@ -50,8 +46,8 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
public InputContainer(final InputContext ic, final boolean small, final int minWidth, final int minHeight) {
inputContext = ic;
caret = new Caret(CaretState.VISIBLE_ON, 0);
root = new BlockContainer(null, small, false);
caret = new Caret(CaretState.VISIBLE_ON, new BlockPosition(root));
}
/**
@ -62,10 +58,9 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
protected InputContainer(InputContainer old, InputContext ic) {
this.caretTime = old.caretTime;
this.extra = old.extra == null ? null : old.extra.clone(null, ic);
this.maxPosition = old.maxPosition;
this.caret = old.caret == null ? null : new Caret(old.caret);
this.inputContext = ic;
this.root = old.root == null ? null : old.root.clone(null, ic);
this.caret = old.caret == null ? null : new Caret(old.caret, root);
this.parsed = old.parsed;
}
@ -76,14 +71,9 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
public void typeBlock(final Block b) {
if (b != null) {
caret.resetRemaining();
// todo: allow blocks to dinamically choose insert mode
var splitAdjacent = b instanceof BlockDivision;
if (root.appendBlock(caret, b, splitAdjacent)) {
caret.setPosition(caret.getPosition() + b.getCaretDeltaPositionAfterCreation());
maxPosition = root.computeCaretMaxBound();
if (root.appendBlock(caret, b)) {
var innerPos = b.getFirstInnerPosition();
caret.setPosition(innerPos == null ? new BlockPosition(b) : innerPos);
root.recomputeDimensions();
}
closeExtra();
@ -97,13 +87,71 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
}
public void del() {
caret.resetRemaining();
if (root.deleteBlock(caret)) {
root.recomputeDimensions();
var pos = caret.getPos();
BlockOrContainer currentElementToRecompute;
boolean removed;
if (pos.isBlock()) {
var block = pos.getBlock();
var lastInnerPosition = block.getLastInnerPosition();
if (lastInnerPosition != null) {
caret.setPosition(lastInnerPosition);
currentElementToRecompute = null;
removed = false;
} else {
caret.setPosition(pos.getPrevious());
var parent = block.getParentContainer();
parent.removeBlockUnsafe(block);
currentElementToRecompute = parent;
removed = true;
}
} else if (pos.isContainer()) {
var container = pos.getContainer();
if (container == root) {
currentElementToRecompute = null;
removed = false;
} else if (!container.hasParent()) {
throw new IllegalStateException();
} else {
var block = container.getParentBlock();
var containers = block.getInnerContainers();
BlockContainer prevContainer;
if (containers == null) {
prevContainer = null;
} else {
var containerIt = containers.listIterator(containers.indexOf(container));
if (containerIt.hasPrevious()) {
prevContainer = containerIt.previous();
} else {
prevContainer = null;
}
}
if (prevContainer != null) {
var lastBlock = prevContainer.getLastBlock();
if (lastBlock != null) {
caret.setPosition(new BlockPosition(lastBlock));
currentElementToRecompute = null;
removed = false;
} else {
caret.setPosition(new BlockPosition(prevContainer));
currentElementToRecompute = null;
removed = false;
}
} else {
caret.setPosition(pos.getPrevious());
var parentContainer = block.getParentContainer();
parentContainer.removeBlockUnsafe(block);
currentElementToRecompute = parentContainer;
removed = true;
}
}
} else {
throw new UnsupportedOperationException();
}
if (caret.getPosition() > 0) {
caret.setPosition(caret.getPosition() - 1);
maxPosition = root.computeCaretMaxBound();
if (removed) {
while (currentElementToRecompute != null) {
currentElementToRecompute.recomputeDimensions();
currentElementToRecompute = currentElementToRecompute.getParent();
}
}
caret.turnOn();
caretTime = 0;
@ -111,46 +159,25 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
}
public BlockReference<?> getSelectedBlock() {
caret.resetRemaining();
final BlockReference<?> selectedBlock = root.getBlock(caret);
return selectedBlock;
}
public BlockReference<?> getBlockAtCaretPosition(final int i) {
final BlockReference<?> selectedBlock = root.getBlock(new Caret(CaretState.HIDDEN, i));
return selectedBlock;
var pos = caret.getPos();
if (pos.isBlock()) {
return pos.getBlock().getReference();
} else {
var container = pos.getContainer();
if (container.hasParent()) {
return container.getParentBlock().getReference();
} else {
return null;
}
}
}
public void moveLeft() {
final int curPos = caret.getPosition();
if (curPos > 0) {
caret.setPosition(curPos - 1);
var prev = caret.getPos().getPrevious();
if (prev != null) {
caret.setPosition(prev);
} else {
caret.setPosition(maxPosition - 1);
}
caret.turnOn();
caretTime = 0;
closeExtra();
}
public void moveRight(final int delta) {
final int curPos = caret.getPosition();
if (curPos + delta < maxPosition) {
caret.setPosition(curPos + delta);
} else {
caret.setPosition(0);
}
caret.turnOn();
caretTime = 0;
closeExtra();
}
public void moveTo(final int position) {
if (position < maxPosition) {
caret.setPosition(position);
} else {
caret.setPosition(0);
caret.setPosition(new BlockPosition(root.getLastBlock()));
}
caret.turnOn();
caretTime = 0;
@ -158,7 +185,22 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
}
public void moveRight() {
moveRight(1);
var prev = caret.getPos().getNext();
if (prev != null) {
caret.setPosition(prev);
} else {
caret.setPosition(new BlockPosition(root));
}
caret.turnOn();
caretTime = 0;
closeExtra();
}
public void moveTo(final BlockPosition position) {
caret.setPosition(position);
caret.turnOn();
caretTime = 0;
closeExtra();
}
@Override
@ -217,7 +259,6 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
* Position relative to the window.
*/
public void draw(final DisplayOutputDevice ge, final Renderer r, final int x, final int y) {
caret.resetRemaining();
root.draw(ge, r, x, y, caret);
if (extra != null) {
extra.draw(ge, r, caret);
@ -225,27 +266,13 @@ public abstract class InputContainer implements GraphicalElement, InputLayout {
}
public void clear() {
caret = new Caret(CaretState.VISIBLE_ON, 0);
caret = new Caret(CaretState.VISIBLE_ON, new BlockPosition(root));
root.clear();
maxPosition = root.computeCaretMaxBound();
recomputeDimensions();
}
public boolean isEmpty() {
return maxPosition <= 1;
}
public int getCaretMaxPosition() {
return maxPosition;
}
public void setCaretPosition(final int pos) {
if (pos > 0 && pos < maxPosition) {
caret.setPosition(pos);
}
caret.turnOn();
caretTime = 0;
closeExtra();
return root.getSize() == 0;
}
public void setParsed(final boolean parsed) {

View File

@ -6,6 +6,9 @@ import it.cavallium.warppi.gui.expression.InputContext;
import it.cavallium.warppi.gui.expression.blocks.*;
import it.cavallium.warppi.math.MathematicalSymbols;
import java.util.ArrayList;
import java.util.List;
public class NormalInputContainer extends InputContainer {
@Deprecated()
@ -30,7 +33,6 @@ public class NormalInputContainer extends InputContainer {
/**
* Copy
* @param userInput
* @param ic
*/
public NormalInputContainer(InputContainer old, InputContext ic) {
@ -93,36 +95,24 @@ public class NormalInputContainer extends InputContainer {
switch (c) {
case MathematicalSymbols.PARENTHESIS_CLOSE: {
final BlockReference<?> ref = getSelectedBlock();
if (ref == null) {
BlockParenthesisAbstract parenthesis = findParenthesis(ref.get());
if (parenthesis == null) {
break;
} else {
final Caret newCaret = new Caret(CaretState.HIDDEN, caret.getPosition());
BlockContainer currentContainer;
BlockReference<?> newRef = ref;
int safeExit = 0;
do {
currentContainer = (BlockContainer) newRef.get().getParentContainer();
final int initialRelativeIndex = currentContainer.getContent().indexOf(newRef.get());
final int newIndex = newCaret.getPosition() + currentContainer.getContent().size() - initialRelativeIndex;
newRef = getBlockAtCaretPosition(newIndex);
newCaret.setPosition(newIndex);
safeExit++;
} while (newRef != null && newRef.get() instanceof IParenthesis == false && currentContainer != null && safeExit < 100000);
if (safeExit >= 100000) {
System.err.println("Error 0x001030: Infinite loop");
}
if (newRef != null) {
moveTo(newCaret.getPosition());
}
moveTo(new BlockPosition(parenthesis));
}
break;
}
case MathematicalSymbols.POWER_OF_TWO:
moveTo(new BlockPosition(getSelectedBlock().get()));
break;
case MathematicalSymbols.DIVISION: {
@SuppressWarnings("unchecked")
final BlockReference<BlockDivision> ref = (BlockReference<BlockDivision>) getSelectedBlock();
@SuppressWarnings("unused")
final BlockContainer parentContainer = ref.getContainer();
BlockReference<?> currentBlock = ref;
List<Block> blocksToMove = new ArrayList<>();
boolean groupedBefore = false;
int before = 0;
while (true) {
@ -135,28 +125,39 @@ public class NormalInputContainer extends InputContainer {
if (!groupedBefore) {
groupedBefore = true;
}
blocksToMove.add(b);
before++;
} else {
break;
}
}
if (groupedBefore) {
moveLeft();
for (int i = 0; i < before; i++) {
final BlockReference<?> b = getSelectedBlock();
del();
moveRight();
typeBlock(b.get());
moveLeft();
moveLeft();
var div = ref.get();
var upperContainer = div.getUpperContainer();
for (int i = blocksToMove.size() - 1; i >= 0; i--) {
var b = blocksToMove.get(i);
b.getParentContainer().removeBlockUnsafe(b);
upperContainer.appendBlock(b);
}
for (int i = 0; i < before + 1; i++) {
moveRight();
}
moveRight();// Move to the divisor
div.recomputeDimensionsToRoot();
moveTo(new BlockPosition(div.getLowerContainer()));
}
break;
}
}
}
private BlockParenthesisAbstract findParenthesis(Block o) {
while (!(o instanceof BlockParenthesisAbstract)) {
var pc = o.getParentContainer();
if (!pc.hasParent()) {
return null;
}
o = pc.getParentBlock();
if (o == null) {
return null;
}
}
return (BlockParenthesisAbstract) o;
}
}

View File

@ -6,6 +6,7 @@ import it.cavallium.warppi.gui.expression.Caret;
import it.cavallium.warppi.gui.expression.CaretState;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockPosition;
import it.cavallium.warppi.gui.expression.layouts.OutputLayout;
import it.cavallium.warppi.gui.graphicengine.Renderer;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
@ -13,21 +14,27 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public abstract class OutputContainer implements GraphicalElement, OutputLayout {
private static final long serialVersionUID = -5714825964892683571L;
public final ObjectArrayList<BlockContainer> roots;
private final Caret caret = new Caret(CaretState.HIDDEN, 0);
private final Caret caret;
public OutputContainer() {
roots = new ObjectArrayList<>();
roots.add(new BlockContainer());
var root = new BlockContainer();
roots.add(root);
caret = new Caret(CaretState.HIDDEN, new BlockPosition(root));
}
public OutputContainer(final boolean small) {
roots = new ObjectArrayList<>();
roots.add(new BlockContainer(null, small));
var root = new BlockContainer(null, small);
roots.add(root);
caret = new Caret(CaretState.HIDDEN, new BlockPosition(root));
}
public OutputContainer(final boolean small, final int minWidth, final int minHeight) {
roots = new ObjectArrayList<>();
roots.add(new BlockContainer(null, small));
var root = new BlockContainer(null, small);
roots.add(root);
caret = new Caret(CaretState.HIDDEN, new BlockPosition(root));
}
public void setContentAsSingleGroup(final ObjectArrayList<Block> blocks) {