package bluej.pkgmgr;

import bluej.BlueJEvent;
import bluej.Boot;
import bluej.Config;
import bluej.classmgr.BPClassLoader;
import bluej.classmgr.ClassMgrPrefPanel;
import bluej.collect.DataCollector;
import bluej.compiler.CompileReason;
import bluej.compiler.CompileType;
import bluej.debugger.Debugger;
import bluej.debugger.DebuggerClass;
import bluej.debugger.DebuggerEvent;
import bluej.debugger.DebuggerListener;
import bluej.debugger.DebuggerObject;
import bluej.debugger.DebuggerThread;
import bluej.debugger.DebuggerThreadListener;
import bluej.debugger.RunOnThread;
import bluej.debugmgr.ExecControls;
import bluej.debugmgr.ExpressionInformation;
import bluej.debugmgr.inspector.ClassInspector;
import bluej.debugmgr.inspector.Inspector;
import bluej.debugmgr.inspector.InspectorManager;
import bluej.debugmgr.inspector.ObjectInspector;
import bluej.debugmgr.inspector.ResultInspector;
import bluej.debugmgr.objectbench.ObjectBench;
import bluej.debugmgr.objectbench.ObjectWrapper;
import bluej.editor.Editor;
import bluej.editor.stride.FXTabbedEditor;
import bluej.editor.stride.FrameShelfStorage;
import bluej.extensions.BProject;
import bluej.extensions.ExtensionBridge;
import bluej.extmgr.ExtensionsManager;
import bluej.groupwork.Repository;
import bluej.groupwork.TeamSettingsController;
import bluej.groupwork.actions.TeamActionGroup;
import bluej.groupwork.ui.CommitAndPushFrame;
import bluej.groupwork.ui.CommitAndPushInterface;
import bluej.groupwork.ui.CommitCommentsFrame;
import bluej.groupwork.ui.StatusFrame;
import bluej.groupwork.ui.TeamSettingsDialog;
import bluej.groupwork.ui.UpdateFilesFrame;
import bluej.parser.entity.EntityResolver;
import bluej.pkgmgr.target.ClassTarget;
import bluej.pkgmgr.target.Target;
import bluej.prefmgr.PrefMgr;
import bluej.terminal.Terminal;
import bluej.testmgr.record.ClassInspectInvokerRecord;
import bluej.testmgr.record.InvokerRecord;
import bluej.utility.Debug;
import bluej.utility.DialogManager;
import bluej.utility.FileUtility;
import bluej.utility.FileUtility.WriteCapabilities;
import bluej.utility.ImportScanner;
import bluej.utility.JavaNames;
import bluej.utility.Utility;
import bluej.utility.javafx.JavaFXUtil;
import bluej.views.View;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.stage.Window;
import javafx.util.Duration;
import threadchecker.OnThread;
import threadchecker.Tag;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.*;


