package bluej.stride.framedjava.frames;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import bluej.stride.framedjava.ast.links.PossibleLink;
import bluej.stride.framedjava.ast.links.PossibleKnownMethodLink;
import bluej.stride.framedjava.slots.UnderlineContainer;
import bluej.stride.slots.EditableSlot.MenuItemOrder;
import bluej.stride.slots.EditableSlot.SortedMenuItem;
import bluej.stride.slots.HeaderItem;
import bluej.stride.slots.WrappableSlotLabel;
import bluej.utility.javafx.ErrorUnderlineCanvas;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Label;
import bluej.parser.AssistContent.ParamInfo;
import bluej.stride.framedjava.ast.AccessPermission;
import bluej.stride.framedjava.ast.AccessPermissionFragment;
import bluej.stride.framedjava.ast.NameDefSlotFragment;
import bluej.stride.framedjava.ast.TypeSlotFragment;
import bluej.stride.framedjava.slots.TextOverlayPosition;
import bluej.stride.generic.Frame;
import bluej.stride.generic.InteractionManager;
import bluej.stride.generic.SingleLineFrame;
import bluej.stride.operations.AbstractOperation.Combine;
import bluej.stride.operations.CustomFrameOperation;
import bluej.stride.operations.FrameOperation;
import bluej.stride.slots.EditableSlot;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformRunnable;
import bluej.utility.javafx.FXRunnable;
import bluej.utility.javafx.HangingFlowPane;
import bluej.utility.javafx.JavaFXUtil;
import bluej.utility.javafx.SharedTransition;
import threadchecker.OnThread;
import threadchecker.Tag;


