package bluej.stride.framedjava.frames;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import bluej.stride.framedjava.elements.BreakElement;
import bluej.stride.generic.DefaultFrameFactory;
import bluej.stride.generic.FrameCanvas;
import bluej.stride.generic.FrameFactory;
import bluej.stride.generic.InteractionManager;
import bluej.stride.generic.SingleLineFrame;
import bluej.utility.javafx.JavaFXUtil;
import bluej.utility.javafx.SharedTransition;
import threadchecker.OnThread;
import threadchecker.Tag;
| A break statement (no parameters). Further, the break statement takes on the colour of whatever it is breaking from, to indicate that it has some scope-level significance.
| @author Fraser McKay
|
public class BreakFrame extends SingleLineFrame
implements CodeFrame<BreakElement>, DebuggableFrame{
private SimpleDoubleProperty xOffset;
private SimpleDoubleProperty yOffset;
public static enum BreakEncloser
{
WHILE, FOREACH, SWITCH;
public String getPseudoClass()
{
switch (this)
{
case WHILE: return "bj-break-while";
case FOREACH: return "bj-break-foreach";
case SWITCH: return "bj-break-switch";
}
return null;
}
}
private BreakElement element;
private Rectangle rectangle;
private FrameCanvas outer;
private VBox overlay;
private boolean normalView = true;
| Default constructor.
|
private BreakFrame(InteractionManager editor)
{
super(editor, "break", "break-");
setHeaderRow(previewSemi);
}
public BreakFrame(InteractionManager editor, boolean enabled)
{
this(editor);
frameEnabledProperty.set(enabled);
}
@Override
public void updateAppearance(FrameCanvas c)
{
super.updateAppearance(c);
if (!normalView || !isFrameEnabled())
{
JavaFXUtil.runNowOrLater(() -> setOverlay(false, null, null));
return;
}
for (BreakEncloser e : BreakEncloser.values())
JavaFXUtil.setPseudoclass(e.getPseudoClass(), false, getNode());
while (c != null && c.getParent() != null && c.getParent().getFrame() != null && c.getParent().getFrame() instanceof CodeFrame<?>)
{
CodeFrame<?> cf = (CodeFrame<?>)c.getParent().getFrame();
if (cf.asBreakEncloser() != null)
{
JavaFXUtil.setPseudoclass(cf.asBreakEncloser().getPseudoClass(), true, getNode());
final FrameCanvas cFinal = c;
JavaFXUtil.runNowOrLater(() -> setOverlay(true, cFinal, cf.asBreakEncloser().getPseudoClass()));
return;
}
c = c.getParent().getFrame().getParentCanvas();
}
JavaFXUtil.runNowOrLater(() -> setOverlay(false, null, null));
}
public static FrameFactory getFactory()
{
return new DefaultFrameFactory<>(BreakFrame.class, BreakFrame::new);
}
@Override
public BreakElement getCode()
{
return element;
}
@Override
public void regenerateCode()
{
element = new BreakElement(this, frameEnabledProperty.get());
}
private void adjustOverlayBounds()
{
if (outer == null || rectangle == null || overlay == null)
return;
final double ourX = getNode().localToScene(0, 0).getX();
final double theirX = outer.getContentSceneBounds().getMinX();
double width = ourX - theirX;
rectangle.setWidth(width + 1.0);
rectangle.setHeight(Math.ceil(getRegion().getHeight() / 4.0));
xOffset.set(-width);
yOffset.set(getRegion().getHeight() * 3.0 / 8.0);
}
@OnThread(Tag.FXPlatform)
private void setOverlay(boolean on, FrameCanvas outer, String pseudo)
{
if (on && overlay == null)
{
this.outer = outer;
rectangle = new Rectangle();
overlay = new VBox(rectangle);
JavaFXUtil.addStyleClass(overlay, "break-frame-overlay");
JavaFXUtil.addStyleClass(rectangle, "break-frame-overlay-rect");
JavaFXUtil.setPseudoclass(pseudo, true, overlay, rectangle);
xOffset = new SimpleDoubleProperty(0.0);
yOffset = new SimpleDoubleProperty(0.0);
JavaFXUtil.onceInScene(overlay, this::adjustOverlayBounds);
getEditor().getCodeOverlayPane().addOverlay(overlay, getNode(), xOffset, yOffset);
JavaFXUtil.addChangeListener(getNode().localToSceneTransformProperty(), t -> adjustOverlayBounds());
JavaFXUtil.addChangeListener(getNode().boundsInLocalProperty(), b -> adjustOverlayBounds());
}
else if (!on && overlay != null)
{
getEditor().getCodeOverlayPane().removeOverlay(overlay);
overlay = null;
rectangle = null;
this.outer = null;
}
}
@Override
@OnThread(Tag.FXPlatform)
public void setView(View oldView, View newView, SharedTransition animation)
{
super.setView(oldView, newView, animation);
normalView = newView == View.NORMAL;
updateAppearance(getParentCanvas());
}
@Override
protected void saveAsRecent()
{
}
@Override
protected void cleanupFrame()
{
JavaFXUtil.runNowOrLater(() -> setOverlay(false, null, null));
}
}
. getPseudoClass
. BreakFrame
. BreakFrame
. updateAppearance
. getFactory
. getCode
. regenerateCode
. adjustOverlayBounds
. setOverlay
. setView
. saveAsRecent
. cleanupFrame
218 neLoCode
+ 3 LoComm