| A BlueJ Project. | | @author Michael Kolling | @author Axel Schmolitzky | @author Andrew Patterson | @author Bruce Quig | public class Project implements DebuggerListener, DebuggerThreadListener, InspectorManager{ public static final int NEW_PACKAGE_DONE = 0; public static final int NEW_PACKAGE_EXIST = 1; public static final int NEW_PACKAGE_BAD_NAME = 2; public static final int NEW_PACKAGE_NO_PARENT = 3; public static final String projectLibDirName = "+libs";
| Property specifying location of JDK source | private static final String JDK_SOURCE_PATH_PROPERTY = "bluej.jdk.source"; private static final String PROJECT_CHARSET_PROP = "project.charset"; public static final String RUN_ON_THREAD_PROP = "project.invoke.thread";
| Collection of all open projects. The canonical name of the project | directory (as a File object) is used as the key. | private static Map<File,Project> projects = new HashMap<File,Project>(); | the path of the project directory. | private final File projectDir;
| reference to the unnamed package | @OnThread(Tag.Any) private final Package unnamedPackage;
| Resolve javadoc for this project | private final JavadocResolver javadocResolver;
| collection of open packages in this project | |(indexed by the qualifiedName of the package). | |The unnamed package ie root package of the package tree | |can be obtained by retrieving "" from this collection */ private Map<String, Package> packages; /** the debugger for this project */ @OnThread(Tag.Any) private final Debugger debugger; /** the ExecControls for this project private ExecControls execControls = null;
| the Terminal for this project | private Terminal terminal = null;
| the documentation generator for this project. | private DocuGenerator docuGenerator;
| when a project is opened, the user may specify a | |directory deep into the projects directory structure. | |BlueJ will correctly find the top of this package | |heirarchy but the bit of the name left over will be | |put into this variable | |ie if opening /home/user/foo/com/sun where | |/home/user/foo is the project directory, this variable | |will be set to com.sun private String initialPackageName = "";
| This holds all object inspectors and class inspectors | |for a project. It should only hold object inspectors that | |have a wrapper on the object bench. Inspectors of fields of | |object inspectors should be handled at the object wrapper level @OnThread(Tag.FXPlatform) private Map<Object,Inspector> inspectors; @OnThread(value = Tag.Any, requireSynchronized = true) private boolean inTestMode = false; private BPClassLoader currentClassLoader; private List<URL> libraryUrls; private TeamSettingsController teamSettingsController = null; private CommitAndPushInterface commitCommentsFrame = null; private UpdateFilesFrame updateFilesFrame = null; private StatusFrame statusFrame = null;
| If true, this project is connected with a source repository | | If empty, not checked yet | @OnThread(value = Tag.Any, requireSynchronized = true) private Optional<Boolean> isSharedProject = Optional.empty(); private TeamActionGroup teamActions;
| Where to find JDK and other library sources (for extracting javadoc) | private List<DocPathEntry> sourcePath;
| Project character set for source files etc | @OnThread(value = Tag.Any,requireSynchronized = true) private Charset characterSet; @OnThread(Tag.FX) private final List<FXTabbedEditor> fXTabbedEditors = new ArrayList<>(); @OnThread(Tag.FX) private final List<Rectangle> fxCachedEditorSizes = new ArrayList<>();
| 1 second timer before starting auto-compile | @OnThread(Tag.FXPlatform) private Timeline compilerTimer; @OnThread(Tag.FXPlatform) private CompileReason latestCompileReason; @OnThread(Tag.FXPlatform) private CompileType latestCompileType;
| Packages scheduled for autocompilation | @OnThread(Tag.FXPlatform) private Set<Package> scheduledPkgs = new HashSet<>();
| Targets scheduled for autocompilation | @OnThread(Tag.FXPlatform) private Set<ClassTarget> scheduledTargets = new HashSet<>();
| The threads currently running in the debugger for this project. We need | to track this in Project because ExecControls may not be showing from the | outset, but we need the state of the threads to be available when | we do show ExecControls, so Project must keep track ready for ExecControls | to potentially be shown later on | private final ObservableList<DebuggerThreadDetails> threadListContents = FXCollections.observableArrayList(); private BProject singleBProject; private boolean closing = false;
| The scanner for available imports. May be null if not requested yet. | @OnThread(value = Tag.Any,requireSynchronized = true) private ImportScanner importScanner;
| check if the project is a dvcs project | private boolean isDVCS=false; private final FrameShelfStorage shelfStorage; private final BooleanProperty terminalShowing = new SimpleBooleanProperty(false); private final BooleanProperty debuggerShowing = new SimpleBooleanProperty(false); private RunOnThread runOnThread; | Construct a project in the directory projectDir. | This must contain the root bluej.pkg of a nested package | (this should by its nature be the unnamed package). | private Project(File projectDir) throws IOException { if (projectDir == null) { throw new NullPointerException(); } Debug.log("Opening project: " + projectDir.toString()); javadocResolver = new ProjectJavadocResolver(this); sourcePath = new ArrayList<DocPathEntry>(); File javaHome = Boot.getInstance().getJavaHome(); File jdkSourceZip = new File(javaHome, "src.zip"); if (jdkSourceZip.isFile()) { sourcePath.add(new DocPathEntry(jdkSourceZip, "")); } else { File javaHomeLib = new File(javaHome, "lib"); jdkSourceZip = new File(javaHomeLib, "src.zip"); if (jdkSourceZip.exists()) { sourcePath.add(new DocPathEntry(jdkSourceZip, "")); } else { jdkSourceZip = new File(javaHome, "src.jar"); if (jdkSourceZip.exists()) { sourcePath.add(new DocPathEntry(jdkSourceZip, "src")); } } } String jdkSourcePath = Config.getPropString(JDK_SOURCE_PATH_PROPERTY, null); if (jdkSourcePath != null) { sourcePath.add(new DocPathEntry(new File(jdkSourcePath), "")); } File javafxSourceZip = Boot.getInstance().getJavaFXSourcePath(); if (javafxSourceZip.isFile()) { sourcePath.add(new DocPathEntry(javafxSourceZip, "")); } this.projectDir = projectDir; libraryUrls = getLibrariesClasspath(); inspectors = new HashMap<Object,Inspector>(); packages = new TreeMap<String, Package>(); docuGenerator = new DocuGenerator(this); unnamedPackage = new Package(this); Properties props = unnamedPackage.getLastSavedProperties(); loadProjectProperties(props); packages.put("", unnamedPackage); shelfStorage = new FrameShelfStorage(this.projectDir); createNewFXTabbedEditor(); getPackage("").refreshPackage(); debugger = Debugger.getDebuggerImpl(getProjectDir(), getTerminal(), this); debugger.setUserLibraries(libraryUrls.toArray(new URL[libraryUrls.size()])); debugger.newClassLoader(getClassLoader()); debugger.addDebuggerListener(this); debugger.setRunOnThread(getRunOnThread() == null ? RunOnThread.DEFAULT : getRunOnThread()); debugger.launch(); File ccfFile = new File(projectDir.getAbsoluteFile(), "team.defs"); isSharedProject = Optional.of(ccfFile.isFile()); isDVCS=false; if (isSharedProject.get()){ TeamSettingsController tsc = new TeamSettingsController(this); isSharedProject = Optional.of(TeamSettingsController.isValidVCSfound(projectDir)); if (isSharedProject.get()){ isDVCS = tsc.isDVCS(); } } teamActions = new TeamActionGroup(isSharedProject.get(), isDVCS); JavaFXUtil.addChangeListenerPlatform(terminalShowing, showTerm -> { if (showTerm && !hasTerminal()) { getTerminal().showHide(true); } }); JavaFXUtil.addChangeListenerPlatform(debuggerShowing, showDebugger -> { if (showDebugger && !hasExecControls()) { ExecControls execControls = getExecControls(); if (showDebugger) execControls.show(); else{ execControls.hide(); } } }); }
| Check if the path given is either a directory with a project file or if | it is the project file itself (project.greenfoot or package.bluej). | | @param projectPath a string representing the path to check. This can | either be a directory name or the filename of a project | file. | @OnThread(Tag.Any) public static boolean isProject(String projectPath) { File startingDir; try { startingDir = pathIntoStartingDirectory(projectPath); } catch (IOException ioe) { return false; } if (startingDir == null) { return false; } return (Package.isPackage(startingDir)); }
| Open a BlueJ project (or find an existing open project). | | @param projectPath | a string representing the path to open. This can either be a | directory name or the filename of a bluej.pkg file. | @return the Project representing the BlueJ project that has this | directory within it or null if there were no bluej.pkg files in | the specified directory. | public static Project openProject(String projectPath) { String startingPackageName; File projectDir; File startingDir; try { startingDir = pathIntoStartingDirectory(projectPath); } catch (IOException ioe) { Debug.reportError("could not resolve directory " + projectPath, ioe); return null; } if (startingDir == null) { return null; } if (Package.isPackage(startingDir)) { File curDir = startingDir; File lastDir = null; startingPackageName = ""; while ((curDir != null) && Package.isPackage(curDir)){ if (lastDir != null) { String lastdirName = lastDir.getName(); if (!JavaNames.isIdentifier(lastdirName)) { break; } startingPackageName = "." + lastdirName + startingPackageName; } lastDir = curDir; curDir = curDir.getParentFile(); } if (startingPackageName.length() > 0) { if (startingPackageName.charAt(0) == '.') { startingPackageName = startingPackageName.substring(1); } } projectDir = lastDir; if (projectDir == null) { projectDir = startingDir; } } else { return null; } boolean readOnly = false; if (Config.isModernWinOS()) { WriteCapabilities capabilities = FileUtility.getVistaWriteCapabilities(projectDir); switch (capabilities) { case VIRTUALIZED_WRITE: Utility.bringToFrontFX(null); DialogManager.showMessageFX(null, "project-is-virtualized"); break; case READ_ONLY: readOnly = true; break; case NORMAL_WRITE: break; default: break; } } else if (!projectDir.canWrite()) { readOnly = true; } boolean isGreenfootStartupProject = Config.isGreenfootStartupProject(projectDir); if (readOnly && !isGreenfootStartupProject) { Utility.bringToFrontFX(null); DialogManager.showMessageFX(null, "project-is-readonly", projectDir.toString()); boolean done = false; while (!done) { File newName = FileUtility.getSaveProjectFX(null, null, Config.getString("pkgmgr.saveAs.title")); if (newName != null) { int result = FileUtility.copyDirectory(projectDir, newName); switch (result) { case FileUtility.NO_ERROR: projectDir = newName; done = true; break; case FileUtility.DEST_EXISTS_NOT_DIR: DialogManager.showErrorFX(null, "directory-exists-file"); break; case FileUtility.DEST_EXISTS_NON_EMPTY: DialogManager.showErrorFX(null, "directory-exists-non-empty"); break; case FileUtility.SRC_NOT_DIRECTORY: case FileUtility.COPY_ERROR: DialogManager.showErrorFX(null, "cannot-save-project"); break; } } else { done = true; } } } Project proj = projects.get(projectDir); if (proj == null) { try { proj = new Project(projectDir); if (proj.isTeamProject() && !proj.getTeamSettingsController().isDVCS() && proj.getTeamSettingsController().getWorkingCopyVersion() != 1.6) { DialogManager.showMessageFX(null, "SVNWorkingCopyNot16"); } projects.put(projectDir, proj); } catch (IOException ioe) { return null; } } if (startingPackageName.equals("")) { Package startingPackage = proj.getPackage(""); while (startingPackage != null){ Package sub = startingPackage.getBoringSubPackage(); if (sub == null) { break; } startingPackage = sub; } proj.initialPackageName = startingPackage.getQualifiedName(); } else { proj.initialPackageName = startingPackageName; } ExtensionsManager.getInstance().projectOpening(proj); DataCollector.projectOpened(proj, ExtensionsManager.getInstance().getLoadedExtensions(proj)); proj.getImportScanner().startScanning(); PrefMgr.addRecentProject(proj.getProjectDir()); File tutorialFile = new File(proj.getProjectDir(), "tutorial.html"); if (tutorialFile.exists()) { try { proj.createNewFXTabbedEditor().openWebViewTab(tutorialFile.toURI().toURL().toString(), true); } catch (MalformedURLException e) { Debug.reportError(e); } } return proj; }
| CleanUp the mess left by a project that has now been closed and | throw it away. | public static void cleanUp(Project project) { DataCollector.projectClosed(project); if (project.hasExecControls()) { project.getExecControls().hide(); } if (project.terminal != null) { project.terminal.cleanup(); project.terminal.dispose(); } if (project.statusFrame != null) { project.statusFrame.close(); } project.removeAllInspectors(); project.getDebugger().removeDebuggerListener(project); project.getDebugger().close(false); projects.remove(project.getProjectDir()); }
| Create a new project in the directory specified by projectPath. | This name must be a directory that does not already exist. | | @param projectPath a string representing the path in which | to make the new project | @return a boolean indicating success or failure | @OnThread(Tag.Any) public static boolean createNewProject(String projectPath) { if (projectPath != null) { File dir = new File(projectPath); if (dir.exists() && (!dir.isDirectory() || dir.list().length > 0)) { return false; } if (dir.exists() || dir.mkdir()) { File newreadmeFile = new File(dir, Package.readmeName); PackageFile pkgFile = PackageFileFactory.getPackageFile(dir); try { if (pkgFile.create()) { Properties props = new Properties(); if (Config.isGreenfoot()) { props.put("mainWindow.width", "850"); props.put("mainWindow.height", "600"); props.put("mainWindow.x", "40"); props.put("mainWindow.y", "40"); } props.put(PROJECT_CHARSET_PROP, "UTF-8"); try { pkgFile.save(props); FileUtility.copyFile(Config.getTemplateFile( "readme"), newreadmeFile); return true; } catch (IOException ioe) { Debug.message("I/O error while creating project: " + ioe.getMessage()); } } } catch (IOException ioe) { } } } Debug.message("Unable to create project directory: " + projectPath); return false; }
| Returns the number of open projects | public static int getOpenProjectCount() { return projects.size(); }
| Gets the set of currently open projects. It is an accessor only. | @return a Set containing all open projects. | public static Collection getProjects() { return projects.values(); }
| Given a Projects key returns the Project objects describing this projects. | public static Project getProject(File projectKey) { return projects.get(projectKey); }
| Helper function to take a path (either a directory or a file) | and return either the canonical path to the directory | (in the case of a bluej.pkg file passed in, return the directory containing | the file. Returns null if file is not a bluej.pkg file or if the | directory/file does not exist. | @OnThread(Tag.Any) private static File pathIntoStartingDirectory(String projectPath) throws IOException { File startingDir; startingDir = new File(projectPath).getCanonicalFile(); if (startingDir.isDirectory()) { return startingDir; }
| allow a bluej.pkg file to be specified. In this case, | |we immediately find the parent directory and use that as the | |starting directory if (startingDir.isFile()) { if (Package.isPackageFileName(startingDir.getName())) { return startingDir.getParentFile(); } } return null; }
| Attempts to add a library to the given list of libraries. | A valid library file is one that is a file, readable, ends either with zip or jar. | Before addition the file is transformed to a URL. | @param risul where to add the file | @param aFile the file to be added. | @OnThread(Tag.Any) private static final void attemptAddLibrary(List<URL> risul, File aFile) { if ( aFile == null ) return; if ( ! (aFile.isFile() && aFile.canRead()) ) return; String libname = aFile.getName().toLowerCase(); if ( ! (libname.endsWith(".jar") || libname.endsWith(".zip")) ) return; try { risul.add(aFile.toURI().toURL()); } catch(MalformedURLException mue) { Debug.reportError("Project.attemptAddLibrary() malformaed file="+aFile); } }
| Returns an array of URLs for all the JAR files located in the lib/userlib directory. | The result is calculated every time the method is called, in this way it is possible | to capture a change in the library content in a reasonable timing. | | @return URLs of the discovered JAR files | @OnThread(Tag.Any) public static final List getUserlibContent() { List<URL> risul = new ArrayList<URL>(); File userLibDir; String userLibSetting = Config.getPropString("bluej.userlibLocation", null); if (userLibSetting == null) { userLibDir = new File(Boot.getBluejLibDir(), "userlib"); } else { userLibDir = new File(userLibSetting); } File[] files = userLibDir.listFiles(); if (files == null) { return risul; } for (int index = 0; index < files.length; index++) { attemptAddLibrary(risul, files[index]); } return risul; }
| Get the character set that should be used for reading and writing source files | in this project. | public synchronized Charset getProjectCharset() { return characterSet; }
| Get the project properties to be written to storage when the project is saved. | @OnThread(Tag.FXPlatform) public synchronized Properties getProjectPropertiesCopy() { Properties p = new Properties(); p.put(PROJECT_CHARSET_PROP, characterSet.name()); if (runOnThread != null) p.put(RUN_ON_THREAD_PROP, runOnThread.name()); return p; }
| Restore project properties (called just after project is opened). | private synchronized void loadProjectProperties(Properties props) { String charsetName = props.getProperty(PROJECT_CHARSET_PROP); if (charsetName != null) { try { characterSet = Charset.forName(charsetName); } catch (IllegalCharsetNameException icne) { Debug.message("Illegal project character set name: " + charsetName); } catch (UnsupportedCharsetException ucse) { Debug.message("Unsupported project character set: " + charsetName); } } if (characterSet == null) { characterSet = Charset.defaultCharset(); props.put(PROJECT_CHARSET_PROP, characterSet.name()); } String runOnThreadProp = props.getProperty(RUN_ON_THREAD_PROP); try { runOnThread = runOnThreadProp == null || runOnThreadProp.isEmpty() ? null : RunOnThread.valueOf(runOnThreadProp); } catch (IllegalArgumentException iae) { Debug.message("Invalid run-on-thread setting: " + runOnThreadProp); } }
| Update an inspector, make sure it's visible, and bring it to | the front. | | @param inspector The inspector to update and show | @OnThread(Tag.FXPlatform) private void updateInspector(final Inspector inspector) { inspector.update(); inspector.show(); inspector.bringToFront(); }
| Return an ObjectInspector for an object. | | @param obj | The object displayed by this viewer | @param name | The name of this object or "null" if the name is unobtainable |* @param pkg * The package all this belongs to (may be null) * @param ir * the InvokerRecord explaining how we got this result/object if * null, the "get" button is permanently disabled * @param parent * The parent frame of this frame * @param animateFromCentre If non-null, animate from the centre of this node. * @return The Viewer value */ | |@OnThread(Tag.FXPlatform) | |public ObjectInspector getInspectorInstance(DebuggerObject obj, | |String name, Package pkg, InvokerRecord ir, Window parent, Node animateFromCentre) | |{ | |ObjectInspector inspector = (ObjectInspector) inspectors.get(obj); | |if (inspector == null) { | |inspector = new ObjectInspector(obj, this, name, pkg, ir, parent); | |inspectors.put(obj, inspector); | |if (animateFromCentre != null) | |{ | |animateInspector(animateFromCentre, inspector, true); | |} | |inspector.show(); | |//org.scenicview.ScenicView.show(inspector.getScene()); | |} | |else { | |updateInspector(inspector); | |} | |// See if it is on the bench: | |// (Also check pkg != null since the data collection mechanism can't deal with null pkg). | |if (! Config.isGreenfoot() && pkg != null) { | |String benchName = null; | |PkgMgrFrame pmf = PkgMgrFrame.findFrame(pkg); | |if (pmf != null) | |{ | |for (ObjectWrapper ow : PkgMgrFrame.findFrame(pkg).getObjectBench().getObjects()) | |{ | |if (ow.getObject().equals(obj)) | |{ | |benchName = ow.getName(); | |} | |} | |} | |DataCollector.inspectorObjectShow(pkg, inspector, benchName, obj.getClassName(), name); | |} | |return inspector; | |} | |@OnThread(Tag.FXPlatform) | |private void animateInspector(Node animateFromCentre, Inspector inspector, boolean fromBottom) | |{ | |// First we must get the root and make sure it's sized for our later calculations: | |Parent root = inspector.getContent(); | |root.applyCss(); | |root.layout(); | |ScaleTransition t = null; | |// Odd JavaFX behaviour on Linux messes up animation, so don't animate on Linux: | |if (!Config.isLinux()) | |{ | |// Start it at zero size, animating to full size: | |root.setScaleX(0.0); | |root.setScaleY(0.0); | |t = new ScaleTransition(Duration.millis(600), root); | |t.setInterpolator(Interpolator.EASE_OUT); | |t.setToX(1.0); | |t.setToY(1.0); | |// To animate from left, need to start at position -0.5 of width, then animate to 0.0 | |root.translateXProperty().bind(inspector.getScene().widthProperty().multiply(root.scaleXProperty().multiply(0.5).add(-0.5))); | |if (fromBottom) | |{ | |// To animate from bottom, need to start at position 0.5 of height, then animate to 0.0 | |root.translateYProperty().bind(inspector.getScene().heightProperty().multiply(root.scaleYProperty().multiply(-0.5).add(0.5))); | |} | |else | |{ | |// To animate from top, need to start at position -0.5 of height, then animate to 0.0 | |root.translateYProperty().bind(inspector.getScene().heightProperty().multiply(root.scaleYProperty().multiply(0.5).add(-0.5))); | |} | |} | |// Position its bottom left at centre of animateFromCentre: | |Scene afcScene = animateFromCentre.getScene(); | |final Point2D windowCoord = new Point2D(afcScene.getWindow().getX(), afcScene.getWindow().getY()); | |final Point2D sceneCoord = new Point2D(afcScene.getX(), afcScene.getY()); | |final Point2D nodeCoord = animateFromCentre.localToScene(animateFromCentre.getBoundsInLocal().getWidth()/2.0, animateFromCentre.getBoundsInLocal().getHeight()/2.0); | |// Set position: | |inspector.setX(windowCoord.getX() + sceneCoord.getX() + nodeCoord.getX()); | |inspector.setY(windowCoord.getY() + sceneCoord.getY() + nodeCoord.getY() + (fromBottom ? -root.prefHeight(-1) : 0)); | |if (t != null) | |{ | |t.play(); | |} | |} | |/** | Get the inspector for the given object. Object can be a DebuggerObject, or a | fully-qualified class name. | | @param obj The object whose inspector to retrieve | @return the inspector, or null if no inspector is open | @OnThread(Tag.FXPlatform) public Inspector getInspector(Object obj) { return inspectors.get(obj); }
| Remove an inspector from the list of inspectors for this project | @param obj the inspector. | @OnThread(Tag.FXPlatform) public void removeInspector(DebuggerObject obj) { Inspector inspector = inspectors.remove(obj); DataCollector.inspectorHide(this, inspector); }
| Remove an inspector from the list of inspectors for this project | @param obj the inspector. | @OnThread(Tag.FXPlatform) public void removeInspector(DebuggerClass cls) { Inspector inspector = inspectors.remove(cls.getName()); DataCollector.inspectorHide(this, inspector); }
| Removes an inspector instance from the collection of inspectors | for this project. It firstly retrieves the inspector object and | then calls its doClose method. | @param obj | @OnThread(Tag.FXPlatform) public void removeInspectorInstance(Object obj) { Inspector inspect = getInspector(obj); if (inspect != null) { inspect.doClose(false); } }
| Removes all inspector instances for this project. | This is used when VM is reset or the project is recompiled. | @OnThread(Tag.FXPlatform) public void removeAllInspectors() { for (Inspector inspector : inspectors.values()) { inspector.hide(); DataCollector.inspectorHide(this, inspector); } inspectors.clear(); }
| Return a ClassInspector for a class. The inspector is visible. | | @param name | The name of this object or "null" if it is not on the object bench |* @param getEnabled * if false, the "get" button is permanently disabled * @param clss * The class displayed by this viewer * @param pkg * The package associated with the request (may be null) * @param parent * The parent frame of this frame | @param animateFromCentre | A node representing the initiator of the inspect action for animation purposes | (may be null). | @return The Viewer value | @OnThread(Tag.FXPlatform) public ClassInspector getClassInspectorInstance(DebuggerClass clss, Package pkg, Window parent, Node animateFromCentre) { ClassInspector inspector = (ClassInspector) inspectors.get(clss.getName()); if (inspector == null) { ClassInspectInvokerRecord ir = new ClassInspectInvokerRecord(clss.getName()); inspector = new ClassInspector(clss, this, pkg, ir, parent); inspectors.put(clss.getName(), inspector); if (animateFromCentre != null) animateInspector(animateFromCentre, inspector, false); inspector.show(); } else { updateInspector(inspector); } DataCollector.inspectorClassShow(this, pkg, inspector, clss.getName()); return inspector; }
| Return an ObjectInspector for an object. The inspector is visible. | | @param obj | The object displayed by this viewer | @param name | The name of this object or "null" if the name is unobtainable |* @param pkg * The package all this belongs to * @param ir * the InvokerRecord explaining how we got this result/object if * null, the "get" button is permanently disabled * @param info * The information about the the expression that gave this result * @param parent * The parent frame of this frame * @return The Viewer value @OnThread(Tag.FXPlatform) public ResultInspector getResultInspectorInstance(DebuggerObject obj, String name, Package pkg, InvokerRecord ir, ExpressionInformation info, javafx.stage.Window parent) { final ResultInspector inspector = new ResultInspector(obj, this, name, pkg, ir, info); inspectors.put(obj, inspector); inspector.initOwner(parent); inspector.centerOnOwner(); inspector.show(); inspector.bringToFront(); return inspector; }
| Iterates through all inspectors and updates them | @OnThread(Tag.FXPlatform) public void updateInspectors() { for (Iterator<Inspector> it = inspectors.values().iterator(); it.hasNext();) { Inspector inspector = it.next(); inspector.update(); } }
| Return the name of the project. | @OnThread(Tag.Any) public String getProjectName() { return projectDir.getName(); }
| Return the location of the project. | @OnThread(Tag.Any) public File getProjectDir() { return projectDir; }
| Return the source path for the project. The source path contains the JDK source, | if available, and the source for any other libraries which have been explicitly | added. | public List getSourcePath() { return sourcePath; }
| Get the project repository. If the user cancels the credentials dialog, | or this is not a team project, returns null. | public Repository getRepository() { boolean shared; synchronized (this) { shared = isSharedProject.orElse(false); } if (shared) { return getTeamSettingsController().trytoEstablishRepository(true); } else { return null; } }
| A string which uniquely identifies this project | @OnThread(Tag.Any) public String getUniqueId() { return String.valueOf(new String("BJID" + getProjectDir().getPath()).hashCode()); }
| Get the name of the package represented by the directory which was specified | as the directory to open when this project was opened. | public String getInitialPackageName() { return initialPackageName; }
| Get a reference to the "unnamed" package |*/ @OnThread(Tag.Any) public Package getUnnamedPackage() { return unnamedPackage; } /** * Get an existing package from the project. The package is opened (i.e a new | Package object is constructed) if it's not already open. All parent packages on | the way to the root of the package tree will also be constructed. | | @param qualifiedName package name i.e. java.util or "" for unnamed package |* @returns the package, or null if the package doesn't exist (directory * doesn't exist, or doesn't contain bluej.pkg file) */ public Package getPackage(String qualifiedName) | |{ | |Package existing = packages.get(qualifiedName); | |if (existing != null) { | |// The unnamed package is always already open, so that case is | |// handled here. | |return existing; | |} | |if (qualifiedName.length() > 0) { | |Package pkg; | |try { | |Package parent = getPackage(JavaNames.getPrefix(qualifiedName)); | |if (parent != null) { | |// Note, construction of the new package throws IOException if | |// the directory or bluej.pkg file doesn't exist | |pkg = new Package(this, JavaNames.getBase(qualifiedName), | |parent); | |packages.put(qualifiedName, pkg); | |pkg.refreshPackage(); | |} | |else { // parent package does not exist. How can it not exist ? | |pkg = null; | |} | |} catch (IOException exc) { | |// the package did not exist in this project | |pkg = null; | |} | |return pkg; | |} | |// Default package is not in the package cache. This should never happen... | |throw new IllegalStateException("Project.getPackage()"); } /** * Get all packages from the project. The returned collection is a live view * and should not be modified directly. * @return all the packages in the current project. */ public Collection<Package> getProjectPackages() | |{ | |return packages.values(); | |} | |/** | Return the extensions BProject associated with this Project. | There should be only one BProject object associated with each Project. | @return the BProject associated with this Project. | public synchronized final BProject getBProject() { if ( singleBProject == null ) singleBProject = ExtensionBridge.newBProject(this); return singleBProject; }
| Returns a package from the project. The package must have already been | opened. | | @param qualifiedName package name ie java.util or "" for unnamed package |* @return null if the named package cannot be found */ public Package getCachedPackage(String qualifiedName) { return packages.get(qualifiedName); } /** * This creates package directories. For the given package, all | intermediate package directories (which do not already exist) | will be created. A bluej.pkg file will be created for each | directory (if it does not already exist). | | @param fullName the fully qualified name of the package to create | directories for | public void createPackageDirectory(String fullName) { StringTokenizer st = new StringTokenizer(fullName, "."); File newPkgDir = getProjectDir(); while (st.hasMoreTokens()) {newPkgDir = new File(newPkgDir, st.nextToken()); } if (newPkgDir.isDirectory() || newPkgDir.mkdirs()) { st = new StringTokenizer(fullName, "."); newPkgDir = getProjectDir(); PackageFile pkgFile = PackageFileFactory.getPackageFile(newPkgDir); try { pkgFile.create(); } catch (IOException ioe) { ioe.printStackTrace(); } while (st.hasMoreTokens()){ newPkgDir = new File(newPkgDir, st.nextToken()); prepareCreateDir(newPkgDir); pkgFile = PackageFileFactory.getPackageFile(newPkgDir); try { pkgFile.create(); } catch (IOException ioe) { ioe.printStackTrace(); } } } }
| Returns a new package with the given fully qualified name. Once | NEW_PACKAGE_DONE is returned you can use getPackage to get the actual | package. | | @param qualifiedName | Ex. java.util or "" for unnamed package |* @return Project.NEW_PACKAGE_DONE, Project.NEW_PACKAGE_EXIST, * Project.NEW_PACKAGE_BAD_NAME */ public int newPackage(String qualifiedName) { if (qualifiedName == null) { | |return NEW_PACKAGE_BAD_NAME; | |} | |Package existing = packages.get(qualifiedName); | |if (existing != null) { | |return NEW_PACKAGE_EXIST; | |} | |// The zero len (unqualified) package should always exist. | |if (qualifiedName.length() < 1) { | |return NEW_PACKAGE_BAD_NAME; | |} | |// The above named package does not exist, lets create it. | |try { | |Package parent = getPackage(JavaNames.getPrefix(qualifiedName)); | |if (parent == null) { | |return NEW_PACKAGE_NO_PARENT; | |} | |// Before creating the package you have to create the directory | |// Maybe it should go into the new Package(...) | |createPackageDirectory(qualifiedName); | |Package pkg = new Package(this, JavaNames.getBase(qualifiedName), | |parent); | |packages.put(qualifiedName, pkg); | |pkg.refreshPackage(); | |} catch (IOException exc) { | |return NEW_PACKAGE_BAD_NAME; | |} | |return NEW_PACKAGE_DONE; | |} | |/** | Get the names of all packages in this project consisting of rootPackage | package and all packages nested below it. | | @param rootPackage | the root package to consider in looking for nested packages | @return a List of String containing the fully qualified names of the | packages. | private List getPackageNames(Package rootPackage) { List<String> l = new LinkedList<String>(); l.add(rootPackage.getQualifiedName()); rootPackage.getChildren(true).forEach(p -> l.addAll(getPackageNames(p))); return l; }
| Get the names of all packages in this project. | | @return a List of String containing the fully qualified names | of the packages in this project. | public List getPackageNames() { return getPackageNames(getPackage("")); }
| Generate documentation for the whole project. | @return "" if everything was alright, an error message otherwise. |*/ public String generateDocumentation() { return docuGenerator.generateProjectDocu(); } public String getDocumentationFile(String filename) | |{ | |return docuGenerator.getDocuPath(filename); | |} | |/** | Generate the documentation for the file in 'filename' | @param filename | public void generateDocumentation(String filename) { docuGenerator.generateClassDocu(filename); }
| Save all open packages of this project. This doesn't save files open | in editor windows - use saveAllEditors() for that. | public void saveAll() { PkgMgrFrame[] frames = PkgMgrFrame.getAllProjectFrames(this); if (frames == null) { return; } for (PkgMgrFrame frame : frames) { frame.doSave(); frame.setStatus(Config.getString("pkgmgr.packageSaved")); } }
| Request all open editor windows for the current project to save their | contents (if modified). | public void saveAllEditors() throws IOException { Iterator<Package> i = packages.values().iterator(); IOException exception = null; while (i.hasNext()) { Package pkg = i.next(); try { pkg.saveFilesInEditors(); } catch(IOException ioe) { exception = ioe; Debug.reportError("Error while trying to save editor file:", ioe); } } if (exception != null) { throw exception; } }
| Reload all constructed packages of this project. | | <p>This function is used after a major change to the contents | of the project directory ie an import. | public void reloadAll() { packages.values().forEach(Package::reload); }
| Make all open package editors clear their selection | public void clearAllSelections() { for (Package pkg : packages.values()) { PackageEditor ed = pkg.getEditor(); if (ed != null) { ed.clearSelection(); } } }
| Make the package editors for this project select the targets given in the | <code>targets</code> parameter. Pre-existing selections remain selected. Targets in a | package with no editor open will not be selected. | | @param targets a list of Targets | public void selectTargetsInGraphs(List<Target> targets) { for (Target target : targets) { PackageEditor packageEditor = target.getPackage().getEditor(); if (packageEditor != null) { packageEditor.addToSelection(target); packageEditor.repaint(); } } }
| Given a fully-qualified target name, return the target or null if the target | doesn't exist. | | <p>Use ReadmeTarget.README_ID ("@README") as the target base name to get the |* readme target for a package. */ public Target getTarget(String targetId) { String packageName = ""; int index = targetId.lastIndexOf('.'); if (index > 0) { packageName = targetId.substring(0, index); targetId = targetId.substring(index + 1); } Package p = getPackage(packageName); | |if (p == null) { | |return null; | |} | |Target target = p.getTarget(targetId); | |return target; | |} | |/** | Open the source editor for each target that is selected in its | package editor | public void openEditorsForSelectedTargets() { List<Target> selectedTargets = getSelectedTargets(); for (Iterator<Target> i = selectedTargets.iterator(); i.hasNext(); ){ Target target = i.next(); if (target instanceof ClassTarget){ ClassTarget classTarget = (ClassTarget) target; Editor editor = classTarget.getEditor(); if (editor != null) { editor.setEditorVisible(true, false); } } } }
| Get a list of selected targets (in all packages) | @return a list of the selected targets | private List getSelectedTargets() { List<Target> selectedTargets = new LinkedList<Target>(); List<String> packageNames = getPackageNames(); for (String packageName : packageNames) { Package p = getPackage(packageName); selectedTargets.addAll(p.getSelectedTargets()); } return selectedTargets; }
| Explicitly restart the remote debug VM. The VM first gets shut down, and then | restarted. | public void restartVM() { getDebugger().close(true); vmClosed(); PkgMgrFrame.displayMessage(this, Config.getString("pkgmgr.creatingVM")); }
| The remote VM for this project has just been initialised and is ready now. | private void vmReady() { packages.values().forEach(Package::reInitBreakpoints); if (Config.isMacOS()) { PkgMgrFrame frame = PkgMgrFrame.findFrame(getUnnamedPackage()); if (frame != null) { frame.bringToFront(); } } BlueJEvent.raiseEvent(BlueJEvent.CREATE_VM_DONE, null); }
| The remote VM for this project has just been closed. Remove everything in this | project that depended on that VM. | private void vmClosed() { removeClassLoader(); newRemoteClassLoader(); libraryUrls = getLibrariesClasspath(); debugger.setUserLibraries(libraryUrls.toArray(new URL[libraryUrls.size()])); }
| Removes the current classloader, and removes | references to classes loaded by it (this includes removing | the objects from all object benches of this project). | public void removeClassLoader() { if (currentClassLoader == null) { return; } clearObjectBenches(); removeAllInspectors(); View.removeAll(currentClassLoader); if (! Config.isGreenfoot()) { new Thread() { @OnThread(Tag.Worker) public void run() { getDebugger().disposeWindows(); } }.start(); } currentClassLoader = null; }
| Clears the objects from all object benches belonging to this project. | public void clearObjectBenches() { PkgMgrFrame[] frames = PkgMgrFrame.getAllProjectFrames(this); if (frames != null) { for (PkgMgrFrame frame : frames) { ObjectBench bench = frame.getObjectBench(); bench.removeAllObjects(getUniqueId()); frame.clearTextEval(); } } }
| Creates a new debugging VM classloader. | Breakpoints are discarded. | public void newRemoteClassLoader() { getDebugger().newClassLoader(getClassLoader()); }
| Creates a new debugging VM classloader, leaving current breakpoints. | public void newRemoteClassLoaderLeavingBreakpoints() { getDebugger().newClassLoader(getClassLoader()); packages.values().forEach(Package::reInitBreakpoints); } @OnThread(Tag.Any) public Debugger getDebugger() { return debugger; } public boolean hasExecControls() { return execControls != null; } public ExecControls getExecControls() { if (execControls == null) { execControls = new ExecControls(this, getDebugger(), Config.isGreenfoot() ? null : threadListContents); debuggerShowing.bindBidirectional(execControls.showingProperty()); } return execControls; } public boolean hasTerminal() { return terminal != null; } public Terminal getTerminal() { if (terminal == null) { terminal = new Terminal(this); terminalShowing.bindBidirectional(terminal.showingProperty()); } return terminal; }
| Loads a class using the current classLoader | public Class loadClass(String className) { try { return getClassLoader().loadClass(className); } catch (ClassNotFoundException e) { return null; } catch (SecurityException se) { return null; } catch (LinkageError le) { return null; } } @OnThread(value = Tag.Any, ignoreParent = true) public synchronized boolean inTestMode() { return inTestMode; } public synchronized void setTestMode(boolean mode) { inTestMode = mode; }
| Returns a list of URL having in it all libraries that are in the +libs directory | of this project. | @return a non null but possibly empty list of URL. | @OnThread(Tag.Any) protected List getPlusLibsContent() { List<URL> risul = new ArrayList<URL>(); File libsDirectory = new File(projectDir, projectLibDirName); if ( ! libsDirectory.isDirectory() || ! libsDirectory.canRead() ) return risul; File []libs = libsDirectory.listFiles(); if ( libs==null || libs.length < 1 ) return risul; for (int index=0; index<libs.length; index++) { attemptAddLibrary(risul, libs[index]); } return risul; }
| Return a ClassLoader that should be used to load or reflect on the project classes. | The same BClassLoader object is returned until the Project is compiled or the content of the | user class list is changed, this is needed to load "compatible" classes in the same classloader space. |* * @return a BClassLoader that provides class loading services for this Project. */ public BPClassLoader getClassLoader() { if (currentClassLoader != null) | |return currentClassLoader; | |List<URL> pathList = new ArrayList<URL>(); | |try { | |Collections.addAll(pathList, Boot.getInstance().getRuntimeUserClassPath()); | |pathList.addAll(libraryUrls); | |// The current project dir must be added to the project class path too. | |pathList.add(getProjectDir().toURI().toURL()); | |} | |catch ( Exception exc ) { | |// Should never happen | |Debug.reportError("Project.getClassLoader() exception: " + exc.getMessage()); exc.printStackTrace(); } URL [] newUrls = pathList.toArray(new URL[pathList.size()]); // The Project Class Loader should not see the BlueJ classes (the necessary | |// ones have been added to the URL list anyway). So we use the boot loader | |// as parent. | |currentClassLoader = new BPClassLoader( newUrls, | |Boot.getInstance().getBootClassLoader()); | |return currentClassLoader; | |} | |/** | Get the classpath for libraries - those specified in preferences, in the project's +libs, | in the BlueJ userlib folder, etc. This doesn't include the BlueJ runtime. | | <p>Most of the time, the list in {}code libraryUrls} should be used instead of calling this | method, as it represents the libraries known to the currently executing VM. | private List getLibrariesClasspath() { List<URL> pathList = new ArrayList<URL>(); pathList.addAll(ClassMgrPrefPanel.getUserConfigContent()); pathList.addAll(getUserlibContent()); pathList.addAll(getPlusLibsContent()); return pathList; }
| Get an entity resolver which can be used to resolve symbols for this project. | | @return an entity resolver which resolves symbols from classes in this project, | and from the classpath. | public EntityResolver getEntityResolver() { return new ProjectEntityResolver(this); }
| Get a javadoc resolver, which can be used to retrieve comments for methods. | @OnThread(Tag.Any) public JavadocResolver getJavadocResolver() { return javadocResolver; }
| Convert a filename into a fully qualified Java name. | Returns null if the file is outside the project | directory. | | The behaviour of this function is not guaranteed if | you pass in a directory name. It is meant for filenames | like /foo/bar/p1/s1/TestName.java | public String convertPathToPackageName(String pathname) { return JavaNames.convertFileToQualifiedName(getProjectDir(), new File(pathname)); } public void removeStepMarks() { packages.values().forEach(Package::removeStepMarks); } | A debugger event was fired. Analyse which event it was, and take | appropriate action. | @OnThread(Tag.Any) public void processDebuggerEvent(final DebuggerEvent event, boolean skipUpdate) { if (skipUpdate) { return; } Platform.runLater(new Runnable() { public void run() { if (event.getID() == DebuggerEvent.DEBUGGER_STATECHANGED) { int newState = event.getNewState(); int oldState = event.getOldState(); if (newState == Debugger.RUNNING) { getTerminal().activate(true); } else if (newState == Debugger.IDLE) { getTerminal().activate(false); } PkgMgrFrame[] frames = PkgMgrFrame.getAllProjectFrames(Project.this); if (frames != null) { for (int i = 0; i < frames.length; i++) { frames[i].setDebuggerState(newState); } } if ((oldState == Debugger.NOTREADY) && (newState == Debugger.IDLE)) { vmReady(); } if ((oldState == Debugger.IDLE) && (newState == Debugger.NOTREADY)) { removeStepMarks(); vmClosed(); } if (newState == Debugger.LAUNCH_FAILED) { BlueJEvent.raiseEvent(BlueJEvent.CREATE_VM_FAILED, null); } return; } DebuggerThread thr = event.getThread(); if (thr == null) { return; } String packageName = JavaNames.getPrefix(thr.getClass(0)); Package pkg = getPackage(packageName); if (pkg != null) { switch (event.getID()) { case DebuggerEvent.THREAD_BREAKPOINT: pkg.hitBreakpoint(thr); break; case DebuggerEvent.THREAD_HALT_UNKNOWN: case DebuggerEvent.THREAD_HALT_STEP_INTO: case DebuggerEvent.THREAD_HALT_STEP_OVER: pkg.hitHalt(thr); break; } } switch (event.getID()) { case DebuggerEvent.THREAD_HALT_UNKNOWN: DataCollector.debuggerHalt(Project.this, thr.getName(), ExecControls.getFilteredStack(thr.getStack())); break; case DebuggerEvent.THREAD_HALT_STEP_INTO: DataCollector.debuggerStepInto(Project.this, thr.getName(), ExecControls.getFilteredStack(thr.getStack())); break; case DebuggerEvent.THREAD_HALT_STEP_OVER: DataCollector.debuggerStepOver(Project.this, thr.getName(), ExecControls.getFilteredStack(thr.getStack())); break; case DebuggerEvent.THREAD_BREAKPOINT: DataCollector.debuggerHitBreakpoint(Project.this, thr.getName(), ExecControls.getFilteredStack(thr.getStack())); break; } } }); }
| Show the source code at a particular position | public void showSource(DebuggerThread thread, String className, String sourceName, int lineNumber) { String packageName = JavaNames.getPrefix(className); Package pkg = getPackage(packageName); if (pkg != null) { pkg.showSourcePosition(thread, sourceName, lineNumber); } } | String representation for debugging. | public String toString() { return "Project:" + getProjectName(); }
| Removes a package (and any sub-packages) from the map of open | packages in the project. | | @param packageQualifiedName The qualified name of the package. | public void removePackage(String packageQualifiedName) { Package pkg = packages.get(packageQualifiedName); if (pkg != null) { pkg.getChildren(false).forEach(childPkg -> removePackage(childPkg.getQualifiedName())); packages.remove(packageQualifiedName); } } | Return the teamwork action group. | public TeamActionGroup getTeamActions() { return teamActions; }
| Determine if project is a team project. | The method will look for the existence of the team configuration file | team.defs | @return true if the project is a team project | @OnThread(Tag.Any) public boolean isTeamProject() { Optional<Boolean> shared; synchronized (this) { shared = this.isSharedProject; } if (!shared.isPresent()){ File ccfFile = new File(projectDir.getAbsoluteFile(), "team.defs"); if (ccfFile.isFile()){ return TeamSettingsController.isValidVCSfound(projectDir); } else { return false; } } return shared.get(); }
| Get an array of Files that resides in the project folders. | @param includePkgFiles true if package layout files should be included | @param includeDirs true if directories should be included | @return List of File objects | public Set getFilesInProject(boolean includePkgFiles, boolean includeDirs) { Set<File> files = new LinkedHashSet<File>(); if (includeDirs) { files.add(projectDir); } traverseDirsForFiles(files, projectDir, includePkgFiles, includeDirs); return files; }
| Get the teams settings controller for this project. Returns null | if this is not a shared project. | public TeamSettingsController getTeamSettingsController() { boolean shared; synchronized (this) { shared = isSharedProject.orElse(false); } if (teamSettingsController == null && shared) { teamSettingsController = new TeamSettingsController(this); } return teamSettingsController; }
| Set the team settings controller for this project. This makes the | project a shared project (unless the controller is null). | public void setTeamSettingsController(TeamSettingsController tsc) { teamSettingsController = tsc; if (tsc != null) { tsc.setProject(this); tsc.writeToProject(); } setProjectShared (tsc != null); }
| Traverse the directory tree starting in dir an add all the encountered | files to the List allFiles. The parameter includePkgFiles determine | whether bluej.pkg files should be added to allFiles as well. | @param allFiles a List to which the method will add the files it meets. | @param dir the directory the search starts from | @param includePkgFiles if true, bluej.pkg files are included as well. | private void traverseDirsForFiles(Set<File> allFiles, File dir, boolean includePkgFiles, boolean includeDirs) { TeamSettingsController teamSettingsController = getTeamSettingsController(); File[] files = dir.listFiles(teamSettingsController == null ? null : teamSettingsController.getFileFilter(includePkgFiles, true)); if (files == null) { return; } for (int i=0; i< files.length; i++ ){ if (files[i].isFile()) { allFiles.add(files[i]); } else { if (includeDirs) { allFiles.add(files[i]); } traverseDirsForFiles(allFiles, files[i], includePkgFiles, includeDirs); } } }
| Get the team settings dialog for this project. Only call this if the | project is a shared project. | public TeamSettingsDialog getTeamSettingsDialog() { return getTeamSettingsController().getTeamSettingsDialog(); }
| Get the commit dialog for this project | public CommitAndPushInterface getCommitCommentsDialog() { if (commitCommentsFrame == null) { if (this.teamSettingsController.isDVCS()) { commitCommentsFrame = new CommitAndPushFrame(this); } else { commitCommentsFrame = new CommitCommentsFrame(this); } } return commitCommentsFrame; }
| Get the update dialog for this project | public UpdateFilesFrame getUpdateDialog() { if (updateFilesFrame == null) { updateFilesFrame = new UpdateFilesFrame(this); } return updateFilesFrame; }
| Set this project as either shared or non-shared. | private void setProjectShared(boolean shared) { synchronized (this) { isSharedProject = Optional.of(shared); } if (shared){ TeamSettingsController tsc = new TeamSettingsController(this); isDVCS = tsc.isDVCS(); } teamActions.setTeamMode(shared, isDVCS); PkgMgrFrame[] frames = PkgMgrFrame.getAllProjectFrames(this); if (frames != null) { for (int i = 0; i < frames.length; i++) { frames[i].updateSharedStatus(shared); } } }
| Find the package name of the package containing the given file. | Might return null if the file isn't in the package, or the directory the | file is in doesn't translate to a valid package name. However, may | return a valid package name which doesn't actually exist as a package | in the project. | public String getPackageForFile(File f) { File projdir = getProjectDir(); String packageName = ""; File parentDir = f.getParentFile(); while (! parentDir.equals(projdir)){ String parentName = parentDir.getName(); if (!JavaNames.isIdentifier(parentName)) { return null; } if (packageName.equals("")) { packageName = parentName; } else { packageName = parentName + "." + packageName; } parentDir = parentDir.getParentFile(); if (parentDir == null) { return null; } } return packageName; }
| Get the team status window associated with this project. | public StatusFrame getStatusWindow() { if (statusFrame == null) { statusFrame = new StatusFrame(this); } return statusFrame; }
| Prepare for the deletion of a directory inside the project. This is | a notification which allows the team management code to save the | version control metadata elsewhere, if necessary. | public boolean prepareDeleteDir(File dir) { TeamSettingsController tsc = getTeamSettingsController(); if (tsc != null) { return tsc.prepareDeleteDir(dir); } else { return true; } }
| Prepare for the creation of a directory inside the project. This is a | notification which allows the team management code to perform any | necessary metadata actions. | public void prepareCreateDir(File dir) { TeamSettingsController tsc = getTeamSettingsController(); if (tsc != null) { tsc.prepareCreateDir(dir); } }
| Gets the FXTabbedEditor which should be used for adding new tabs | @OnThread(Tag.FX) public FXTabbedEditor getDefaultFXTabbedEditor() { return fXTabbedEditors.get(0); } public boolean isClosing() { return closing; } public void setClosing(boolean closing) { this.closing = closing; } @OnThread(Tag.Any) public void scheduleCompilation(boolean immediate, CompileReason reason, CompileType type, Package pkg) { Platform.runLater(() -> scheduleCompilation(immediate, reason, type, pkg, null)); } @OnThread(Tag.Any) public void scheduleCompilation(boolean immediate, CompileReason reason, CompileType type, ClassTarget target) { Platform.runLater(() -> scheduleCompilation(immediate, reason, type, null, target)); }
| Schedules a compilation within the project, of the given package (if not null) and/or the given target (if not null) | @param immediate Whether to compile right now, or whether to compile after 1 seconds (this timer will be extended by | every later call of scheduleCompilation to 1s again) | @param reason Why we are compiling (used for Blackbox data collection) | @param type The type of compilation (used for deciding whether to keep class files, whether to open editors to show errors) | @param pkg The package in which to compile all targets (or null if don't want full-package compilation) | @param target The target to compile (or null if you don't want specific target compiled) | | Note: only one of pkg or target should be non-null. | @OnThread(Tag.FXPlatform) private void scheduleCompilation(boolean immediate, CompileReason reason, CompileType type, Package pkg, ClassTarget target) { if (immediate) { if (compilerTimer != null) { if (pkg != null) scheduledPkgs.remove(pkg); if (target != null) scheduledTargets.remove(target); if (scheduledPkgs.isEmpty() && scheduledTargets.isEmpty()) { compilerTimer.stop(); } } if (pkg != null) pkg.compileOnceIdle(null, reason, type); else if (target != null) target.getPackage().compileOnceIdle(target, reason, type); } else { if (pkg != null) scheduledPkgs.add(pkg); if (target != null) scheduledTargets.add(target); latestCompileReason = reason; latestCompileType = type; if (compilerTimer != null) { compilerTimer.stop(); compilerTimer.playFromStart(); } else { EventHandler<ActionEvent> listener = e -> { Set<Package> pkgsToCompile; Set<ClassTarget> targetsToCompile; pkgsToCompile = scheduledPkgs; scheduledPkgs = new HashSet<>(); targetsToCompile = scheduledTargets; scheduledTargets = new HashSet<>(); for (Package p : pkgsToCompile) { p.compileOnceIdle(null, latestCompileReason, latestCompileType); } for (ClassTarget t : targetsToCompile) { t.getPackage().compileOnceIdle(t, latestCompileReason, latestCompileType); } }; compilerTimer = new Timeline(new KeyFrame(Duration.millis(1000), listener)); compilerTimer.setCycleCount(1); compilerTimer.playFromStart(); } } } @OnThread(Tag.Any) public synchronized ImportScanner getImportScanner() { if (importScanner == null) importScanner = new ImportScanner(this); return importScanner; } @OnThread(Tag.FXPlatform) public FXTabbedEditor createNewFXTabbedEditor() { FXTabbedEditor ed = new FXTabbedEditor(Project.this, recallFxPosition(fXTabbedEditors.size())); ed.initialise(); fXTabbedEditors.add(ed); fXTabbedEditors.forEach(FXTabbedEditor::updateMoveMenus); return ed; } @OnThread(Tag.FX) public List getAllFXTabbedEditorWindows() { return Collections.unmodifiableList(fXTabbedEditors); } @OnThread(Tag.FX) public void removeFXTabbedEditor(FXTabbedEditor fxTabbedEditor) { while (fxCachedEditorSizes.size() < fXTabbedEditors.size()) fxCachedEditorSizes.add(0, null); } fxCachedEditorSizes.set(fXTabbedEditors.size() - 1, new Rectangle(fxTabbedEditor.getX(), fxTabbedEditor.getY(), fxTabbedEditor.getWidth(), fxTabbedEditor.getHeight())); if (fXTabbedEditors.stream().anyMatch(ed -> ed != fxTabbedEditor && !ed.hasTutorial())) { fxTabbedEditor.cleanup(); fXTabbedEditors.remove(fxTabbedEditor); } fXTabbedEditors.forEach(FXTabbedEditor::updateMoveMenus); } @OnThread(Tag.FXPlatform) public void saveEditorLocations(Properties props) { for (int i = 0; i < fXTabbedEditors.size(); i++) { saveEditorLocation(props, fXTabbedEditors.get(i), "editor.fx." + i); } for (int i = fXTabbedEditors.size(); i < fxCachedEditorSizes.size(); i++) { saveEditorLocation(props, fxCachedEditorSizes.get(i), "editor.fx." + i); } } @OnThread(Tag.FXPlatform) private void saveEditorLocation(Properties props, FXTabbedEditor editor, String prefix) { props.put(prefix + ".x", String.valueOf(editor.getX())); props.put(prefix + ".y", String.valueOf(editor.getY())); props.put(prefix + ".width", String.valueOf(editor.getWidth())); props.put(prefix + ".height", String.valueOf(editor.getHeight())); } @OnThread(Tag.FXPlatform) private void saveEditorLocation(Properties props, Rectangle rect, String prefix) { if (rect == null) return; props.put(prefix + ".x", String.valueOf((int)rect.getX())); props.put(prefix + ".y", String.valueOf((int)rect.getY())); props.put(prefix + ".width", String.valueOf((int)rect.getWidth())); props.put(prefix + ".height", String.valueOf((int)rect.getHeight())); } public void setAllEditorStatus(String status) { fXTabbedEditors.forEach(fte -> fte.setTitleStatus(status)); } @OnThread(Tag.FX) private Rectangle recallPosition(String prefix, List<Rectangle> cache, int index) { if (index < cache.size() && cache.get(index) != null) { return cache.get(index); } Properties props = unnamedPackage.getLastSavedProperties(); prefix = prefix + "." + index; int x = Integer.parseInt(props.getProperty(prefix + ".x", "-1")); int y = Integer.parseInt(props.getProperty(prefix + ".y", "-1")); int width = Integer.parseInt(props.getProperty(prefix + ".width", "-1")); int height = Integer.parseInt(props.getProperty(prefix + ".height", "-1")); if (x >= 0 && y >= 0 && width > 100 && height > 100) { return new Rectangle(x, y, width, height); } else { return null; } } @OnThread(Tag.FX) private Rectangle recallFxPosition(int index) { return recallPosition("editor.fx", fxCachedEditorSizes, index); } @OnThread(Tag.FX) public FrameShelfStorage getShelfStorage() { return shelfStorage; } public BooleanProperty terminalShowing() { return terminalShowing; } public BooleanProperty debuggerShowing() { return debuggerShowing; } @Override @OnThread(Tag.Any) public void threadStateChanged(DebuggerThread thread, boolean shouldDisplay) { Platform.runLater(() -> { for (int i = 0; i < threadListContents.size(); i++) { if (threadListContents.get(i).isThread(thread)) { threadListContents.get(i).update(); break; } } if (hasExecControls()) { getExecControls().updateThreadDetails(thread); if (shouldDisplay) { getExecControls().selectThread(thread); } } }); } @Override @OnThread(Tag.Any) public void clearThreads() { Platform.runLater(() -> { threadListContents.clear(); }); } @Override @OnThread(Tag.Any) public void addThread(DebuggerThread thread) { DebuggerThreadDetails details = new DebuggerThreadDetails(thread); Platform.runLater(() -> { threadListContents.add(details); }); } @Override @OnThread(Tag.Any) public void removeThread(DebuggerThread thread) { DebuggerThreadDetails details = new DebuggerThreadDetails(thread); Platform.runLater(() -> { threadListContents.remove(details); }); }
| Gets the setting for this project as to which thread constructor/method invocations will run on. | public RunOnThread getRunOnThread() { return runOnThread; }
| Sets the setting for this project as to which thread constructor/method invocations will run on. | This is communicated to the currently running debug VM, and will also be remembered if the debug | VM is restarted (and will be saved to the project properties on exit, for next load). | public void setRunOnThread(RunOnThread runOnThread) { this.runOnThread = runOnThread; debugger.setRunOnThread(runOnThread == null ? RunOnThread.DEFAULT : runOnThread); }
| We fetch the display details on the debugger thread, | not from the FX thread, and this object allows us to capture some | of the thread details at one point in time and keep | the snapshot: namely the suspended state and the | display string. This prevents us seeing "future" updates |* which have happened in the debugger but not yet made * their way to the GUI. */ public static class DebuggerThreadDetails { private final DebuggerThread debuggerThread; | |private String debuggerThreadDisplay; | |private boolean suspended; | |@OnThread(Tag.Any) | |public DebuggerThreadDetails(DebuggerThread dt) | |{ | |this.debuggerThread = dt; | |update(); | |} | |/** | Update details based on the current state of the thread. | @OnThread(Tag.Any) public void update() { this.debuggerThreadDisplay = debuggerThread.toString(); this.suspended = debuggerThread.isSuspended(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; DebuggerThreadDetails that = (DebuggerThreadDetails) o; return debuggerThread.equals(that.debuggerThread); } @Override public int hashCode() { return debuggerThread.hashCode(); } @Override public String toString() { return debuggerThreadDisplay; } public boolean isThread(DebuggerThread dt) { return debuggerThread.equals(dt); }
| Gets whether the thread was suspended when this DebuggerThreadDetails | object was created. Should be used in preference to getThread().isSuspended() | because it is set once and will not change, whereas getThread().isSuspended() | is live and may return in effect a "future" value (i.e. one which has | * occurred in the debugger but not yet reached the GUI, and is queued * to be processed after this event). */ public boolean isSuspended() { | |
return suspended; | |
} | | public DebuggerThread getThread() | | { | | return debuggerThread; | | } | | } | | }
top, use, map, class Project

.   Project
.   isProject
.   openProject
.   cleanUp
.   createNewProject
.   getOpenProjectCount
.   getProjects
.   getProject
.   pathIntoStartingDirectory
.   attemptAddLibrary
.   getUserlibContent
.   getProjectCharset
.   getProjectPropertiesCopy
.   loadProjectProperties
.   updateInspector
.   getInspector
.   removeInspector
.   removeInspector
.   removeInspectorInstance
.   removeAllInspectors
.   getClassInspectorInstance
.   getResultInspectorInstance
.   updateInspectors
.   getProjectName
.   getProjectDir
.   getSourcePath
.   getRepository
.   getUniqueId
.   getInitialPackageName
.   getBProject
.   createPackageDirectory
.   getPackageNames
.   getPackageNames
.   generateDocumentation
.   saveAll
.   saveAllEditors
.   reloadAll
.   clearAllSelections
.   selectTargetsInGraphs
.   openEditorsForSelectedTargets
.   getSelectedTargets
.   restartVM
.   vmReady
.   vmClosed
.   removeClassLoader
.   run
.   clearObjectBenches
.   newRemoteClassLoader
.   newRemoteClassLoaderLeavingBreakpoints
.   getDebugger
.   hasExecControls
.   getExecControls
.   hasTerminal
.   getTerminal
.   loadClass
.   inTestMode
.   setTestMode
.   getPlusLibsContent
.   getLibrariesClasspath
.   getEntityResolver
.   getJavadocResolver
.   convertPathToPackageName
.   removeStepMarks
.   processDebuggerEvent
.   run
.   showSource
.   toString
.   removePackage
.   getTeamActions
.   isTeamProject
.   getFilesInProject
.   getTeamSettingsController
.   setTeamSettingsController
.   traverseDirsForFiles
.   getTeamSettingsDialog
.   getCommitCommentsDialog
.   getUpdateDialog
.   setProjectShared
.   getPackageForFile
.   getStatusWindow
.   prepareDeleteDir
.   prepareCreateDir
.   getDefaultFXTabbedEditor
.   isClosing
.   setClosing
.   scheduleCompilation
.   scheduleCompilation
.   scheduleCompilation
.   getImportScanner
.   createNewFXTabbedEditor
.   getAllFXTabbedEditorWindows
.   removeFXTabbedEditor
.   saveEditorLocations
.   saveEditorLocation
.   saveEditorLocation
.   setAllEditorStatus
.   recallPosition
.   recallFxPosition
.   getShelfStorage
.   terminalShowing
.   debuggerShowing
.   threadStateChanged
.   clearThreads
.   addThread
.   removeThread
.   getRunOnThread
.   setRunOnThread
.   update
.   equals
.   hashCode
.   toString
.   isThread




2443 neLoCode + 477 LoComm