package greenfoot.guifx.images;
import bluej.Config;
import bluej.pkgmgr.Project;
import bluej.utility.Debug;
import bluej.utility.DialogManager;
import bluej.utility.FileUtility;
import bluej.utility.javafx.FXConsumer;
import bluej.utility.javafx.FXRunnable;
import bluej.utility.javafx.JavaFXUtil;
import greenfoot.guifx.PastedImageNameDialog;
import greenfoot.guifx.classes.LocalGClassNode;
import greenfoot.util.ExternalAppLauncher;
import greenfoot.util.GreenfootUtil;
import java.io.File;
import java.io.IOException;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Window;
import javafx.util.Duration;
import threadchecker.OnThread;
import threadchecker.Tag;
import javax.swing.*;
| A Pane for selecting a class image. The image can be selected from either the
| project image library, or the greenfoot library, or an external location.
|
| @author Davin McCall
| @author Amjad Altadmri
|
@OnThread(Tag.FXPlatform)
class ImageLibPane
extends VBox{
private final Project project;
private final Window container;
private FXRunnable cancelRefresh;
private ImageLibList projImageList;
private ImageLibList greenfootImageList;
private File projImagesDir;
private ObjectProperty<File> selectedImageFile = new SimpleObjectProperty<>(null);
| Menu items that are in the context menu.
|
private MenuItem editItem;
private MenuItem duplicateItem;
private MenuItem deleteItem;
| Suffix used when creating a copy of an existing image (duplicate)
|
private static final String COPY_SUFFIX = Config.getString("imagelib.duplicate.image.name.suffix");
| PopupMenu icon
|
private static final String DROPDOWN_ICON_FILE = "menu-button.png";
| Construct ImageLibPane with a known classTarget. Usually used by
| the SelectImageFrame for selecting an image for an existing class.
|
| @param container The contained frame
| @param project The project
| @param classNode The class node of the existing class
|
ImageLibPane(Window container, Project project, LocalGClassNode classNode)
{
this(container, project, getSpecifiedImage(project, classNode));
}
| Construct ImageLibPane. Usually used by the NewImageClassFrame for creating an new image class.
|
| @param container The contained window
| @param project The current project
|
ImageLibPane(Window container, Project project)
{
this(container, project, (File) null);
}
| A private construct for ImageLibPane to build assign the fields and build the controls.
|
| @param container The contained window
| @param project The current project
| @param specifiedImage The image to be selected initially
|
private ImageLibPane(Window container, Project project, File specifiedImage)
{
super(10);
this.container = container;
this.project = project;
getChildren().addAll(buildImageLists(specifiedImage), createCogMenu());
setItemButtons(projImageList.getSelectionModel().getSelectedItem() != null
&& projImageList.getSelectionModel().getSelectedItem().getImageFile() != null);
container.setOnShown(e -> {
cancelRefresh = JavaFXUtil.runRegular(Duration.millis(1000), () -> projImageList.refresh());
});
container.setOnHidden(e -> {
if (cancelRefresh != null)
{
cancelRefresh.run();
cancelRefresh = null;
}
});
}
| Build Image selection panels - project and greenfoot image library.
|
| @param specifiedImage The image to be selected. Could be null.
| @return a Pane containing the image lists.
|
private Pane buildImageLists(File specifiedImage)
{
GridPane listsGridPane = new GridPane();
listsGridPane.setVgap(5);
ColumnConstraints constraints = new ColumnConstraints();
constraints.setHgrow(Priority.SOMETIMES);
listsGridPane.getColumnConstraints().setAll(constraints, constraints, constraints);
projImagesDir = new File(project.getProjectDir(), "images");
projImageList = new ImageLibList(projImagesDir, true);
projImageList.select(specifiedImage);
ScrollPane imageScrollPane = new ScrollPane(projImageList);
imageScrollPane.setFitToWidth(true);
imageScrollPane.setFitToHeight(true);
GridPane.setVgrow(imageScrollPane, Priority.ALWAYS);
GridPane.setMargin(imageScrollPane, new Insets(0, 10, 0, 0));
listsGridPane.addColumn(0, new Label(Config.getString("imagelib.projectImages")), imageScrollPane);
greenfootImageList = new ImageLibList(false);
JavaFXUtil.addChangeListenerPlatform(projImageList.getSelectionModel().selectedItemProperty(), imageListEntry -> valueChanged(imageListEntry, true));
JavaFXUtil.addChangeListenerPlatform(greenfootImageList.getSelectionModel().selectedItemProperty(), imageListEntry -> valueChanged(imageListEntry, false));
ImageCategorySelector imageCategorySelector = new ImageCategorySelector(new File(Config.getGreenfootLibDir(), "imagelib"));
imageCategorySelector.setImageLibList(greenfootImageList);
ScrollPane categoryScrollPane = new ScrollPane(imageCategorySelector);
categoryScrollPane.setFitToWidth(true);
categoryScrollPane.setFitToHeight(true);
listsGridPane.addColumn(1, new Label(Config.getString("imagelib.categories")), categoryScrollPane);
ScrollPane greenfootImagesScrollPane = new ScrollPane(greenfootImageList);
greenfootImagesScrollPane.setFitToWidth(true);
greenfootImagesScrollPane.setFitToHeight(true);
listsGridPane.addColumn(2, new Label(Config.getString("imagelib.images")), greenfootImagesScrollPane);
VBox.setVgrow(listsGridPane, Priority.ALWAYS);
return listsGridPane;
}
| Creates the cog button, which contains options for a selected image and options to
| add new or imported images to the project.
|
| @return a Menu Button representing the cog.
|
private MenuButton createCogMenu()
{
editItem = createSelectedEntryMenuItem("imagelib.edit", "imagelib.edit.tooltip", this::editImage);
duplicateItem = createSelectedEntryMenuItem("imagelib.duplicate", "imagelib.duplicate.tooltip", this::duplicateSelected);
deleteItem = createSelectedEntryMenuItem("imagelib.delete", "imagelib.delete.tooltip", this::confirmDelete);
return new MenuButton(null,
new ImageView(new Image(ImageLibPane.class.getClassLoader().getResourceAsStream(DROPDOWN_ICON_FILE))),
editItem, duplicateItem, deleteItem, new SeparatorMenuItem(),
createGeneralMenuItem("imagelib.create.button", "imagelib.create.tooltip", event -> createNewImage()),
createGeneralMenuItem("imagelib.paste.image", "imagelib.paste.tooltip", event -> pasteImage()),
createGeneralMenuItem("imagelib.import.button", "imagelib.import.tooltip", event -> importImage()));
}
| Create a MenuItem for an image list entry, assign an action to it and disable it initially.
|
| @param label The label of the menu item.
| @param tooltip The text of the tooltip to show.
| @param consumer The action to be performed on the selected entry.
| @return A menu item which invokes the action passed on the selected image list entry.
|
private MenuItem createSelectedEntryMenuItem(String label, String tooltip, FXConsumer<ImageListEntry> consumer)
{
MenuItem item = new MenuItem(Config.getString(label));
Tooltip.install(item.getGraphic(), new Tooltip(Config.getString(tooltip)));
item.setDisable(true);
item.setOnAction(event -> {
ImageListEntry entry = projImageList.getSelectionModel().getSelectedItem();
if (entry != null && entry.getImageFile() != null)
{
consumer.accept(entry);
}
});
return item;
}
| Create a general MenuItem and assign an action to it.
|
| @param label The label of the menu item.
| @param tooltip The text of the tooltip to show.
| @param eventHandler The action to be performed by the menu item.
| @return A menu item which invokes the passed action.
|
private MenuItem createGeneralMenuItem(String label, String tooltip, EventHandler<ActionEvent> eventHandler)
{
MenuItem item = new MenuItem(Config.getString(label));
Tooltip.install(item.getGraphic(), new Tooltip(Config.getString(tooltip)));
item.setOnAction(eventHandler);
return item;
}
| Create a new image through new image dialog.
|
private void createNewImage()
{
new NewImageDialog(container, projImagesDir).showAndWait().ifPresent(file -> {
projImageList.refresh();
projImageList.select(file);
selectImage(file);
});
}
| An image was selected/unselected in one of the ImageLibLists
|
| @param entry The image entry selected/unselected
| @param isProjImageList True if the entry effected is in the
| project images' list, false otherwise.
|
private void valueChanged(ImageListEntry entry, boolean isProjImageList)
{
if (entry != null && entry.getImageFile() != null)
{
if (isProjImageList)
{
greenfootImageList.getSelectionModel().clearSelection();
}
else
{
projImageList.getSelectionModel().clearSelection();
}
selectImage(entry.getImageFile());
setItemButtons(isProjImageList);
}
else
{
selectImage(null);
setItemButtons(false);
}
}
| Change the three selection based menu items to the
| parameter provided.
| @param state To enable or disable the menu item buttons.
|
private void setItemButtons(boolean state)
{
editItem.setDisable(!state);
duplicateItem.setDisable(!state);
deleteItem.setDisable(!state);
}
| Selects the given file (or no file).
|
| @param imageFile The file to select. If null, then "no image" is selected.
|*/
private void selectImage(File imageFile)
{
selectedImageFile.set(imageFile);
}
/**
* Gets specified image file (which will be in the project images/ directory) for this specific
| class, without searching super classes (see getClassImage for that). Returns null if none
| specified.
|
private static File getSpecifiedImage(Project project, LocalGClassNode gclass)
{
String imageName = gclass.getImageFilename();
if (imageName != null && !imageName.equals(""))
{
File imageDir = new File(project.getProjectDir(), "images");
return new File(imageDir, imageName).getAbsoluteFile();
}
return null;
}
private void importImage()
{
FileChooser chooser = new FileChooser();
chooser.setTitle(Config.getString("imagelib.browse.button"));
chooser.getExtensionFilters().addAll(
new ExtensionFilter("Images", "*.png", "*.jpg", "*.jpeg", "*.gif"),
new ExtensionFilter("All Files", "*.*"));
File selectedFile = chooser.showOpenDialog(container);
if (selectedFile != null)
{
File newFile = new File(projImagesDir, selectedFile.getName());
GreenfootUtil.copyFile(selectedFile, newFile);
if (projImageList != null)
{
projImageList.select(newFile);
}
}
}
| Get the selected image file
|
public ObjectProperty selectedImageProperty()
{
return selectedImageFile;
}
| Create a new file which is an exact copy of the parameter
| image, and select it if it has been craeted successfully.
|
| @param entry Cannot be null, nor can its imageFile.
|
private void duplicateSelected(ImageListEntry entry)
{
File srcFile = entry.getImageFile();
File dstFile = null;
File dir = srcFile.getParentFile();
String fileName = srcFile.getName();
int index = fileName.lastIndexOf('.');
String baseName;
String ext;
if (index != -1)
{
baseName = fileName.substring(0, index);
ext = fileName.substring(index + 1);
}
else
{
baseName = fileName;
ext = "";
}
baseName += ("_" + COPY_SUFFIX);
try
{
dstFile = GreenfootUtil.createNumberedFile(dir, baseName, ext);
FileUtility.copyFile(srcFile, dstFile);
}
catch (IOException e)
{
Debug.reportError(e);
}
if (dstFile != null)
{
projImageList.select(dstFile);
}
}
| Confirms whether or not to delete the selected file.
| @param entry Cannot be null, nor can its imageFile.
|
private void confirmDelete(ImageListEntry entry)
{
boolean delete = DialogManager.askQuestionFX(container, "imagelib-delete-confirm",
new String[] {entry.getImageFile().getName()
}) == 0;
if (delete)
{
entry.getImageFile().delete();
projImageList.refresh();
}
}
| Opens an external app to edit an image file.
|
| @param entry The list entry contains the image.
|
private void editImage(ImageListEntry entry)
{
File file = entry.getImageFile();
SwingUtilities.invokeLater(() -> ExternalAppLauncher.editImage(file));
}
private void pasteImage()
{
if (Clipboard.getSystemClipboard().hasImage())
{
Image image = Clipboard.getSystemClipboard().getImage();
new PastedImageNameDialog(container, image, projImagesDir).showAndWait().ifPresent(file -> {
projImageList.refresh();
projImageList.select(file);
selectImage(file);
});
}
else
{
DialogManager.showErrorFX(container, "no-clipboard-image-data");
}
}
}
. - ImageLibPane
. ImageLibPane
. buildImageLists
. createCogMenu
. createSelectedEntryMenuItem
. createGeneralMenuItem
. createNewImage
. valueChanged
. setItemButtons
. getSpecifiedImage
. importImage
. selectedImageProperty
. duplicateSelected
. confirmDelete
. editImage
. pasteImage
431 neLoCode
+ 55 LoComm