package bluej.stride.framedjava.frames;
import bluej.Config;
import bluej.debugger.gentype.Reflective;
import bluej.parser.AssistContent.CompletionKind;
import bluej.parser.AssistContent.ParamInfo;
import bluej.stride.framedjava.ast.ASTUtility;
import bluej.stride.framedjava.ast.AccessPermission;
import bluej.stride.framedjava.ast.AccessPermissionFragment;
import bluej.stride.framedjava.ast.JavaFragment.PosInSourceDoc;
import bluej.stride.framedjava.ast.JavadocUnit;
import bluej.stride.framedjava.ast.NameDefSlotFragment;
import bluej.stride.framedjava.ast.ParamFragment;
import bluej.stride.framedjava.elements.ClassElement;
import bluej.stride.framedjava.elements.CodeElement;
import bluej.stride.framedjava.elements.ConstructorElement;
import bluej.stride.framedjava.elements.MethodProtoElement;
import bluej.stride.framedjava.elements.NormalMethodElement;
import bluej.stride.framedjava.slots.ExpressionCompletionCalculator;
import bluej.stride.framedjava.slots.TypeSlot;
import bluej.stride.generic.AssistContentThreadSafe;
import bluej.stride.generic.ExtensionDescription;
import bluej.stride.generic.ExtensionDescription.ExtensionSource;
import bluej.stride.generic.Frame;
import bluej.stride.generic.FrameCanvas;
import bluej.stride.generic.FrameContentRow;
import bluej.stride.generic.FrameCursor;
import bluej.stride.generic.FrameFactory;
import bluej.stride.generic.InteractionManager;
import bluej.stride.operations.CustomFrameOperation;
import bluej.stride.operations.FrameOperation;
import bluej.stride.operations.ToggleBooleanProperty;
import bluej.stride.slots.*;
import bluej.stride.slots.EditableSlot.MenuItemOrder;
import bluej.stride.slots.SuggestionList.SuggestionDetailsWithHTMLDoc;
import bluej.stride.slots.SuggestionList.SuggestionListListener;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformConsumer;
import bluej.utility.javafx.HangingFlowPane;
import bluej.utility.javafx.JavaFXUtil;
import bluej.utility.javafx.SharedTransition;
import javafx.beans.binding.StringExpression;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TextField;
import threadchecker.OnThread;
import threadchecker.Tag;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class NormalMethodFrame extends MethodFrameWithBody<NormalMethodElement>
public static final String STATIC_NAME = "static";
public static final String TOGGLE_STATIC_METHOD = "toggleStaticMethod";
public static final String FINAL_NAME = "final";
public static final String TOGGLE_FINAL_METHOD = "toggleFinalMethod";
private final SlotLabel staticLabel;
private BooleanProperty staticModifier = new SimpleBooleanProperty(false);
private final SlotLabel finalLabel;
private BooleanProperty finalModifier = new SimpleBooleanProperty(false);
private final WrappableSlotLabel overrideLabel = new WrappableSlotLabel("") {
@Override
public void setView(View oldView, View newView, SharedTransition animate)
{
if (oldView == View.NORMAL && newView == View.JAVA_PREVIEW)
{
fadeOut(animate, true);
}
else
{
fadeIn(animate);
}
}
};
@OnThread(Tag.FXPlatform)
private String curOverrideSource = null;
private final TypeSlot returnType;
private final TextSlot<NameDefSlotFragment> methodName;
private NormalMethodElement element;
private NormalMethodFrame(InteractionManager editor)
{
super(editor);
setDocumentationPromptText(Config.getString("frame.class.method.doc.prompt"));
methodName = new MethodNameDefTextSlot(editor, this, getHeaderRow(), new MethodOverrideCompletionCalculator(), "method-name-");
methodName.addValueListener(new SlotTraversalChars(
() -> getHeaderRow().focusRight(methodName),
SlotTraversalChars.METHOD_NAME.getChars()) {
@Override
public void deletePressedAtEnd(HeaderItem slot)
{
paramsPane.deleteFirstParam();
}
});
returnType = new TypeSlot(editor, this, this, getHeaderRow(), TypeSlot.Role.RETURN, "method-return-type-");
returnType.addClosingChar(' ');
returnType.markReturnType();
paramsPane = new FormalParameters(editor, this, this, getHeaderRow(), "method-param-");
returnType.setSimplePromptText("type");
methodName.setPromptText("name");
staticLabel = new SlotLabel("static ");
finalLabel = new SlotLabel("final ");
modifiers.put(STATIC_NAME, staticModifier);
modifiers.put(FINAL_NAME, finalModifier);
overrideLabel.addStyleClass("method-override-label");
overrideLabel.setAlignment(HangingFlowPane.FlowAlignment.RIGHT);
getHeaderRow().bindContentsConcat(FXCollections.<ObservableList<? extends HeaderItem>>observableArrayList(
FXCollections.observableArrayList(access),
JavaFXUtil.listBool(staticModifier, staticLabel),
JavaFXUtil.listBool(finalModifier, finalLabel),
FXCollections.observableArrayList(returnType),
FXCollections.observableArrayList(methodName),
paramsPane.getSlots(),
throwsPane.getHeaderItems(),
FXCollections.observableArrayList(overrideLabel)
));
JavaFXUtil.addChangeListener(staticModifier, b -> editor.modifiedFrame(this, false));
JavaFXUtil.addChangeListener(finalModifier, b -> editor.modifiedFrame(this, false));
}
public NormalMethodFrame(InteractionManager editor, AccessPermissionFragment access, boolean staticModifier,
boolean finalModifier, String returnType, String name, String documentation, boolean enabled)
{
this(editor);
this.access.setValue(access.getValue());
access.registerSlot(this.access);
this.staticModifier.set(staticModifier);
this.finalModifier.set(finalModifier);
setDocumentation(documentation);
this.returnType.setText(returnType);
methodName.setText(name);
frameEnabledProperty.set(enabled);
}
@Override
public boolean focusWhenJustAdded()
{
returnType.requestFocus();
return true;
}
public static FrameFactory getFactory()
{
return new FrameFactory<NormalMethodFrame>() {
@Override
public NormalMethodFrame createBlock(InteractionManager editor)
{
return new NormalMethodFrame(editor);
}
@Override
public Class getBlockClass()
{
return NormalMethodFrame.class;
}
};
}
@Override
public void regenerateCode()
{
List<ParamFragment> params = generateParams();
element = new NormalMethodElement(this, new AccessPermissionFragment(this, access), staticModifier.get(),
finalModifier.get(), returnType.getSlotElement(), methodName.getSlotElement(),
params, throwsPane.getTypes(), getContents(), new JavadocUnit(getDocumentation()), frameEnabledProperty.get());
}
@Override
public NormalMethodElement getCode()
{
return element;
}
public String getName()
{
return methodName.getText();
}
private class MethodOverrideCompletionCalculator
implements CompletionCalculator
{
private List<AssistContentThreadSafe> inheritedMethods;
private SuggestionList suggestionDisplay;
@Override
@OnThread(Tag.FXPlatform)
public void withCalculatedSuggestionList(PosInSourceDoc pos, CodeElement codeEl,
SuggestionListListener listener, FXPlatformConsumer<SuggestionList> handler) {
ClassFrame classFrame = (ClassFrame)ASTUtility.getTopLevelElement(codeEl).getFrame();
classFrame.withInheritedItems(Collections.singleton(CompletionKind.METHOD), inheritedMethodsByDeclarer ->
{
inheritedMethods = inheritedMethodsByDeclarer.values().stream().flatMap(List::stream).collect(Collectors.toList());
suggestionDisplay = new SuggestionList(getEditor(),
Utility.mapList(inheritedMethods, ac -> new SuggestionDetailsWithHTMLDoc(
ac.getName(),
ExpressionCompletionCalculator.getParamsCompletionDisplay(ac),
ac.getType(),
SuggestionList.SuggestionShown.COMMON,
ac.getDocHTML())),
null, SuggestionList.SuggestionShown.RARE, null, listener);
handler.accept(suggestionDisplay);
});
}
@Override
public boolean execute(TextField field, int selected, int startOfCurWord)
{
if (selected == -1) {
return false;
}
AssistContentThreadSafe a = inheritedMethods.get(selected);
methodName.setText(a.getName());
returnType.setText(a.getType());
access.setValue(AccessPermission.fromAccess(a.getAccessPermission()));
paramsPane.setParams(a.getParams(), ParamInfo::getUnqualifiedType, ParamInfo::getFormalName);
return true;
}
}
@Override
@OnThread(Tag.FXPlatform)
public List getContextOperations()
{
List<FrameOperation> operations = new ArrayList<>(super.getContextOperations());
InteractionManager editor = getEditor();
operations.add(new CustomFrameOperation(editor, "method->constructor",
Arrays.asList(Config.getString("frame.operation.change"), Config.getString("frame.operation.change.to.constructor")),
MenuItemOrder.TRANSFORM, this,
() -> {
Frame parent = getParentCanvas().getParent().getFrame();
if (parent instanceof ClassFrame) {
FrameCanvas p = ((ClassFrame)parent).getConstructorsCanvas();
FrameCursor c = p.getLastCursor();
ConstructorElement el = new ConstructorElement(null, new AccessPermissionFragment(this, access), generateParams(),
throwsPane.getTypes(), null, null, getContents(), new JavadocUnit(getDocumentation()), frameEnabledProperty.get());
c.insertBlockAfter(el.createFrame(getEditor()));
getParentCanvas().removeBlock(this);
}
}
));
operations.add(new CustomFrameOperation(editor, "concrete->abstract",
Arrays.asList(Config.getString("frame.operation.change"), Config.getString("frame.operation.change.to.abstract")),
MenuItemOrder.TRANSFORM, this,
() -> {
FrameCursor c = getCursorBefore();
MethodProtoElement el = new MethodProtoElement(null, returnType.getSlotElement(), methodName.getSlotElement(),
generateParams(), throwsPane.getTypes(), new JavadocUnit(getDocumentation()), frameEnabledProperty.get());
c.insertBlockAfter(el.createFrame(getEditor()));
c.getParentCanvas().removeBlock(this);
}
));
operations.addAll(getStaticFinalOperations());
return operations;
}
@Override
public List getAvailableExtensions(FrameCanvas innerCanvas, FrameCursor cursorInCanvas)
{
final List<ExtensionDescription> extensions = new ArrayList<>(super.getAvailableExtensions(innerCanvas, cursorInCanvas));
getStaticFinalOperations().stream().forEach(op -> extensions.add(new ExtensionDescription(op, this, true,
ExtensionSource.BEFORE, ExtensionSource.AFTER, ExtensionSource.MODIFIER, ExtensionSource.SELECTION)));
return extensions;
}
private List getStaticFinalOperations()
{
List<ToggleBooleanProperty> operations = new ArrayList<>();
operations.add(new ToggleBooleanProperty(getEditor(), TOGGLE_FINAL_METHOD, FINAL_NAME, 'n'));
operations.add(new ToggleBooleanProperty(getEditor(), TOGGLE_STATIC_METHOD, STATIC_NAME, 's'));
return operations;
}
public StringExpression returnTypeProperty()
{
return returnType.javaProperty();
}
@OnThread(Tag.FXPlatform)
public void updateOverrideDisplay(ClassElement topLevel)
{
if (element == null)
return;
final NormalMethodElement cachedElement = element;
List<String> qualParamTypes = cachedElement.getQualifiedParamTypes(topLevel);
Reflective overriddenFrom = topLevel.findSuperMethod(cachedElement.getName(), qualParamTypes);
if (overriddenFrom != null)
{
String name = overriddenFrom.getSimpleName();
if (name.indexOf('.') != -1)
name = name.substring(name.lastIndexOf('.') + 1);
final String nameFinal = name;
if (curOverrideSource == null || !curOverrideSource.equals(nameFinal))
{
curOverrideSource = nameFinal;
overrideLabel.setText(Config.getString("frame.class.overrides.from").replace("$", nameFinal));
}
}
else
{
if (curOverrideSource != null)
{
curOverrideSource = null;
overrideLabel.setText("");
}
}
}
@Override
public EditableSlot getErrorShowRedirect()
{
return methodName;
}
@Override
public void focusName()
{
methodName.requestFocus(Focus.LEFT);
}
@Override
protected FrameContentRow makeHeader(String stylePrefix)
{
return new MethodHeaderRow(this, stylePrefix)
{
@Override
protected EditableSlot getSlotAfterParams()
{
return throwsPane.getTypeSlots().findFirst().orElse(null);
}
@Override
protected EditableSlot getSlotBeforeParams()
{
return methodName;
}
};
}
@Override
public boolean tryRestoreTo(CodeElement codeElement)
{
if (codeElement instanceof NormalMethodElement)
{
NormalMethodElement nme = (NormalMethodElement)codeElement;
staticModifier.set(nme.isStatic());
finalModifier.set(nme.isFinal());
returnType.setText(nme.getType());
methodName.setText(nme.getName());
restoreDetails(nme);
return true;
}
return false;
}
}
. setView
. NormalMethodFrame
. deletePressedAtEnd
. HeaderItem>>observableArrayList
. NormalMethodFrame
. focusWhenJustAdded
. getFactory
. createBlock
. getBlockClass
. regenerateCode
. getCode
. getName
top,
use,
map,
class MethodOverrideCompletionCalculator
. withCalculatedSuggestionList
. execute
. getContextOperations
. getAvailableExtensions
. getStaticFinalOperations
. returnTypeProperty
. updateOverrideDisplay
. getErrorShowRedirect
. focusName
. makeHeader
. getSlotAfterParams
. getSlotBeforeParams
. tryRestoreTo
495 neLoCode
+ 0 LoComm