package bluej.editor.stride;
import bluej.BlueJTheme;
import bluej.Config;
import bluej.Main;
import bluej.collect.DataCollector;
import bluej.editor.stride.FrameCatalogue.Hint;
import bluej.pkgmgr.Project;
import bluej.prefmgr.PrefMgr;
import bluej.stride.generic.ExtensionDescription;
import bluej.stride.generic.Frame;
import bluej.stride.generic.FrameCursor;
import bluej.stride.generic.InteractionManager;
import bluej.utility.Debug;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformConsumer;
import bluej.utility.javafx.FXPlatformRunnable;
import bluej.utility.javafx.FXSupplier;
import bluej.utility.javafx.JavaFXUtil;
import bluej.utility.javafx.UnfocusableScrollPane;
import bluej.utility.javafx.UntitledCollapsiblePane;
import bluej.utility.javafx.UntitledCollapsiblePane.ArrowLocation;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringExpression;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.MenuBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.Duration;
import threadchecker.OnThread;
import threadchecker.Tag;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
| FXTabbedEditor is the editor window that contains all the editors in JavaFX tabs (currently,
| this is the Stride editors only).
|
| Because you can drag between tabs, it is responsible for handling dragging, rather than the individual editor tabs doing it.
|
| It is also responsible for changing the menus on the window when the tab changes.
|
public @OnThread(Tag.FX) class FXTabbedEditor
{
| Are we currently showing the frame catalogue/cheat sheet?
|
private final SimpleBooleanProperty showingCatalogue = new SimpleBooleanProperty(true);
| The associated project (one window always maps to single project
|
private final Project project;
| The frames which are currently being dragged, if any
|
private final ArrayList<Frame> dragSourceFrames = new ArrayList<Frame>();
| Relative to window overlay, not to scene
|
private final SimpleDoubleProperty mouseDragXProperty = new SimpleDoubleProperty();
private final SimpleDoubleProperty mouseDragYProperty = new SimpleDoubleProperty();
| The starting size of the window. May be null. Updated on window close.
|
private Rectangle startSize;
| The actual window
|
private Stage stage;
| The scene within the stage
|
private Scene scene;
| The tabs container
|
private TabPane tabPane;
| The Pane used for frames being dragged
|
private Pane dragPane;
| The Pane in front of dragPane used for showing cursor drop destinations
| (so they appear in front of the dragged frames):
|
private Pane dragCursorPane;
| The window overlay pane, covers whole window
|
private WindowOverlayPane overlayPane;
| The right-hand side FrameCatalogue
|
private FrameCatalogue cataloguePane;
| The menu bar at the top of the window (or system menu bar on Mac)
|
private MenuBar menuBar;
| The tab that is being hovered over to switch tabs (while dragging frames):
|
private Tab hoverTab;
| The cancellation action for the scheduled task to switch to another tab after enough time has passed while hovering
|
private FXPlatformRunnable hoverTabTask;
| The picture being shown of the currently dragged frames
|
private ImageView dragIcon = null;
| Cached so it can be read from any thread. Written to once on Swing thread in initialise,
| then effectively final thereafter
|
@OnThread(Tag.Any) private String projectTitle;
private StringProperty titleStatus = new SimpleStringProperty("");
private UntitledCollapsiblePane collapsibleCatalogueScrollPane;
private FrameShelf shelf;
private boolean dragFromShelf;
@OnThread(Tag.Any)
public FXTabbedEditor(Project project, Rectangle startSize)
{
this.project = project;
this.startSize = startSize;
}
p.public static boolean isUselessDrag(FrameCursor dragTarget, List<Frame> dragging, boolean copying)
{
return !copying && (dragging.contains(dragTarget.getFrameAfter()) || dragging.contains(dragTarget.getFrameBefore()));
}
| Initialises the FXTabbedEditor.
|
@OnThread(Tag.FXPlatform)
public void initialise()
{
projectTitle = project.getProjectName();
stage = new Stage();
BlueJTheme.setWindowIconFX(stage);
initialiseFX();
}
| The actual initialisation, on the FX thread
|
@OnThread(Tag.FXPlatform)
private void initialiseFX()
{
if (Thread.currentThread().getContextClassLoader() == null)
{
Thread.currentThread().setContextClassLoader(Main.getStoredContextClassLoader());
}
Config.loadFXFonts();
tabPane = new TabPane();
tabPane.setTabClosingPolicy(TabClosingPolicy.ALL_TABS);
menuBar = new MenuBar();
JavaFXUtil.addStyleClass(menuBar, "editor-menubar");
menuBar.setUseSystemMenuBar(true);
dragPane = new Pane();
dragPane.setMouseTransparent(true);
dragCursorPane = new Pane();
dragCursorPane.setMouseTransparent(true);
cataloguePane = new FrameCatalogue();
BorderPane menuAndTabPane = new BorderPane();
menuAndTabPane.setTop(menuBar);
overlayPane = new WindowOverlayPane();
menuAndTabPane.setCenter(new StackPane(tabPane));
shelf = new FrameShelf(this, project.getShelfStorage());
ScrollPane catalogueScrollPane = new UnfocusableScrollPane(cataloguePane);
catalogueScrollPane.setMaxWidth(FrameCatalogue.CATALOGUE_FRAME_WIDTH);
catalogueScrollPane.setMinWidth(0.0);
catalogueScrollPane.setFitToWidth(true);
catalogueScrollPane.setFocusTraversable(false);
catalogueScrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
catalogueScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
JavaFXUtil.addStyleClass(catalogueScrollPane, "catalogue-scroll");
BorderPane catalogueBackground = new BorderPane();
JavaFXUtil.addStyleClass(catalogueBackground, "catalogue-background");
Label title = new Label(Config.getString("frame.catalogue.title"));
BorderPane.setAlignment(title, Pos.BOTTOM_RIGHT);
catalogueBackground.setBottom(title);
StackPane catalogueScrollPaneStacked = new StackPane(catalogueBackground, catalogueScrollPane);
catalogueScrollPaneStacked.setMinWidth(0.0);
FXPlatformConsumer<? super Boolean> frameCatalogueShownListener =
show -> recordShowHideFrameCatalogue(show, FrameCatalogue.ShowReason.ARROW);
collapsibleCatalogueScrollPane = new UntitledCollapsiblePane(catalogueScrollPaneStacked, ArrowLocation.LEFT,
PrefMgr.getFlag(PrefMgr.STRIDE_SIDEBAR_SHOWING), frameCatalogueShownListener);
collapsibleCatalogueScrollPane.addArrowWrapperStyleClass("catalogue-collapse");
showingCatalogue.bindBidirectional(collapsibleCatalogueScrollPane.expandedProperty());
JavaFXUtil.addChangeListener(showingCatalogue, expanded -> PrefMgr.setFlag(PrefMgr.STRIDE_SIDEBAR_SHOWING, expanded));
JavaFXUtil.runAfterCurrent(() -> {
boolean flag = PrefMgr.getFlag(PrefMgr.STRIDE_SIDEBAR_SHOWING);
showingCatalogue.set(flag);
recordShowHideFrameCatalogue(flag, FrameCatalogue.ShowReason.PROPERTIES);
});
JavaFXUtil.addStyleClass(collapsibleCatalogueScrollPane, "catalogue-scroll-collapsible");
menuAndTabPane.setRight(collapsibleCatalogueScrollPane);
scene = new Scene(new StackPane(menuAndTabPane, dragPane, dragCursorPane, overlayPane.getNode()), 800, 700);
stage.setScene(scene);
Config.addEditorStylesheets(scene);
tabPane.getStyleClass().add("tabbed-editor");
tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
{
@Override
@OnThread(value = Tag.FXPlatform, ignoreParent = true)
public void changed(ObservableValue<? extends Tab> a, Tab prevSel, Tab selTab)
{
if (selTab != null)
FXTabbedEditor.this.updateMenusForTab((FXTab) selTab);
if (prevSel != null && prevSel != selTab)
((FXTab) prevSel).notifyUnselected();
if (selTab != null && stage.isFocused())
((FXTab) selTab).notifySelected();
if (selTab != null && ((FXTab) selTab).shouldShowCatalogue())
{
collapsibleCatalogueScrollPane.setVisible(true);
collapsibleCatalogueScrollPane.setManaged(true);
}
else
{
collapsibleCatalogueScrollPane.setVisible(false);
collapsibleCatalogueScrollPane.setManaged(false);
}
if (FXTabbedEditor.this.isWindowVisible())
{
if (!(selTab instanceof FrameEditorTab))
{
JavaFXUtil.runPlatformLater(() -> FXTabbedEditor.this.scheduleUpdateCatalogue(null, null, CodeCompletionState.NOT_POSSIBLE, false, Frame.View.NORMAL, Collections.emptyList(), Collections.emptyList()));
}
}
}
});
tabPane.getTabs().addListener((ListChangeListener<? super Tab>) e -> {
if (tabPane.getTabs().isEmpty())
{
startSize = new Rectangle((int)stage.getX(), (int)stage.getY(), (int)stage.getWidth(), (int)stage.getHeight());
stage.close();
project.removeFXTabbedEditor(this);
}
});
stage.setOnHidden(e -> {
List<Tab> tabs = new ArrayList<>(tabPane.getTabs());
tabs.forEach(t -> close((FXTab)t));
});
JavaFXUtil.addChangeListenerPlatform(stage.focusedProperty(), focused -> {
if (focused) {
((FXTab) tabPane.getSelectionModel().getSelectedItem()).notifySelected();
}
else {
Tab selectedItem = tabPane.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
((FXTab) selectedItem).notifyUnselected();
}
}
});
JavaFXUtil.addChangeListenerPlatform(stage.iconifiedProperty(), minimised -> {
if (minimised)
((FXTab)tabPane.getSelectionModel().getSelectedItem()).notifyUnselected();
});
tabPane.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if (Config.isWinOS() && (e.getCode() == KeyCode.ALT_GRAPH || (e.getCode() == KeyCode.ALT && e.isControlDown())))
{
e.consume();
return;
}
if (Config.isWinOS() && e.isAltDown() && e.isControlDown())
{
e.consume();
return;
}
if (!e.isShortcutDown() || e.isAltDown())
return;
int tab = tabPane.getSelectionModel().getSelectedIndex();
switch (e.getCode())
{
case DIGIT1: tab = 0; break;
case DIGIT2: tab = 1; break;
case DIGIT3: tab = 2; break;
case DIGIT4: tab = 3; break;
case DIGIT5: tab = 4; break;
case DIGIT6: tab = 5; break;
case DIGIT7: tab = 6; break;
case DIGIT8: tab = 7; break;
case DIGIT9: tab = 8; break;
case TAB:
if (e.isShiftDown())
{
tab = tab - 1;
if (tab < 0)
tab = tabPane.getTabs().size() - 1;
}
else
{
tab = (tab + 1) % tabPane.getTabs().size();
}
break;
default: return;
}
if (tab < tabPane.getTabs().size())
{
tabPane.getSelectionModel().select(tabPane.getTabs().get(tab));
}
e.consume();
});
stage.titleProperty().bind(Bindings.concat(
JavaFXUtil.applyPlatform(tabPane.getSelectionModel().selectedItemProperty(), t -> ((FXTab)t).windowTitleProperty(), "Unknown")
," - ", projectTitle, titleStatus));
}
| It prepares the recordShowHideFrameCatalogue event and invoke the appropriate method to register it.
| If there is an appropriate selected tab, will invoke this tab method after looking for a possible focused cursor.
| If there is no an appropriate selected tab, will invoke the DataCollector's recordShowHideFrameCatalogue method,
| without any info about any editor or a focused cursor.
|
| @param show true for showing and false for hiding
| @param reason The event which triggers the change.
| It is one of the values in the FrameCatalogue.ShowReason enum.
|
@OnThread(Tag.FXPlatform)
private void recordShowHideFrameCatalogue(boolean show, FrameCatalogue.ShowReason reason)
{
Tab selectedTab = tabPane.getSelectionModel().getSelectedItem();
if (selectedTab instanceof InteractionManager) {
((InteractionManager) selectedTab).recordShowHideFrameCatalogue(show, reason);
}
else {
DataCollector.showHideFrameCatalogue(getProject(), null, null, -1, show, reason);
}
}
@OnThread(Tag.FXPlatform)
private void updateMenusForTab(FXTab selTab)
{
menuBar.getMenus().setAll(selTab.getMenus());
}
| Property for whether the catalogue/cheat sheet is currently showing
|
public BooleanProperty catalogueShowingProperty()
{
return showingCatalogue;
}
| Adds the given FXTab to this FXTabbedEditor window
| @param panel The FXTab to add
| @param visible Whether to make the FXTabbedEditor window visible
| @param toFront Whether to bring the tab to the front (i.e. select the tab)
|
@OnThread(Tag.FXPlatform)
public void addTab(final FXTab panel, boolean visible, boolean toFront)
{
addTab(panel, visible, toFront, false);
}
@OnThread(Tag.FXPlatform)
public void addTab(final FXTab panel, boolean visible, boolean toFront, boolean partOfMove)
{
panel.setParent(this, partOfMove);
panel.initialiseFX();
if (!tabPane.getTabs().contains(panel)) {
tabPane.getTabs().add(panel);
if (toFront)
{
setWindowVisible(visible, panel);
bringToFront(panel);
Platform.runLater(panel::focusWhenShown);
}
}
}
| Opens a Javadoc tab for a core Java class (i.e. comes with the JRE)
| with given qualified name.
|
| If there already exists a tab viewing that page, that page is selected rather than
| a new tab being opened.
|
@OnThread(Tag.FXPlatform)
public void openJavaCoreDocTab(String qualifiedClassName)
{
openJavaCoreDocTab(qualifiedClassName, "");
}
| Opens a Javadoc tab for a core Java class (i.e. comes with the JRE) with given qualified name,
| and the given URL suffix (typically, "#method_anchor")
|*
* If there already exists a tab viewing that page, that page is selected rather than
* a new tab being opened.
*/
@OnThread(Tag.FXPlatform)
public void openJavaCoreDocTab(String qualifiedClassName, String suffix)
|
|{
|
|String target = Utility.getDocURL(qualifiedClassName, suffix);
|
|openWebViewTab(target);
|
|}
|
|/**
| Opens a Javadoc tab for a Greenfoot class (e.g. greenfoot.Actor)
| with given qualified name.
|
| If there already exists a tab viewing that page, that page is selected rather than
| a new tab being opened.
|
@OnThread(Tag.FXPlatform)
public void openGreenfootDocTab(String qualifiedClassName)
{
openGreenfootDocTab(qualifiedClassName, "");
}
| Opens a Javadoc tab for a Greenfoot class (e.g. greenfoot.Actor)
| with given qualified name and URL suffix (typically, "#method_anchor")
|*
* If there already exists a tab viewing that page, that page is selected rather than
* a new tab being opened.
*/
@OnThread(Tag.FXPlatform)
public void openGreenfootDocTab(String qualifiedClassName, String suffix)
|
|{
|
|try
|
|{
|
|String target = Utility.getGreenfootApiDocURL(qualifiedClassName.replace('.', '/') + ".html");
openWebViewTab(target + suffix);
}
catch (IOException e)
{
Debug.reportError(e);
}
}
/**
* Sets the window visible, and adds/removes the given tab
| @param visible Whether to add the tab and make window visible (true), or remove the tab (false).
| Window is only hidden if no tabs remain (handled elsewhere in code)
| @param tab The tab in question
|
public void setWindowVisible(boolean visible, Tab tab)
{
if (visible)
{
if (!stage.isShowing()) {
if (startSize != null)
{
stage.setX(startSize.getX());
stage.setY(startSize.getY());
stage.setWidth(startSize.getWidth());
stage.setHeight(startSize.getHeight());
}
stage.show();
}
if (!tabPane.getTabs().contains(tab))
{
tabPane.getTabs().add(tab);
}
}
else
{
tabPane.getTabs().remove(tab);
}
}
| Returns whether the window is currently shown
|
public boolean isWindowVisible()
{
return stage.isShowing();
}
| Brings the tab to the front: unminimises window, brings window to the front, and selects the tab
|
@OnThread(Tag.FXPlatform)
public void bringToFront(Tab tab)
{
stage.setIconified(false);
Utility.bringToFrontFX(stage);
tabPane.getSelectionModel().select(tab);
}
| Gets the project this window is associated with
|
@OnThread(Tag.Any)
public Project getProject()
{
return project;
}
| Removes the given tab from this tabbed editor window
|
@OnThread(Tag.FXPlatform)
public void close(FXTab tab)
{
close(tab, false);
}
@OnThread(Tag.FXPlatform)
private void close(FXTab tab, boolean partOfMove)
{
tabPane.getTabs().remove(tab);
tab.setParent(null, partOfMove);
}
| Opens a web view tab to display the given URL.
|
| If a web view tab already exists which is displaying that URL (sans anchors),
| that tab is displayed and a new tab is not opened.
|
@OnThread(Tag.FXPlatform)
public void openWebViewTab(String url)
{
openWebViewTab(url, false);
}
| Opens a web view tab to display the given URL.
|
| If a web view tab already exists which is displaying that URL (sans anchors),
| that tab is displayed and a new tab is not opened.
|
| @param isTutorial True if this is a special web tab containing the interactive tutorial
|
@OnThread(Tag.FXPlatform)
public void openWebViewTab(String url, boolean isTutorial)
{
try
{
URI target = new URI(url);
for (FXTab tab : getFXTabs())
{
if (tab.getWebAddress() == null)
continue;
URI tabURI = new URI(tab.getWebAddress());
if (tabURI.equals(target))
{
bringToFront(tab);
return;
}
}
}
catch (URISyntaxException e)
{
Debug.reportError("Error in URI when opening web view tab: \"" + url + "\"");
}
addTab(new WebTab(url, isTutorial), true, true);
}
| The list of currently open tabs
|
public ObservableList tabsProperty()
{
return tabPane.getTabs();
}
| The pane on which the dragged frames are shown
|
public Pane getDragPane()
{
return dragPane;
}
| The pane on which dragged frame cursor destinations are shown
| (so that they appear in front of the dragged frames)
|
public Pane getDragCursorPane()
{
return dragCursorPane;
}
| Begin dragging the given list of frames, starting at the given scene position
|
public void frameDragBegin(List<Frame> srcFrames, boolean fromShelf, double mouseSceneX, double mouseSceneY)
{
if (dragIcon != null || !dragSourceFrames.isEmpty())
{
throw new IllegalStateException("Drag begun while drag in progress");
}
dragSourceFrames.clear();
dragSourceFrames.addAll(srcFrames);
Image img = Frame.takeShot(dragSourceFrames, null);
if (dragSourceFrames.stream().allMatch(Frame::canDrag) && img != null)
{
ImageView icon = new ImageView(img);
icon.setEffect(new DropShadow(7.0, 2.0, 2.0, Color.BLACK));
for (Frame src : dragSourceFrames)
{
src.setDragSourceEffect(true);
}
double srcSceneX = dragSourceFrames.get(0).getNode().localToScene(0, 0).getX();
double srcSceneY = dragSourceFrames.get(0).getNode().localToScene(0, 0).getY();
icon.layoutXProperty().bind(mouseDragXProperty.subtract(mouseSceneX - srcSceneX));
icon.layoutYProperty().bind(mouseDragYProperty.subtract(mouseSceneY - srcSceneY));
getDragPane().getChildren().add(icon);
dragIcon = icon;
dragFromShelf = fromShelf;
scene.setCursor(Cursor.CLOSED_HAND);
}
else
{
dragSourceFrames.clear();
}
}
| Notify us that the current frame has reached the given position
| @param sceneX Scene X position of mouse
| @param sceneY Scene Y position of mouse
| @param dragType Whether the copy-drag key is being held (true) or not (false)
|
@OnThread(Tag.FXPlatform)
public void draggedTo(double sceneX, double sceneY, JavaFXUtil.DragType dragType)
{
if (!dragSourceFrames.isEmpty()) {
Point2D p = dragPane.sceneToLocal(sceneX, sceneY);
mouseDragXProperty.set(p.getX());
mouseDragYProperty.set(p.getY());
checkHoverDuringDrag(sceneX, sceneY, dragType);
if (tabPane.getSelectionModel().getSelectedItem() instanceof FrameEditorTab)
{
((FrameEditorTab)tabPane.getSelectionModel().getSelectedItem()).draggedToTab(dragSourceFrames, sceneX, sceneY, calcDragCopy(dragType, false));
}
shelf.draggedTo(dragSourceFrames, sceneX, sceneY, calcDragCopy(dragType, true));
}
}
| Given the current state of this.dragFromShelf and the two params,
| works out if the drag operation would be a copy or a move.
| @param toShelf
| @return true if copying, false if moving
|
private boolean calcDragCopy(JavaFXUtil.DragType dragType, boolean toShelf)
{
switch (dragType)
{
case FORCE_MOVING:
return false;
case FORCE_COPYING:
return true;
default:
if (dragFromShelf && toShelf)
return false;
else if (dragFromShelf && !toShelf)
return true;
else{ return false;
}
}
}
| Returns whether a frame drag is currently taking place
|
public boolean isDragging()
{
return !dragSourceFrames.isEmpty();
}
| During a drag, checks if the mouse is hovering over a tab header.
| (If so, after a little delay, that tab is switched to)
| @param sceneX The mouse scene X position
| @param sceneY The mouse scene Y position
| @param dragType Whether the copy-drag key is being held down
|
@OnThread(Tag.FXPlatform)
private void checkHoverDuringDrag(double sceneX, double sceneY, JavaFXUtil.DragType dragType)
{
for (Tab t : tabPane.getTabs())
{
Bounds b = t.getGraphic().localToScene(t.getGraphic().getBoundsInLocal());
if (b.contains(sceneX, sceneY))
{
if (hoverTab != t && t instanceof FrameEditorTab)
{
hoverTab = t;
if (hoverTabTask != null)
hoverTabTask.run();
hoverTabTask = JavaFXUtil.runAfter(Duration.millis(500), () -> {
((FrameEditorTab)tabPane.getSelectionModel().getSelectedItem()).draggedToAnotherTab();
tabPane.getSelectionModel().select(t);
draggedTo(sceneX, sceneY, dragType);
});
}
}
}
}
| Notify us that a frame drag has ended
| @param dragType Whether the copy-drag key was held down as the drag finished
|
@OnThread(Tag.FXPlatform)
public void frameDragEnd(JavaFXUtil.DragType dragType)
{
if (hoverTabTask != null)
hoverTabTask.run();
hoverTab = null;
if (!dragSourceFrames.isEmpty())
{
getDragPane().getChildren().remove(dragIcon);
dragIcon = null;
dragSourceFrames.forEach(f -> f.setDragSourceEffect(false));
if (tabPane.getSelectionModel().getSelectedItem() instanceof FrameEditorTab)
{
((FrameEditorTab)tabPane.getSelectionModel().getSelectedItem()).dragEndTab(dragSourceFrames, dragFromShelf, calcDragCopy(dragType, false));
}
shelf.dragEnd(dragSourceFrames, dragFromShelf, calcDragCopy(dragType, true));
dragSourceFrames.clear();
scene.setCursor(Cursor.DEFAULT);
}
}
| Schedule a future update to the frame catalogue.
|
| @param editor The editor associated with the currently shown tab.
| Pass null if a different kind of tab (e.g. web tab) is showing.
| @param c The frame cursor currently focused.
| Pass null if there is no currently focused cursor or a different kind of tab is showing
| @param codeCompletion Whether code completion is currently possible
| @param selection Whether there is currently a frame selection
| @param viewMode The current view mode (if a frame editor tab is showing)
| @param hints The list of hints that should be displayed
|
@OnThread(Tag.FXPlatform)
public void scheduleUpdateCatalogue(FrameEditorTab editor, FrameCursor c, CodeCompletionState codeCompletion, boolean selection, Frame.View viewMode, List<ExtensionDescription> altExtensions, List<Hint> hints)
{
cataloguePane.scheduleUpdateCatalogue(editor, viewMode == Frame.View.NORMAL ? c : null, codeCompletion, selection, viewMode, altExtensions, hints);
}
| Gets the window overlay pane
|
public WindowOverlayPane getOverlayPane()
{
return overlayPane;
}
| Returns true when, and only when, this editor window has a single tab in it
|
public boolean hasOneTab()
{
return tabPane.getTabs().size() == 1;
}
public boolean containsTab(Tab tab)
{
return tabPane.getTabs().contains(tab);
}
public StringExpression titleProperty()
{
return stage.titleProperty();
}
private List getFXTabs()
{
return Utility.mapList(tabPane.getTabs(), t -> (FXTab)t);
}
@OnThread(Tag.Swing)
public void setPosition(int x, int y)
{
Platform.runLater(() -> {
stage.setX(x);
stage.setY(y);
});
}
@OnThread(Tag.Swing)
public void setSize(int width, int height)
{
Platform.runLater(() -> {
stage.setWidth(width);
stage.setHeight(height);
});
}
public void setTitleStatus(String status)
{
this.titleStatus.set(status);
}
public Window getWindow()
{
return stage;
}
public static void setupFrameDrag(Frame f, boolean isShelf, FXSupplier<FXTabbedEditor> parent, FXSupplier<Boolean> canDrag, FXSupplier<FrameSelection> selection)
{
f.getNode().setOnDragDetected(event -> {
double mouseSceneX = event.getSceneX();
double mouseSceneY = event.getSceneY();
if (canDrag.get())
{
if (selection.get().contains(f))
{
parent.get().frameDragBegin(selection.get().getSelected(), isShelf, mouseSceneX, mouseSceneY);
}
else
{
parent.get().frameDragBegin(Arrays.asList(f), isShelf, mouseSceneX, mouseSceneY);
}
}
event.consume();
});
f.getNode().setOnMouseDragged(event -> {
parent.get().draggedTo(event.getSceneX(), event.getSceneY(), JavaFXUtil.getDragModifiers(event));
event.consume();
});
f.getNode().setOnMouseReleased(event -> {
if (!parent.get().isDragging())
return;
parent.get().draggedTo(event.getSceneX(), event.getSceneY(), JavaFXUtil.getDragModifiers(event));
parent.get().frameDragEnd(JavaFXUtil.getDragModifiers(event));
event.consume();
});
}
| Called when this window is no longer going to be used
|
public void cleanup()
{
shelf.cleanup();
}
| Does one of the tabs in this window contain a tutorial web view tab?
|
public boolean hasTutorial()
{
return tabPane.getTabs().stream().anyMatch(t -> t instanceof FXTab && ((FXTab)t).isTutorial());
}
public static enum CodeCompletionState
{
NOT_POSSIBLE, SHOWING, POSSIBLE;
}
@OnThread(Tag.FXPlatform)
public void moveToNewLater(FXTab tab)
{
FXTabbedEditor newWindow = project.createNewFXTabbedEditor();
moveTabTo(tab, newWindow);
}
@OnThread(Tag.FXPlatform)
public void moveTabTo(FXTab tab, FXTabbedEditor destination)
{
close(tab, true);
destination.addTab(tab, true, true, true);
}
@OnThread(Tag.FXPlatform)
public void updateMoveMenus()
{
tabPane.getTabs().forEach(t -> updateMenusForTab((FXTab)t));
}
@OnThread(Tag.FX)
public int getX()
{
return (int)stage.getX();
}
@OnThread(Tag.FX)
public int getY()
{
return (int)stage.getY();
}
@OnThread(Tag.FX)
public int getWidth()
{
return (int)stage.getWidth();
}
@OnThread(Tag.FX)
public int getHeight()
{
return (int)stage.getHeight();
}
}
. - FXTabbedEditor
. FXTabbedEditor
. isUselessDrag
. initialise
. initialiseFX
. changed
. recordShowHideFrameCatalogue
. updateMenusForTab
. catalogueShowingProperty
. addTab
. addTab
. openJavaCoreDocTab
. openGreenfootDocTab
. setWindowVisible
. isWindowVisible
. bringToFront
. getProject
. close
. close
. openWebViewTab
. openWebViewTab
. tabsProperty
. getDragPane
. getDragCursorPane
. frameDragBegin
. draggedTo
. calcDragCopy
. isDragging
. checkHoverDuringDrag
. frameDragEnd
. scheduleUpdateCatalogue
. getOverlayPane
. hasOneTab
. containsTab
. titleProperty
. getFXTabs
. setPosition
. setSize
. setTitleStatus
. getWindow
. setupFrameDrag
. cleanup
. hasTutorial
. moveToNewLater
. moveTabTo
. updateMoveMenus
. getX
. getY
. getWidth
. getHeight
1042 neLoCode
+ 106 LoComm