X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=plugins%2Fnet.mograsim.plugin.core%2Fsrc%2Fnet%2Fmograsim%2Fplugin%2Fnature%2FProjectMachineContext.java;h=ecce9e818f68226e1340e0f0bddd7bf02b8d8ed7;hb=d8d92dba4339e1240e4362046eadbe51c6740780;hp=0e6185c410045ad5d5fcf0a8c385700de556f02d;hpb=f919efc362c3de5c94d894dc8fc7fe22c03fc865;p=Mograsim.git
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java
index 0e6185c4..ecce9e81 100644
--- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java
+++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java
@@ -2,24 +2,56 @@ package net.mograsim.plugin.nature;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
+import net.mograsim.machine.MachineRegistry;
+import net.mograsim.plugin.nature.ProjectContextEvent.ProjectContextEventType;
+
+/**
+ * This class is a register for {@link MachineContext} mapped by their {@link IProject}
+ *
+ * It can be used to obtain (and thereby create if necessary) {@link MachineContext}s for projects and {@link IAdaptable}s that are somewhat
+ * associated to Mograsim nature. The register is unique and static context of this class. Since it also depends on the installed machines,
+ * it listens to changes of the {@link MachineRegistry}.
+ *
+ * @author Christian Femers
+ *
+ */
public class ProjectMachineContext
{
private static Map projectMachineContexts = Collections.synchronizedMap(new HashMap<>());
+ private static final Set listeners = Collections.synchronizedSet(new HashSet<>());
public static final String MOGRASIM_PROJECT_PREFS_NODE = "net.mograsim";
public static final String MACHINE_PROPERTY = "net.mograsim.projectMachineId";
+ private ProjectMachineContext()
+ {
+
+ }
+
+ /**
+ * This method returns the associated machine context or created a new one if none is associated yet.
+ *
+ * @param project the project to get the {@link MachineContext} for (or create one, if possible). It must have Mograsim nature.
+ *
+ * @throws IllegalArgumentException if the project is not accessible or has no mograsim nature
+ * @throws NullPointerException if the project is null
+ *
+ */
public static MachineContext getMachineContextOf(IProject project)
{
MachineContext mc = projectMachineContexts.get(project);
@@ -28,9 +60,21 @@ public class ProjectMachineContext
validateMograsimNatureProject(project);
mc = new MachineContext(project);
projectMachineContexts.put(project, mc);
+ notifyListeners(new ProjectContextEvent(mc, ProjectContextEventType.NEW));
return mc;
}
+ /**
+ * This method returns the associated machine context or created a new one if none is associated yet. The given resource must be
+ * adaptable to {@link IProject}.
+ *
+ * @param mograsimProjectAdapable the {@link IProject}-{@link IAdaptable} to get the {@link MachineContext} for (or create one, if
+ * possible). Must be contained in a Mograsim nature project.
+ *
+ * @throws IllegalArgumentException if the project is not accessible or has no mograsim nature
+ * @throws NullPointerException if the {@link IAdaptable} is null or it cannot be adapted to {@link IProject}
+ *
+ */
public static MachineContext getMachineContextOf(IAdaptable mograsimProjectAdapable)
{
IProject project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
@@ -38,6 +82,14 @@ public class ProjectMachineContext
return getMachineContextOf(project);
}
+ /**
+ * Returns all {@link MachineContext} known, in the sense of all that got ever created during this runtime.
+ */
+ public static Map getAllProjectMachineContexts()
+ {
+ return Collections.unmodifiableMap(projectMachineContexts);
+ }
+
static ScopedPreferenceStore getProjectPrefs(IProject mograsimProject)
{
return new ScopedPreferenceStore(new ProjectScope(mograsimProject), MOGRASIM_PROJECT_PREFS_NODE);
@@ -49,6 +101,7 @@ public class ProjectMachineContext
if (mograsimProjectAdapable instanceof IProject)
{
project = (IProject) mograsimProjectAdapable;
+ Objects.requireNonNull(project, "Project was null");
} else
{
project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
@@ -67,6 +120,9 @@ public class ProjectMachineContext
return project;
}
+ /**
+ * Tests for Mograsim nature. This method is null safe and will not throw any exception.
+ */
static boolean hasMograsimNature(IProject project)
{
if (project == null)
@@ -88,4 +144,48 @@ public class ProjectMachineContext
return Optional.of(preferenceStore.getString(MACHINE_PROPERTY));
return Optional.empty();
}
+
+ static void notifyListeners(ProjectContextEvent projectContextEvent)
+ {
+ listeners.forEach(l -> l.onProjectContextChange(projectContextEvent));
+ }
+
+ public static void addProjectContextListener(ProjectContextListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ public static void removeProjectContextListener(ProjectContextListener listener)
+ {
+ listeners.remove(listener);
+ }
+
+ static
+ {
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(ProjectMachineContext::resourceChanged);
+ MachineRegistry.addMachineRegistryListener(newMap -> updateAllStatus());
+ }
+
+ private static void updateAllStatus()
+ {
+ projectMachineContexts.forEach((p, mc) -> mc.updateStatus());
+ }
+
+ private static void resourceChanged(IResourceChangeEvent event)
+ {
+ // We try to do as many cheap tests first as possible, because this listener is not limited to plain project actions.
+ if (event.getResource() == null)
+ return;
+ IProject project = event.getResource().getProject();
+ if (project == null)
+ return;
+ MachineContext mc = projectMachineContexts.get(project);
+ if (mc == null)
+ return;
+ ProjectContextEventType eventType = ProjectContextEventType.ofResourceChangeEvent(event.getType());
+// if (eventType == ProjectContextEventType.OTHER_CHANGE && project.isOpen())
+// return; // we don't care about all small changes (TODO: research if this has any drawbacks)
+ eventType.getForcedStatus().ifPresent(mc::forceUpdateStatus);
+ notifyListeners(new ProjectContextEvent(mc, eventType));
+ }
}