2018-09-02 13:36:49 +02:00
package it.cavallium.warppi.gui.expression.blocks ;
2017-03-03 23:06:43 +01:00
2018-10-04 23:39:19 +02:00
import java.util.Arrays ;
2019-02-27 23:29:03 +01:00
import it.cavallium.warppi.WarpPI ;
import it.cavallium.warppi.device.display.DisplayOutputDevice ;
2018-09-02 13:36:49 +02:00
import it.cavallium.warppi.gui.GraphicalElement ;
import it.cavallium.warppi.gui.expression.Caret ;
import it.cavallium.warppi.gui.expression.CaretState ;
2018-10-04 23:39:19 +02:00
import it.cavallium.warppi.gui.expression.InputContext ;
2018-09-02 13:36:49 +02:00
import it.cavallium.warppi.gui.graphicengine.BinaryFont ;
import it.cavallium.warppi.gui.graphicengine.Renderer ;
import it.cavallium.warppi.math.Function ;
import it.cavallium.warppi.math.MathContext ;
import it.cavallium.warppi.math.parser.MathParser ;
import it.cavallium.warppi.math.parser.features.interfaces.Feature ;
2018-09-12 22:16:33 +02:00
import it.cavallium.warppi.util.Error ;
import it.cavallium.warppi.util.Errors ;
2017-05-16 22:02:44 +02:00
import it.unimi.dsi.fastutil.objects.ObjectArrayList ;
2018-10-04 08:49:11 +02:00
import it.unimi.dsi.fastutil.objects.ObjectListIterator ;
2017-05-16 22:02:44 +02:00
2018-09-22 14:10:36 +02:00
public class BlockContainer implements TreeContainer , GraphicalElement {
2017-03-03 23:06:43 +01:00
2017-03-26 22:44:09 +02:00
private static boolean initialized = false ;
2017-04-10 22:50:43 +02:00
2017-04-11 22:04:44 +02:00
private int minWidth ;
private int minHeight ;
2017-03-03 23:06:43 +01:00
private final ObjectArrayList < Block > content ;
private boolean small ;
private int width ;
private int height ;
private int line ;
2017-03-26 22:44:09 +02:00
public final boolean withBorder ;
2017-04-11 22:04:44 +02:00
private boolean autoMinimums ;
2018-09-28 11:39:28 +02:00
private final TreeBlock parent ;
2017-04-10 22:50:43 +02:00
2018-10-04 23:39:19 +02:00
public BlockContainer ( ) {
this ( null , false , BlockContainer . getDefaultCharWidth ( false ) , BlockContainer . getDefaultCharHeight ( false ) , true ) ;
autoMinimums = true ;
}
2018-09-28 11:39:28 +02:00
public BlockContainer ( final TreeBlock parent ) {
2018-09-22 14:10:36 +02:00
this ( parent , false , BlockContainer . getDefaultCharWidth ( false ) , BlockContainer . getDefaultCharHeight ( false ) , true ) ;
2017-04-11 22:04:44 +02:00
autoMinimums = true ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2018-09-28 11:39:28 +02:00
public BlockContainer ( final TreeBlock parent , final boolean small ) {
2018-09-22 14:10:36 +02:00
this ( parent , small , BlockContainer . getDefaultCharWidth ( small ) , BlockContainer . getDefaultCharHeight ( small ) , true ) ;
2017-04-11 22:04:44 +02:00
autoMinimums = true ;
2017-03-26 22:44:09 +02:00
}
2017-04-10 22:50:43 +02:00
2018-09-28 11:39:28 +02:00
public BlockContainer ( final TreeBlock parent , final boolean small , final ObjectArrayList < Block > content ) {
2018-09-22 14:10:36 +02:00
this ( parent , small , BlockContainer . getDefaultCharWidth ( small ) , BlockContainer . getDefaultCharHeight ( small ) , content , true ) ;
2017-11-01 22:34:35 +01:00
autoMinimums = true ;
}
2018-09-28 11:39:28 +02:00
public BlockContainer ( final TreeBlock parent , final boolean small , final boolean withBorder ) {
2018-09-22 14:10:36 +02:00
this ( parent , small , BlockContainer . getDefaultCharWidth ( small ) , BlockContainer . getDefaultCharHeight ( small ) , withBorder ) ;
2017-04-11 22:04:44 +02:00
autoMinimums = true ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2018-09-28 11:39:28 +02:00
public BlockContainer ( final TreeBlock parent , final boolean small , final int minWidth , final int minHeight , final boolean withBorder ) {
2018-09-22 14:10:36 +02:00
this ( parent , small , minWidth , minHeight , new ObjectArrayList < > ( ) , withBorder ) ;
2017-04-11 22:04:44 +02:00
autoMinimums = false ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2018-09-28 11:39:28 +02:00
public BlockContainer ( final TreeBlock parent , final boolean small , final int minWidth , final int minHeight , final ObjectArrayList < Block > content , final boolean withBorder ) {
2018-09-22 14:10:36 +02:00
this . parent = parent ;
2017-03-03 23:06:43 +01:00
this . small = small ;
this . minWidth = minWidth ;
this . minHeight = minHeight ;
2017-03-26 22:44:09 +02:00
this . withBorder = withBorder ;
2018-09-28 11:39:28 +02:00
for ( final Block b : content ) {
if ( b . isSmall ( ) ! = small ) {
2017-03-26 22:44:09 +02:00
b . setSmall ( small ) ;
2018-09-28 11:39:28 +02:00
}
}
2017-03-03 23:06:43 +01:00
this . content = content ;
recomputeDimensions ( ) ;
}
2018-09-28 11:39:28 +02:00
2018-10-09 23:51:42 +02:00
private BlockContainer ( final TreeBlock parent , BlockContainer old , InputContext ic ) {
2018-10-04 23:39:19 +02:00
this . autoMinimums = old . autoMinimums ;
this . content = new ObjectArrayList < > ( ) ;
for ( Block b : old . content ) {
2018-10-09 23:51:42 +02:00
this . content . add ( b . clone ( this , ic ) ) ;
2018-10-04 23:39:19 +02:00
}
2018-10-09 23:51:42 +02:00
2018-10-04 23:39:19 +02:00
this . height = old . height ;
this . line = old . line ;
this . minHeight = old . minHeight ;
this . minWidth = old . minWidth ;
2018-10-09 23:51:42 +02:00
this . parent = parent ;
2018-10-04 23:39:19 +02:00
this . small = old . small ;
this . width = old . width ;
this . withBorder = old . withBorder ;
}
2018-10-09 23:51:42 +02:00
public BlockContainer clone ( final TreeBlock parent , InputContext ic ) {
return new BlockContainer ( parent , this , ic ) ;
2018-10-04 23:39:19 +02:00
}
2018-09-22 14:10:36 +02:00
@Override
public TreeBlock getParentBlock ( ) {
return parent ;
}
@Override
public boolean hasParent ( ) {
return parent ! = null ;
}
2017-03-26 22:44:09 +02:00
2018-09-22 11:17:30 +02:00
public void addBlock ( final int position , final Block b ) {
2018-03-11 21:49:41 +01:00
addBlockUnsafe ( position , b ) ;
recomputeDimensions ( ) ;
}
2018-05-12 21:18:29 +02:00
2018-09-22 11:17:30 +02:00
public void addBlockUnsafe ( final int position , final Block b ) {
2018-09-22 14:10:36 +02:00
b . setParent ( this ) ;
2018-09-28 11:39:28 +02:00
if ( b . isSmall ( ) ! = small ) {
2017-03-26 22:44:09 +02:00
b . setSmall ( small ) ;
2018-09-28 11:39:28 +02:00
}
if ( position > = content . size ( ) ) {
2017-03-26 22:44:09 +02:00
content . add ( b ) ;
2018-09-28 11:39:28 +02:00
} else {
2017-03-26 22:44:09 +02:00
content . add ( position , b ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-26 22:44:09 +02:00
}
2017-04-10 22:50:43 +02:00
2018-09-22 11:17:30 +02:00
public void appendBlock ( final Block b ) {
2017-04-10 22:50:43 +02:00
appendBlockUnsafe ( b ) ;
recomputeDimensions ( ) ;
}
2018-09-22 11:17:30 +02:00
public void appendBlockUnsafe ( final Block b ) {
2018-09-22 14:10:36 +02:00
b . setParent ( this ) ;
2018-09-28 11:39:28 +02:00
if ( b . isSmall ( ) ! = small ) {
2017-03-26 22:44:09 +02:00
b . setSmall ( small ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-03 23:06:43 +01:00
content . add ( b ) ;
}
2018-09-22 11:17:30 +02:00
public void removeBlock ( final Block b ) {
2018-03-11 21:49:41 +01:00
removeBlockUnsafe ( b ) ;
2017-03-03 23:06:43 +01:00
recomputeDimensions ( ) ;
}
2018-09-22 11:17:30 +02:00
public void removeBlockUnsafe ( final Block b ) {
2018-09-22 14:10:36 +02:00
b . setParent ( null ) ;
2018-03-11 21:49:41 +01:00
content . remove ( b ) ;
}
2018-09-22 11:17:30 +02:00
public void removeAt ( final int i ) {
2018-09-22 14:10:36 +02:00
content . remove ( i ) . setParent ( null ) ;
2017-03-03 23:06:43 +01:00
recomputeDimensions ( ) ;
}
2017-04-10 22:50:43 +02:00
2018-09-22 11:17:30 +02:00
public BlockReference < ? > getBlockAt ( final int i ) {
2018-05-12 21:18:29 +02:00
final Block b = content . get ( i ) ;
2018-03-11 21:49:41 +01:00
return new BlockReference < > ( b , i , this ) ;
}
public int getSize ( ) {
return content . size ( ) ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2017-03-03 23:06:43 +01:00
public void clear ( ) {
content . clear ( ) ;
recomputeDimensions ( ) ;
}
2017-04-10 22:50:43 +02:00
2017-03-03 23:06:43 +01:00
/ * *
2018-09-22 11:17:30 +02:00
*
2017-04-10 22:50:43 +02:00
* @param ge
* Graphic Engine class .
* @param r
* Graphic Renderer class of < b > ge < / b > .
* @param x
* Position relative to the window .
* @param y
* Position relative to the window .
* @param caret
* Position of the caret .
2017-03-03 23:06:43 +01:00
* /
2019-02-27 23:29:03 +01:00
public void draw ( final DisplayOutputDevice ge , final Renderer r , final int x , final int y , final Caret caret ) {
2017-03-26 22:44:09 +02:00
int paddingX = 1 ;
2017-03-03 23:06:43 +01:00
2018-09-28 11:39:28 +02:00
if ( caret . getRemaining ( ) = = 0 ) {
if ( content . size ( ) > 0 ) {
2017-04-11 22:04:44 +02:00
BlockContainer . drawCaret ( ge , r , caret , small , x , y + line - content . get ( 0 ) . line , content . get ( 0 ) . height ) ;
2018-09-28 11:39:28 +02:00
} else {
2017-04-11 22:04:44 +02:00
BlockContainer . drawCaret ( ge , r , caret , small , x , y , height ) ;
2018-09-28 11:39:28 +02:00
}
}
2017-04-10 22:50:43 +02:00
2017-03-26 22:44:09 +02:00
if ( withBorder & & content . size ( ) = = 0 ) {
2017-05-05 22:27:11 +02:00
r . glColor ( BlockContainer . getDefaultColor ( ) ) ;
2017-04-10 22:50:43 +02:00
r . glDrawLine ( x + paddingX , y , x + paddingX + width - 1 , y ) ;
r . glDrawLine ( x + paddingX , y , x + paddingX , y + height - 1 ) ;
r . glDrawLine ( x + paddingX + width - 1 , y , x + paddingX + width - 1 , y + height - 1 ) ;
r . glDrawLine ( x + paddingX , y + height - 1 , x + paddingX + width - 1 , y + height - 1 ) ;
2018-09-28 11:39:28 +02:00
} else {
2017-04-10 22:50:43 +02:00
for ( final Block b : content ) {
2017-03-26 22:44:09 +02:00
caret . skip ( 1 ) ;
2017-04-10 22:50:43 +02:00
b . draw ( ge , r , x + paddingX , y + line - b . line , caret ) ;
2017-03-26 22:44:09 +02:00
paddingX + = b . getWidth ( ) ;
2018-09-28 11:39:28 +02:00
if ( caret . getRemaining ( ) = = 0 ) {
2017-04-11 22:04:44 +02:00
BlockContainer . drawCaret ( ge , r , caret , small , x + paddingX , y + line - b . line , b . height ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-26 22:44:09 +02:00
paddingX + = 1 ;
}
2018-09-28 11:39:28 +02:00
}
2017-03-26 22:44:09 +02:00
caret . skip ( 1 ) ;
}
2018-09-22 11:17:30 +02:00
public boolean putBlock ( final Caret caret , final Block newBlock ) {
2017-03-26 22:44:09 +02:00
boolean added = false ;
if ( caret . getRemaining ( ) = = 0 ) {
2017-04-10 22:50:43 +02:00
addBlock ( 0 , newBlock ) ;
2017-03-26 22:44:09 +02:00
added = true ;
}
2017-04-10 22:50:43 +02:00
2017-03-26 22:44:09 +02:00
int pos = 0 ;
2017-04-10 22:50:43 +02:00
for ( final Block b : content ) {
2017-03-26 22:44:09 +02:00
caret . skip ( 1 ) ;
pos + + ;
2017-04-10 22:50:43 +02:00
added = added | b . putBlock ( caret , newBlock ) ;
2017-03-26 22:44:09 +02:00
if ( caret . getRemaining ( ) = = 0 ) {
2017-04-10 22:50:43 +02:00
addBlock ( pos , newBlock ) ;
2017-03-26 22:44:09 +02:00
added = true ;
}
}
caret . skip ( 1 ) ;
2018-09-28 11:39:28 +02:00
if ( added ) {
2017-03-26 22:44:09 +02:00
recomputeDimensions ( ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-26 22:44:09 +02:00
return added ;
}
2018-09-22 11:17:30 +02:00
public boolean delBlock ( final Caret caret ) {
2017-03-26 22:44:09 +02:00
boolean removed = false ;
2017-04-10 22:50:43 +02:00
2017-03-26 22:44:09 +02:00
int pos = 0 ;
2017-04-10 22:50:43 +02:00
for ( final Block b : content ) {
2017-03-03 23:06:43 +01:00
caret . skip ( 1 ) ;
2017-03-26 22:44:09 +02:00
pos + + ;
2017-04-10 22:50:43 +02:00
final int deltaCaret = caret . getRemaining ( ) ;
2018-10-05 22:09:54 +02:00
final int caretOldPos = caret . getPosition ( ) ;
2017-04-10 22:50:43 +02:00
removed = removed | b . delBlock ( caret ) ;
2018-09-22 11:17:30 +02:00
if ( caret . getRemaining ( ) = = 0 | | removed = = false & & deltaCaret > = 0 & & caret . getRemaining ( ) < 0 ) {
2018-10-04 09:52:14 +02:00
ObjectArrayList < Block > blocks = this . getBlockAt ( pos - 1 ) . get ( ) . getInnerBlocks ( ) ;
2018-10-05 22:09:54 +02:00
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 + + ;
}
2018-10-04 09:52:14 +02:00
}
2018-10-09 23:51:42 +02:00
// 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 + + ;
}
2018-10-04 08:49:11 +02:00
}
2018-10-09 23:51:42 +02:00
caret . setPosition ( caretOldPos - innerContainersBeforeCaret ) ;
removed = true ;
2018-10-04 08:49:11 +02:00
}
2017-03-26 22:44:09 +02:00
}
2017-03-03 23:06:43 +01:00
}
caret . skip ( 1 ) ;
2018-09-28 11:39:28 +02:00
if ( removed ) {
2017-03-26 22:44:09 +02:00
recomputeDimensions ( ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-26 22:44:09 +02:00
return removed ;
2017-03-03 23:06:43 +01:00
}
2018-09-22 11:17:30 +02:00
public BlockReference < ? > getBlock ( final Caret caret ) {
2018-03-11 21:49:41 +01:00
BlockReference < ? > block = null ;
2017-09-24 18:47:30 +02:00
2017-05-05 22:27:11 +02:00
int pos = 0 ;
for ( final Block b : content ) {
caret . skip ( 1 ) ;
pos + + ;
final int deltaCaret = caret . getRemaining ( ) ;
2017-09-24 18:47:30 +02:00
block = b . getBlock ( caret ) ;
2018-09-28 11:39:28 +02:00
if ( block ! = null ) {
2017-06-05 22:50:33 +02:00
return block ;
2018-09-28 11:39:28 +02:00
}
2018-09-22 11:17:30 +02:00
if ( caret . getRemaining ( ) = = 0 | | deltaCaret > = 0 & & caret . getRemaining ( ) < 0 ) {
2017-05-05 22:27:11 +02:00
block = getBlockAt ( pos - 1 ) ;
return block ;
}
}
caret . skip ( 1 ) ;
return block ;
}
2017-03-03 23:06:43 +01:00
@Override
public void recomputeDimensions ( ) {
int l = 0 ; //Line
int w = 0 ; //Width
int h2 = 0 ; //Height under the line. h = h2 + l
int h = 0 ; //Height
2017-04-10 22:50:43 +02:00
for ( final Block b : content ) {
2017-03-26 22:44:09 +02:00
w + = b . getWidth ( ) + 1 ;
2017-03-03 23:06:43 +01:00
final int bl = b . getLine ( ) ;
final int bh = b . getHeight ( ) ;
final int bh2 = bh - bl ;
2018-09-28 11:39:28 +02:00
if ( bl > l ) {
2017-03-03 23:06:43 +01:00
l = bl ;
2018-09-28 11:39:28 +02:00
}
if ( bh2 > h2 ) {
2017-03-03 23:06:43 +01:00
h2 = bh2 ;
2018-09-28 11:39:28 +02:00
}
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2018-09-28 11:39:28 +02:00
if ( content . size ( ) > 0 ) {
2017-03-26 22:44:09 +02:00
w - = 1 ;
2018-09-28 11:39:28 +02:00
}
2017-04-10 22:50:43 +02:00
2017-03-03 23:06:43 +01:00
h = h2 + l ;
line = l ;
2018-09-28 11:39:28 +02:00
if ( w > minWidth ) {
2017-03-03 23:06:43 +01:00
width = w ;
2018-09-28 11:39:28 +02:00
} else {
2017-03-03 23:06:43 +01:00
width = minWidth ;
2018-09-28 11:39:28 +02:00
}
if ( h > minHeight ) {
2017-03-03 23:06:43 +01:00
height = h ;
2018-09-28 11:39:28 +02:00
} else {
2017-03-03 23:06:43 +01:00
height = minHeight ;
2017-04-10 22:50:43 +02:00
line = height / 2 ;
2017-03-03 23:06:43 +01:00
}
}
@Override
public int getWidth ( ) {
return width ;
}
@Override
public int getHeight ( ) {
return height ;
}
@Override
public int getLine ( ) {
return line ;
}
private static final BinaryFont [ ] defFonts = new BinaryFont [ 2 ] ;
private static final int [ ] defFontSizes = new int [ 4 ] ;
private static final int defColor = 0xFF000000 ;
2017-04-10 22:50:43 +02:00
2018-09-22 11:17:30 +02:00
public static void initializeFonts ( final BinaryFont big , final BinaryFont small ) {
BlockContainer . defFonts [ 0 ] = big ;
BlockContainer . defFonts [ 1 ] = small ;
BlockContainer . defFontSizes [ 0 ] = big . getCharacterWidth ( ) ;
BlockContainer . defFontSizes [ 1 ] = big . getCharacterHeight ( ) ;
BlockContainer . defFontSizes [ 2 ] = small . getCharacterWidth ( ) ;
BlockContainer . defFontSizes [ 3 ] = small . getCharacterHeight ( ) ;
BlockContainer . initialized = true ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2019-11-02 23:13:19 +01:00
public static boolean isInitialized ( ) {
return BlockContainer . initialized ;
}
2018-09-22 11:17:30 +02:00
public static BinaryFont getDefaultFont ( final boolean small ) {
BlockContainer . checkInitialized ( ) ;
return BlockContainer . defFonts [ small ? 1 : 0 ] ;
2017-03-03 23:06:43 +01:00
}
public static int getDefaultColor ( ) {
2018-09-22 11:17:30 +02:00
return BlockContainer . defColor ;
2017-03-03 23:06:43 +01:00
}
2018-09-22 11:17:30 +02:00
public static int getDefaultCharWidth ( final boolean b ) {
BlockContainer . checkInitialized ( ) ;
return BlockContainer . defFontSizes [ b ? 2 : 0 ] ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2018-09-22 11:17:30 +02:00
public static int getDefaultCharHeight ( final boolean b ) {
BlockContainer . checkInitialized ( ) ;
return BlockContainer . defFontSizes [ b ? 3 : 1 ] ;
2017-03-03 23:06:43 +01:00
}
2017-04-10 22:50:43 +02:00
2019-02-27 23:29:03 +01:00
public static void drawCaret ( final DisplayOutputDevice ge , final Renderer r , final Caret caret , final boolean small ,
2018-09-22 11:17:30 +02:00
final int x , final int y , final int height ) {
2017-03-26 22:44:09 +02:00
if ( caret . getState ( ) = = CaretState . VISIBLE_ON ) {
2018-09-22 11:17:30 +02:00
r . glColor ( BlockContainer . getDefaultColor ( ) ) ;
2017-09-24 18:47:30 +02:00
r . glFillColor ( x , y , small ? 2 : 3 , height ) ;
2017-05-05 22:27:11 +02:00
caret . setLastLocation ( x , y ) ;
2017-09-24 18:47:30 +02:00
caret . setLastSize ( small ? 2 : 3 , height ) ;
2017-03-26 22:44:09 +02:00
}
2017-03-03 23:06:43 +01:00
}
2018-09-22 11:17:30 +02:00
public void setSmall ( final boolean small ) {
2017-03-03 23:06:43 +01:00
this . small = small ;
2018-05-12 21:18:29 +02:00
if ( autoMinimums ) {
minWidth = BlockContainer . getDefaultCharWidth ( small ) ;
minHeight = BlockContainer . getDefaultCharHeight ( small ) ;
2017-04-11 22:04:44 +02:00
}
2018-09-28 11:39:28 +02:00
for ( final Block b : content ) {
2017-04-11 22:04:44 +02:00
b . setSmall ( small ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-03 23:06:43 +01:00
recomputeDimensions ( ) ;
}
public ObjectArrayList < Block > getContent ( ) {
return content . clone ( ) ;
}
2017-04-10 22:50:43 +02:00
2017-03-26 22:44:09 +02:00
private static void checkInitialized ( ) {
2018-09-28 11:39:28 +02:00
if ( ! BlockContainer . initialized ) {
2019-02-27 23:29:03 +01:00
WarpPI . getPlatform ( ) . throwNewExceptionInInitializerError ( " Please initialize BlockContainer by running the method BlockContainer.initialize(...) first! " ) ;
2018-09-28 11:39:28 +02:00
}
2017-03-26 22:44:09 +02:00
}
2017-04-09 22:01:03 +02:00
public int computeCaretMaxBound ( ) {
int maxpos = 0 ;
2018-09-28 11:39:28 +02:00
for ( final Block b : content ) {
2017-04-10 22:50:43 +02:00
maxpos + = 1 + b . computeCaretMaxBound ( ) ;
2018-09-28 11:39:28 +02:00
}
2017-04-10 22:50:43 +02:00
return maxpos + 1 ;
2017-04-09 22:01:03 +02:00
}
2017-04-10 22:50:43 +02:00
2018-09-22 11:17:30 +02:00
public Function toFunction ( final MathContext context ) throws Error {
2018-05-12 21:18:29 +02:00
final ObjectArrayList < Block > blocks = getContent ( ) ;
2017-05-26 22:37:18 +02:00
final ObjectArrayList < Feature > blockFeatures = new ObjectArrayList < > ( ) ;
for ( final Block block : blocks ) {
final Feature blockFeature = block . toFeature ( context ) ;
2018-09-28 11:39:28 +02:00
if ( blockFeature = = null ) {
2017-09-24 18:47:30 +02:00
throw new Error ( Errors . NOT_IMPLEMENTED , " The block " + block . getClass ( ) . getSimpleName ( ) + " isn't a known Block " ) ;
2018-09-28 11:39:28 +02:00
}
2017-05-26 22:37:18 +02:00
blockFeatures . add ( blockFeature ) ;
}
final Function result = MathParser . joinFeatures ( context , blockFeatures ) ;
return result ;
}
2017-09-24 18:47:30 +02:00
2017-03-03 23:06:43 +01:00
}