| A frame to show the details of an inherited method in the inherited canvas | public class InheritedMethodFrame extends SingleLineFrame{ private final InteractionManager editor; private final ClassFrame container; private final String originatingClass; private final AccessPermission access; private final String returnType; private final String methodName; private final List<ParamInfo> params; private final InheritedMethodSlot slot; private final WrappableSlotLabel overrideLabel = new WrappableSlotLabel(""); private NormalMethodFrame override; public InheritedMethodFrame(InteractionManager editor, ClassFrame container, String originatingClass, AccessPermission access, String returnType, String methodName, List<ParamInfo> params) { super(editor, "", "inherited-method-"); String preName = access + " \t" + returnType + " "; String postName = "(" + params.stream().map(p -> p.getUnqualifiedType() + (p.getFormalName() == null ? "" : " " + p.getFormalName())). collect(Collectors.joining(", ")) + ")"; this.editor = editor; this.container = container; this.originatingClass = originatingClass; this.access = access; this.returnType = returnType; this.methodName = methodName; this.params = params; slot = new InheritedMethodSlot(preName, methodName, postName); overrideLabel.addStyleClass("inherited-method-override-label"); overrideLabel.setAlignment(HangingFlowPane.FlowAlignment.RIGHT); checkForOverride(); setHeaderRow(slot, overrideLabel); } private void checkForOverride() { container.findMethod(methodName, params, override -> { this.override = override; if (override != null) { overrideLabel.setText("overridden in this class"); } }); } @Override public boolean canDrag() { return false; } @Override @OnThread(Tag.FXPlatform) public List getContextOperations() { List<FrameOperation> operations = new ArrayList<>(); operations.add(new FrameOperation(getEditor(), "GO TO " + originatingClass + "." + methodName, Combine.ONE) { private StringProperty text = new SimpleStringProperty("Scanning... "); @Override public List getLabels() { return Collections.singletonList(new ItemLabel(text, MenuItemOrder.GOTO_DEFINITION)); } @Override protected void execute(List<Frame> frames) { } public SortedMenuItem getMenuItem(boolean contextMenu) { CustomMenuItem item = initializeCustomItem(); item.setDisable(true); return MenuItemOrder.GOTO_DEFINITION.item(item); } @Override @OnThread(Tag.FXPlatform) public void onMenuShowing(CustomMenuItem item) { InheritedMethodFrame.this.editor.searchLink(new PossibleKnownMethodLink(originatingClass, methodName, Utility.mapList(params, pi -> pi.getQualifiedType()), 0, 1, slot), optLink -> { if (optLink.isPresent()) { text.set("Show original"); item.setDisable(false); item.onActionProperty().set(e -> optLink.get().getOnClick().run()); } }); } @Override public void onMenuHidden(CustomMenuItem item) { item.setDisable(true); text.set("Scanning..."); } @Override public boolean onlyOnContextMenu() { return true; } }); if (override == null) { operations.add(new CustomFrameOperation(editor, "OVERRIDE", Arrays.asList("Override"), MenuItemOrder.OVERRIDE, this, () -> { NormalMethodFrame methodFrame = new NormalMethodFrame(editor, new AccessPermissionFragment(access), false, false, returnType, methodName, "", true); params.forEach(p -> methodFrame.paramsPane.addFormal(new TypeSlotFragment(p.getUnqualifiedType(), p.getUnqualifiedType()), new NameDefSlotFragment((p.getFormalName() == null ? "" : p.getFormalName())))); container.getLastInternalCursor().insertBlockAfter(methodFrame); methodFrame.getFirstInternalCursor().requestFocus(); methodFrame.markFresh(); })); } else { operations.add(new CustomFrameOperation(editor, "GO TO " + methodName, Arrays.asList("Show override"), MenuItemOrder.GOTO_OVERRIDE, this, () -> { override.focusName(); })); } return operations; } private class InheritedMethodSlot implements HeaderItem, ErrorUnderlineCanvas.UnderlineInfo, UnderlineContainer { private final ObservableList<Label> labels = FXCollections.observableArrayList(); private final int methodNameIndex; public InheritedMethodSlot(String preName, String methodName, String postName) { Arrays.stream(preName.split("\\s+")).forEach(s -> labels.add(new Label(s + " "))); methodNameIndex = labels.size(); final Label methodNameLabel = new Label(methodName); JavaFXUtil.addStyleClass(methodNameLabel, "inherited-method-name"); labels.add(methodNameLabel); Arrays.stream(postName.split("\\s+")).forEach(s -> labels.add(new Label(s + " "))); for (Label label : labels) { JavaFXUtil.addStyleClass(label, "inherited-method-slot"); label.setOnMouseMoved(e -> { JavaFXUtil.setPseudoclass("bj-hyperlink", getHeaderRow().getOverlay().linkFromX(e.getSceneX()) != null, label); }); label.setOnMouseClicked(e -> { Utility.ifNotNull(getHeaderRow().getOverlay().linkFromX(e.getSceneX()), FXPlatformRunnable::run); }); } } @Override public TextOverlayPosition getOverlayLocation(int caretPos, boolean javaPos) { Label label = labels.get(methodNameIndex); return TextOverlayPosition.nodeToOverlay(label, JavaFXUtil.measureString(label, label.getText().substring(0, caretPos)), 0, label.getBaselineOffset(), label.getHeight()); } @Override public ObservableList getComponents() { return labels; } @Override @OnThread(Tag.FXPlatform) public void addUnderline(EditableSlot.Underline u) { getHeaderRow().getOverlay().addUnderline(this, 0, labels.get(methodNameIndex).getText().length(), u.getOnClick()); } @Override @OnThread(Tag.FXPlatform) public void removeAllUnderlines() { getHeaderRow().getOverlay().clearUnderlines(); } @Override public List findLinks() { return Collections.singletonList(new PossibleKnownMethodLink(originatingClass, methodName, Utility.mapList(params, ParamInfo::getQualifiedType), 0, 1, this)); } @Override public EditableSlot asEditable() { return null; } @Override public void setView(Frame.View oldView, Frame.View newView, SharedTransition animate) { } } @Override @OnThread(Tag.FXPlatform) public void compiled() { super.compiled(); checkForOverride(); } }
top, use, map, class InheritedMethodFrame

.   InheritedMethodFrame
.   checkForOverride
.   canDrag
.   getContextOperations
.   getLabels
.   execute
.   getMenuItem
.   onMenuShowing
.   onMenuHidden
.   onlyOnContextMenu

top, use, map, class InheritedMethodSlot

.   InheritedMethodSlot
.   getOverlayLocation
.   getComponents
.   addUnderline
.   removeAllUnderlines
.   findLinks
.   asEditable
.   setView
.   compiled




332 neLoCode + 1 LoComm