Refactor caret positioning
This commit is contained in:
parent
3031966145
commit
7ae4315837
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user