diff --git a/sb/src/main/java/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java b/sb/src/main/java/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java
index 82b07ecd06b11bc027498dff8081a2ef63eafe87..e6745e8de14819f8dd1a3dc3eb0f0bc3483f25d2 100644
--- a/sb/src/main/java/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java
+++ b/sb/src/main/java/com/oracle/javafx/scenebuilder/app/info/InfoPanelController.java
@@ -215,6 +215,10 @@ public class InfoPanelController extends AbstractFxmlPanelController {
                 updateControllerAndControllerClassEditor(controllerClassEditor.getTextField().getText());
             }
         });
+        
+        getEditorController().getGlossary().revisionProperty().addListener((ov, t, t1) -> {
+        	resetSuggestedControllerClasses(getEditorController().getFxmlLocation());
+        });
 
         leftTableColumn.setCellValueFactory(new PropertyValueFactory<>("key")); //NOI18N
         rightTableColumn.setCellValueFactory(new PropertyValueFactory<>("fxomObject")); //NOI18N
@@ -468,7 +472,7 @@ public class InfoPanelController extends AbstractFxmlPanelController {
     
     private final ChangeListener<Boolean> checkBoxListener = (ov, t, t1) -> toggleFxRoot();
 
-    public void resetSuggestedControllerClasses(URL location) {
+    private void resetSuggestedControllerClasses(URL location) {
         if (controllerClassEditor != null) {
             // The listener on fxmlLocationProperty is called before the file
             // denoted by the location is created on disk, hence the runLater.
diff --git a/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java b/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java
index 12fd88bee258916fb90d71426c88f5b33bb18bd9..589009af4f204fd760b54b07e78b020d393e5a84 100644
--- a/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java
+++ b/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/inspector/InspectorPanelController.java
@@ -223,6 +223,10 @@ public class InspectorPanelController extends AbstractFxmlPanelController {
 
     // Charsets for the properties of included elements
     private Map<String, Charset> availableCharsets;
+    
+    private ChangeListener<Number> glossaryRevisionListener = (ov, t, t1) -> {
+    	updateInspector();
+    };
 
     /*
      * Public
@@ -519,6 +523,8 @@ public class InspectorPanelController extends AbstractFxmlPanelController {
         // Listen the Scene stylesheets changes
         getEditorController().sceneStyleSheetProperty().addListener((ChangeListener<ObservableList<File>>) (ov, t, t1) -> updateInspector());
         
+        getEditorController().getGlossary().revisionProperty().addListener(glossaryRevisionListener);
+        
         selectionState = new SelectionState(editorController);
         viewModeChanged(null, getViewMode());
         expandedSectionChanged();
@@ -533,6 +539,12 @@ public class InspectorPanelController extends AbstractFxmlPanelController {
         searchResultDividerPosition = inspectorRoot.getDividerPositions()[0];
         searchPatternDidChange();
     }
+    
+    @Override
+    protected void editorControllerChanged(EditorController oldController, EditorController newController) {
+		oldController.getGlossary().revisionProperty().removeListener(glossaryRevisionListener);
+    	newController.getGlossary().revisionProperty().addListener(glossaryRevisionListener);
+    }
 
     /*
      * Private
diff --git a/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/util/AbstractPanelController.java b/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/util/AbstractPanelController.java
index 1d97ce9a7a283910ddbdf11a29f7d337f2e41f40..3d06d4c3f2fa0fa0767e51362f65354ae37b46ca 100644
--- a/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/util/AbstractPanelController.java
+++ b/sb/src/main/java/com/oracle/javafx/scenebuilder/kit/editor/panel/util/AbstractPanelController.java
@@ -120,9 +120,14 @@ public abstract class AbstractPanelController {
     	
     	if (old != null) {
     		editorSelectionDidChange();
+        	editorControllerChanged(old, editorController);
     	}
     }
     
+    protected void editorControllerChanged(EditorController oldController, EditorController newController) {
+    	
+    }
+    
     /**
      * Returns the root FX object of this panel.
      * When called the first time, this method invokes {@link #makePanel()}
diff --git a/sb4e.test/src/no/tobask/sb4e/test/JavaProjectGlossaryTest.java b/sb4e.test/src/no/tobask/sb4e/test/JavaProjectGlossaryTest.java
index 485f7609ccf45c1af48a47d3f5a463c37793c24b..8fd0046660542549a5385e3e26706db28d8b0604 100644
--- a/sb4e.test/src/no/tobask/sb4e/test/JavaProjectGlossaryTest.java
+++ b/sb4e.test/src/no/tobask/sb4e/test/JavaProjectGlossaryTest.java
@@ -3,6 +3,7 @@ package no.tobask.sb4e.test;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.JavaCore;
@@ -25,20 +26,14 @@ public class JavaProjectGlossaryTest {
 	JavaProjectGlossary glossary;
 	URL fxmlLocation;
 	IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("testProject");
-	InfoPanelController infoPanelController;
 	
 	@Rule
 	public final ExternalResource projectResource = new JavaProjectResource(project);
 		
-	@Before
-	public void setUp() throws Exception {
-		infoPanelController = mock(InfoPanelController.class);
-	}
-	
 	@Test
 	public void discoversCandidates() throws Exception {
 		fxmlLocation = project.getFolder("src").getFile("Test.fxml").getLocationURI().toURL();
-		glossary = new JavaProjectGlossary("", fxmlLocation, infoPanelController);
+		glossary = new JavaProjectGlossary("", fxmlLocation);
 		List<String> controllerSuggestions = glossary.queryControllerClasses(fxmlLocation);
 		assertEquals(1, controllerSuggestions.size());
 	}
@@ -46,10 +41,11 @@ public class JavaProjectGlossaryTest {
 	@Test
 	public void reactsToRemoval() throws Exception {
 		fxmlLocation = project.getFolder("src").getFile("Test.fxml").getLocationURI().toURL();
-		glossary = new JavaProjectGlossary("", fxmlLocation, infoPanelController);
+		glossary = new JavaProjectGlossary("", fxmlLocation);
+		JavaCore.addElementChangedListener(glossary, ElementChangedEvent.POST_CHANGE);
 		assertEquals(1, glossary.queryControllerClasses(fxmlLocation).size());
 		getController().delete(true, null);
-		verify(infoPanelController).resetSuggestedControllerClasses(fxmlLocation);
+		assertEquals(1, glossary.getRevision());;
 		assertEquals(0, glossary.queryControllerClasses(fxmlLocation).size());
 	}
 
diff --git a/sb4e/src/no/tobask/sb4e/ControllerCandidateChecker.java b/sb4e/src/no/tobask/sb4e/ControllerCandidateChecker.java
deleted file mode 100644
index 52892aa99e40787a434bb90ec7622113962f552c..0000000000000000000000000000000000000000
--- a/sb4e/src/no/tobask/sb4e/ControllerCandidateChecker.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package no.tobask.sb4e;
-
-import java.util.List;
-
-import org.eclipse.jdt.core.dom.ASTVisitor;
-import org.eclipse.jdt.core.dom.Annotation;
-import org.eclipse.jdt.core.dom.BodyDeclaration;
-import org.eclipse.jdt.core.dom.FieldDeclaration;
-import org.eclipse.jdt.core.dom.IExtendedModifier;
-import org.eclipse.jdt.core.dom.MethodDeclaration;
-
-import javafx.fxml.FXML;
-
-public class ControllerCandidateChecker extends ASTVisitor {
-
-	private static final String FXML_ANNOTATION = FXML.class.getSimpleName();
-	private boolean hasEmptyConstructor;
-	private boolean hasFxmlAnnotatedMembers;
-	
-	private boolean hasConstructor;
-		
-	@Override
-	public boolean visit(FieldDeclaration node) {
-		return visitBodyDeclaration(node);
-	}
-	
-	@Override
-	public boolean visit(MethodDeclaration node) {
-		if (node.isConstructor()) {
-			hasConstructor = true;
-			hasEmptyConstructor = hasEmptyConstructor || node.parameters().size() == 0;
-		}
-		return visitBodyDeclaration(node);
-	}
-	
-	@SuppressWarnings("unchecked")
-	private boolean visitBodyDeclaration(BodyDeclaration node) {
-		List<IExtendedModifier> modifiers = node.modifiers();
-		for (IExtendedModifier modifier : modifiers) {
-			if (modifier.isAnnotation()) {
-				String annotationName = ((Annotation) modifier).getTypeName().toString();
-				if (annotationName != null && annotationName.equals(FXML_ANNOTATION)) {
-					hasFxmlAnnotatedMembers = true;
-				}
-			}
-		}
-		return false;
-	}
-	
-	public boolean visitedCandidate() {
-		return (hasEmptyConstructor || !hasConstructor) && hasFxmlAnnotatedMembers;
-	}
-	
-}
diff --git a/sb4e/src/no/tobask/sb4e/FxControllerValidator.java b/sb4e/src/no/tobask/sb4e/FxControllerValidator.java
index ad81556e3d3aa98f392c8c52ebf2864c15e5668f..e5438781131f590b9a809da22069312b05bf2251 100644
--- a/sb4e/src/no/tobask/sb4e/FxControllerValidator.java
+++ b/sb4e/src/no/tobask/sb4e/FxControllerValidator.java
@@ -50,8 +50,7 @@ public class FxControllerValidator extends CompilationParticipant {
 					String fxmlContent = FXOMDocument.readContentFromURL(documentLocation);
 					FXOMDocument document = new FXOMDocument(fxmlContent, documentLocation,
 							Activator.getClassLoader(), I18N.getBundle());
-					CompilationUnit ast = getAst(clazz);
-					file.recordNewProblems(getProblems(ast, document));
+					file.recordNewProblems(getProblems(clazz, document));
 				} catch (IOException e) {
 					e.printStackTrace();
 				}
@@ -71,19 +70,28 @@ public class FxControllerValidator extends CompilationParticipant {
 		return true;
 	}
 	
-	private CategorizedProblem[] getProblems(CompilationUnit ast, FXOMDocument document) {
-		FxControllerVisitor visitor = new FxControllerVisitor();
+	private String getDocumentName(URL url) {
+		String path = url.getFile();
+		int start = path.lastIndexOf("/") + 1;
+		int end = path.lastIndexOf(".");
+		return path.substring(start, end);
+	}
+	
+	private CategorizedProblem[] getProblems(ICompilationUnit clazz, FXOMDocument document) {
+		CompilationUnit ast = getAst(clazz);
+		String documentName = getDocumentName(document.getLocation());
+		FxControllerVisitor visitor = new FxControllerVisitor(documentName, clazz.getElementName());
 		ast.accept(visitor);
-		Map<String, String> controllerIds = visitor.getFxIds();
+		Map<String, List<String>> controllerIds = visitor.getFxIds();
 		Map<String, FXOMObject> documentIds = document.collectFxIds();
 		List<String> missingIds = new ArrayList<>();
-		for (Entry<String, FXOMObject> id : documentIds.entrySet()) {
-			if (!controllerIds.containsKey(id.getKey())) {
-				FXOMObject fxomObject = id.getValue();
-				if (fxomObject instanceof FXOMInstance) {
-					FXOMInstance instance = (FXOMInstance) fxomObject;
-					missingIds.add(id.getKey() + ";" + instance.getDeclaredClass().getName());
-				}
+		for (Entry<String, FXOMObject> docId : documentIds.entrySet()) {
+			FXOMInstance instance = (FXOMInstance) docId.getValue();
+			String componentType = instance.getDeclaredClass().getSimpleName();
+			String id = docId.getKey();
+			List<String> idsForInstanceType = controllerIds.get(componentType);
+			if (idsForInstanceType == null || !idsForInstanceType.contains(id)) {
+				missingIds.add(id + ";" + instance.getDeclaredClass().getName());
 			}
 		}
 
diff --git a/sb4e/src/no/tobask/sb4e/FxControllerVisitor.java b/sb4e/src/no/tobask/sb4e/FxControllerVisitor.java
index 468295d23cdda04f96aab38b3367d06d1daad7ae..86c5578843ba6813a6a64aece9e5036babf6e0dd 100644
--- a/sb4e/src/no/tobask/sb4e/FxControllerVisitor.java
+++ b/sb4e/src/no/tobask/sb4e/FxControllerVisitor.java
@@ -1,66 +1,144 @@
 package no.tobask.sb4e;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import org.eclipse.jdt.core.dom.ASTVisitor;
 import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
 import org.eclipse.jdt.core.dom.FieldDeclaration;
 import org.eclipse.jdt.core.dom.IExtendedModifier;
 import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
 import org.eclipse.jdt.core.dom.Modifier;
 import org.eclipse.jdt.core.dom.SimpleType;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
 import org.eclipse.jdt.core.dom.Type;
 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 
+import javafx.beans.value.ObservableValue;
+import javafx.event.Event;
 import javafx.fxml.FXML;
 
 public class FxControllerVisitor extends ASTVisitor {
 	
-	private Map<String, String> fxIds = new HashMap<>(); // var name -> type
 	private static final String FXML_ANNOTATION = FXML.class.getSimpleName();
+	private List<String> eventHandlers = new ArrayList<>();
+	private Map<String, List<String>> fxIds = new HashMap<>();
+	
+	private boolean hasEmptyConstructor;
+	private boolean hasConstructor;
+	private String documentName;
+	private String className;
 	
+	public FxControllerVisitor(String documentName, String className) {
+		this.documentName = documentName;
+		this.className = className;
+	}
+
 	@Override
-	public boolean visit(FieldDeclaration node) {
-		if (isFxIdCandidate(node)) {
-			Type type = node.getType();
-			ITypeBinding typeBinding = type.resolveBinding();
-			String typeName;
-			if (typeBinding != null) {
-				typeName = typeBinding.getQualifiedName();
-			} else {
-				if (type.isSimpleType()) {
-					typeName = ((SimpleType) type).getName().getFullyQualifiedName();
-				} else {
-					typeName = "UNKNOWN";
-				}
-			}
-			List<VariableDeclarationFragment> fragments = node.fragments();
-			String variableName = fragments.get(0).getName().toString();
-			fxIds.put(variableName, typeName);
+	public boolean visit(MethodDeclaration node) {
+		if (node.isConstructor()) {
+			hasConstructor = true;
+			hasEmptyConstructor = hasEmptyConstructor || node.parameters().size() == 0;
+		}
+		
+		if ((isPublic(node) || hasFxmlAnnotation(node)) && isValidEventHandler(node)) {
+			String name = node.getName().getFullyQualifiedName();
+			eventHandlers.add(name);
 		}
-		return super.visit(node);
+		return false;
 	}
 	
+	@SuppressWarnings("unchecked")
+	private boolean isValidEventHandler(MethodDeclaration node) {
+		List<SingleVariableDeclaration> parameters = node.parameters();
+		if (parameters.size() == 0) {
+			return true;
+		} else if (parameters.size() == 1) {
+			SingleVariableDeclaration param = parameters.get(0);
+			return isSubClassOf(Event.class.getName(), param.getType());
+		} else if (parameters.size() == 3) {
+			SingleVariableDeclaration firstParam = parameters.get(0);
+			return isSubClassOf(ObservableValue.class.getName(), firstParam.getType());
+		}
+		return false;
+	}
 	
-	public Map<String, String> getFxIds() {
-		return fxIds;
+	private boolean isPublic(BodyDeclaration node) {
+		return Modifier.isPublic(node.getModifiers());
 	}
 
-	private boolean isFxIdCandidate(FieldDeclaration field)	{
-		List<IExtendedModifier> modifiers = field.modifiers();
-		if (Modifier.isPublic(field.getModifiers())) {
-			return true;
+	@Override
+	public boolean visit(FieldDeclaration node) {
+		if ((isPublic(node) || hasFxmlAnnotation(node)) && isSubClassOf("javafx", node.getType())) {
+			addToIds(node);
 		}
-		boolean hasFxmlAnnotation = false;
+		return true;
+	}
+	
+	@SuppressWarnings("unchecked")
+	private void addToIds(FieldDeclaration node) {
+		Type type = node.getType();
+		if (type.isSimpleType()) {
+			String typeName = ((SimpleType) type).getName().getFullyQualifiedName();
+			List<VariableDeclarationFragment> fragments = node.fragments();
+			String varName = fragments.get(0).getName().getFullyQualifiedName();
+			List<String> prevIds = fxIds.putIfAbsent(typeName,
+					new ArrayList<>(Arrays.asList(varName)));
+			if (prevIds != null) {
+				prevIds.add(varName);
+			}
+ 		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	private boolean hasFxmlAnnotation(BodyDeclaration node) {
+		List<IExtendedModifier> modifiers = node.modifiers();
 		for (IExtendedModifier modifier : modifiers) {
 			if (modifier.isAnnotation()) {
-				String annotationName = ((Annotation) modifier).getTypeName().toString();
-				hasFxmlAnnotation = hasFxmlAnnotation || annotationName.equals(FXML_ANNOTATION);
+				String annotationName = ((Annotation) modifier).getTypeName().getFullyQualifiedName();
+				if (annotationName != null && annotationName.equals(FXML_ANNOTATION)) {
+					return true;
+				}
 			}
 		}
-		return hasFxmlAnnotation;
+		return false;
+	}
+	
+	private boolean isSubClassOf(String superClass, Type classType) {
+		if (classType.isPrimitiveType()) {
+			return false;
+		}
+		ITypeBinding binding = classType.resolveBinding();
+		if (binding != null) {
+			ITypeBinding objectType = classType.getAST().resolveWellKnownType("java.lang.Object");
+			ITypeBinding type = binding;
+			while (type.getSuperclass() != objectType) {
+				type = type.getSuperclass();
+				if (type.getQualifiedName().startsWith(superClass)) {
+					return true;
+				}
+			}
+		}
+		return false;
 	}
 
+	public List<String> getEventHandlers() {
+		return new ArrayList<>(eventHandlers);
+	}
+	
+	public Map<String, List<String>> getFxIds() {
+		return new HashMap<>(fxIds);
+	}
+	
+	public boolean isCandidate() {
+		boolean hasFxMembers = eventHandlers.size() > 0 || fxIds.size() > 0;
+		boolean contentMatch = (hasEmptyConstructor || !hasConstructor) && hasFxMembers;
+		boolean nameMatch = className.startsWith(documentName);
+		return contentMatch || nameMatch;
+	}
+	
 }
diff --git a/sb4e/src/no/tobask/sb4e/JavaProjectGlossary.java b/sb4e/src/no/tobask/sb4e/JavaProjectGlossary.java
index de54d8fc8a3f5d3a5b03a036067c003d2a7bba2b..fa8864210e4d6c3880138eae32dde926aa94f71f 100644
--- a/sb4e/src/no/tobask/sb4e/JavaProjectGlossary.java
+++ b/sb4e/src/no/tobask/sb4e/JavaProjectGlossary.java
@@ -2,7 +2,6 @@ package no.tobask.sb4e;
 
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -10,45 +9,29 @@ import java.util.stream.Collectors;
 import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IElementChangedListener;
-import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaElementDelta;
 import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.ILocalVariable;
-import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import com.oracle.javafx.scenebuilder.app.info.InfoPanelController;
 import com.oracle.javafx.scenebuilder.kit.glossary.Glossary;
 
-import javafx.beans.value.ObservableValue;
-import javafx.event.Event;
-import javafx.fxml.FXML;
-
 public class JavaProjectGlossary extends Glossary implements IElementChangedListener {
-
-	private static final String FXML_ANNOTATION = FXML.class.getSimpleName();
 	
 	private String qualifiedControllerName;
 	private URL fxmlLocation;
-	private InfoPanelController infoPanelController;
 
-	private Map<String, Map<String, List<String>>> fxIds = new HashMap<>();
-	private Map<String, List<String>> eventHandlers = new HashMap<>();
+	private Map<String, List<String>> fxIds;
+	private List<String> eventHandlers;
 	private List<ICompilationUnit> candidateControllers;
 
-	public JavaProjectGlossary(String controllerClassName, URL fxmlLocation,
-			InfoPanelController infoPanelController) {
+	public JavaProjectGlossary(String controllerClassName, URL fxmlLocation) {
 		this.qualifiedControllerName = controllerClassName;
 		this.fxmlLocation = fxmlLocation;
-		this.infoPanelController = infoPanelController;
-		JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE);
 	}
 
 	@Override
@@ -69,85 +52,91 @@ public class JavaProjectGlossary extends Glossary implements IElementChangedList
 
 	@Override
 	public List<String> queryFxIds(URL fxmlLocation, String controllerClass, Class<?> targetType) {
-		if (qualifiedControllerName == null || !qualifiedControllerName.equals(controllerClass)) {
-			qualifiedControllerName = controllerClass;
+		String previousController = qualifiedControllerName;
+		qualifiedControllerName = controllerClass;
+		if (qualifiedControllerName == null) {
+			return new ArrayList<>();
 		}
-		Map<String, List<String>> controllerFxIds = fxIds.get(qualifiedControllerName);
-		if (controllerFxIds == null) {
+		if (!previousController.equals(qualifiedControllerName) || fxIds == null) {
 			ICompilationUnit controller = JavaModelUtils.getClass(fxmlLocation, qualifiedControllerName);
-			controllerFxIds = controller == null ?
-					new HashMap<>() : getFxIds(controller);
-			fxIds.put(qualifiedControllerName, controllerFxIds);
+			fxIds = controller == null ? new HashMap<>() : getFxIds(controller);
 		}
 		String typeName = Signature.getSimpleName(targetType.getName());
-		List<String> ids = controllerFxIds.getOrDefault(typeName, new ArrayList<>());
+		List<String> ids = fxIds.getOrDefault(typeName, new ArrayList<>());
 		return new ArrayList<>(ids);
 	}
 
 	@Override
 	public List<String> queryEventHandlers(URL fxmlLocation, String controllerClass) {
-		if (qualifiedControllerName == null || !qualifiedControllerName.equals(controllerClass)) {
-			qualifiedControllerName = controllerClass;
+		String previousController = qualifiedControllerName;
+		qualifiedControllerName = controllerClass;
+		if (qualifiedControllerName == null) {
+			return new ArrayList<>();
 		}
-		List<String> controllerEventHandlers = eventHandlers.get(qualifiedControllerName);
-		if (controllerEventHandlers == null) {
+		if (!previousController.equals(qualifiedControllerName) || eventHandlers == null) {
 			ICompilationUnit controller = JavaModelUtils.getClass(fxmlLocation, qualifiedControllerName);
-			controllerEventHandlers = controller == null ?
+			eventHandlers = controller == null ?
 					new ArrayList<>() : getEventHandlers(controller);
-			eventHandlers.put(qualifiedControllerName, controllerEventHandlers);
 		}
-		return new ArrayList<>(controllerEventHandlers);
+		return new ArrayList<>(eventHandlers);
 	}
 
 	@Override
 	public void elementChanged(ElementChangedEvent event) {
 		IJavaElementDelta delta = getClassChangedDelta(event.getDelta());
+		boolean revised = false;
 		if (delta != null) {
 			ICompilationUnit affectedClass = (ICompilationUnit) delta.getElement();
 			if (fxmlLocation != null && inSameProject(affectedClass)) {
-				if (updateControllerCandidates(delta)) {
-					infoPanelController.resetSuggestedControllerClasses(fxmlLocation);
+				List<ICompilationUnit> prevCandidates = new ArrayList<>(candidateControllers);
+				updateControllerCandidates(delta);
+				if (!prevCandidates.equals(candidateControllers)) {
+					revised = true;
 				}
 				
 				if (delta.getKind() != IJavaElementDelta.REMOVED && qualifiedControllerName != null
 						&& JavaModelUtils.getQualifiedName(affectedClass).equals(qualifiedControllerName)) {
-					fxIds.put(qualifiedControllerName, getFxIds(affectedClass));
-					eventHandlers.put(qualifiedControllerName, getEventHandlers(affectedClass));
+					Map<String, List<String>> prevFxIds = fxIds;
+					fxIds = getFxIds(affectedClass);
+					List<String> prevEventHandlers = eventHandlers;
+					eventHandlers = getEventHandlers(affectedClass);
+					if (!fxIds.equals(prevFxIds) || !eventHandlers.equals(prevEventHandlers)) {
+						revised = true;
+					}
 				}
 			}
 		}
+		if (revised) {
+			incrementRevision();
+		}
 	}
 		
-	private boolean updateControllerCandidates(IJavaElementDelta delta) {
-		boolean updated = false;
+	private void updateControllerCandidates(IJavaElementDelta delta) {
 		ICompilationUnit compUnit = (ICompilationUnit) delta.getElement();
 		if (delta.getKind() == IJavaElementDelta.REMOVED) {
 			if (candidateControllers.contains(compUnit)) {
 				candidateControllers.remove(compUnit);
-				updated = true;
 			}
 		} else {
 			CompilationUnit ast = delta.getCompilationUnitAST();
 			CompilationUnit clazz = ast != null ? ast : getAst(compUnit);
-			ControllerCandidateChecker checker = new ControllerCandidateChecker();
+			FxControllerVisitor checker = new FxControllerVisitor(getDocumentName(fxmlLocation),
+					compUnit.getElementName());
 			clazz.accept(checker);
-			boolean isCandidateController = checker.visitedCandidate();
-			if (candidateControllers.contains(compUnit)) {
-				if (!isCandidateController) {
-					candidateControllers.remove(compUnit);
-					updated = true;
-				}
-			} else if (isCandidateController) {
+			boolean isCandidateController = checker.isCandidate();
+
+			if (isCandidateController && !candidateControllers.contains(compUnit)) {
 				candidateControllers.add(compUnit);
-				updated = true;
+			} else if (!isCandidateController && candidateControllers.contains(compUnit)) {
+				candidateControllers.remove(compUnit);
 			}
 		}
-		return updated;
 	}
 			
 	private CompilationUnit getAst(ICompilationUnit source) {
 		ASTParser parser = ASTParser.newParser(AST.JLS9);
 		parser.setSource(source);
+		parser.setResolveBindings(true);
 		return (CompilationUnit) parser.createAST(null);
 	}
 
@@ -168,7 +157,7 @@ public class JavaProjectGlossary extends Glossary implements IElementChangedList
 		
 	private List<ICompilationUnit> getCandidateControllers(IPackageFragment pkg) {
 		ASTParser parser = ASTParser.newParser(AST.JLS9);
-		Requestor requestor = new Requestor();
+		Requestor requestor = new Requestor(getDocumentName(fxmlLocation));
 		try {
 			parser.createASTs(pkg.getCompilationUnits(), null, requestor, null);
 			return requestor.getCandidates();
@@ -177,77 +166,28 @@ public class JavaProjectGlossary extends Glossary implements IElementChangedList
 			return new ArrayList<>();
 		}
 	}
+	
+	private String getDocumentName(URL url) {
+		String path = url.getFile();
+		int start = path.lastIndexOf("/") + 1;
+		int end = path.lastIndexOf(".");
+		return path.substring(start, end);
+	}
 			
 	private List<String> getEventHandlers(ICompilationUnit controller) {
-		List<String> eventHandlers = new ArrayList<>();
-		IType type = controller.findPrimaryType();
-		try {
-			for (IMethod method : type.getMethods()) {
-				if (isEventHandler(method)) {
-					eventHandlers.add(method.getElementName());
-				}
-			}
-		} catch (JavaModelException e) {
-			e.printStackTrace();
-		}
-		return eventHandlers;
-	}
-
-	private boolean isEventHandler(IMethod method) throws JavaModelException {
-		boolean isFxmlAnnotated = method.getAnnotation(FXML_ANNOTATION).exists();
-		boolean returnsVoid = method.getReturnType().equals(Signature.SIG_VOID);
-		if (isFxmlAnnotated && returnsVoid) {
-			// valid ones are:
-			// 1) zero parameters
-			// 2) one parameter of javafx.event type
-			// 3) three parameters, where the first one is of ObservableValue type
-			ILocalVariable[] parameters = method.getParameters();
-			if (parameters.length == 0) {
-				return true;
-			} else if (parameters.length == 1) {
-				return isSubclass(parameters[0], Event.class);
-			} else if (parameters.length == 3) {
-				return isSubclass(parameters[0], ObservableValue.class);
-			}
-		}
-		return false;
-	}
-	
-	private boolean isSubclass(ILocalVariable parameter, Class<?> clazz) throws JavaModelException {
-		String simpleName = Signature.getSignatureSimpleName(parameter.getTypeSignature());
-		IType declaringType = parameter.getDeclaringMember().getDeclaringType();
-		String[][] resolvedNames = declaringType.resolveType(simpleName);
-		if (resolvedNames != null && resolvedNames.length > 0) {
-			String superClassName = resolvedNames[0][0];
-			return superClassName.equals(Signature.getQualifier(clazz.getName()));
-		} else {
-			return false;
-		}
+		CompilationUnit compUnit = getAst(controller);
+		FxControllerVisitor checker = new FxControllerVisitor(getDocumentName(fxmlLocation),
+				controller.getElementName());
+		compUnit.accept(checker);
+		return checker.getEventHandlers();
 	}
 
 	private Map<String, List<String>> getFxIds(ICompilationUnit controller) {
-		Map<String, List<String>> ids = new HashMap<>();
-		IType type = controller.findPrimaryType();
-		try {
-			for (IField field : type.getFields()) {
-				if (field.getAnnotation(FXML_ANNOTATION).exists()) {
-					addToIds(ids, field);
-				}
-			}
-		} catch (JavaModelException e) {
-			e.printStackTrace();
-		}
-		return ids;
-	}
-
-	private void addToIds(Map<String, List<String>> ids, IField field) throws JavaModelException {
-		String typeName = Signature.getSignatureSimpleName(field.getTypeSignature());
-		String fieldName = field.getElementName();
-		List<String> existingIds = ids.putIfAbsent(typeName,
-				new ArrayList<>(Arrays.asList(fieldName)));
-		if (existingIds != null) {
-			existingIds.add(fieldName);
-		}
+		CompilationUnit compUnit = getAst(controller);
+		FxControllerVisitor checker = new FxControllerVisitor(getDocumentName(fxmlLocation),
+				controller.getElementName());
+		compUnit.accept(checker);
+		return checker.getFxIds();
 	}
 
 }
diff --git a/sb4e/src/no/tobask/sb4e/Requestor.java b/sb4e/src/no/tobask/sb4e/Requestor.java
index 6d3db506eaa2c74521911d113ccbe13e99f46192..44e2e5f384aa7106f31cfadc1b3670db5bef52d3 100644
--- a/sb4e/src/no/tobask/sb4e/Requestor.java
+++ b/sb4e/src/no/tobask/sb4e/Requestor.java
@@ -10,12 +10,17 @@ import org.eclipse.jdt.core.dom.CompilationUnit;
 public class Requestor extends ASTRequestor {
 	
 	private List<ICompilationUnit> candidates = new ArrayList<>();
+	private String documentName;
+	
+	public Requestor(String documentName) {
+		this.documentName = documentName;
+	}
 	
 	@Override
 	public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
-		ControllerCandidateChecker checker = new ControllerCandidateChecker();
-		ast.accept(checker);
-		if (checker.visitedCandidate()) {
+		FxControllerVisitor visitor = new FxControllerVisitor(documentName, source.getElementName());
+		ast.accept(visitor);
+		if (visitor.isCandidate()) {
 			candidates.add(source);
 		}
 	}
diff --git a/sb4e/src/no/tobask/sb4e/editors/FXMLEditor.java b/sb4e/src/no/tobask/sb4e/editors/FXMLEditor.java
index d8a499391170b57be525ba04bdbb3267a3207b03..5ee21dcce3895d6f033c5eadff71f414ec8c070c 100644
--- a/sb4e/src/no/tobask/sb4e/editors/FXMLEditor.java
+++ b/sb4e/src/no/tobask/sb4e/editors/FXMLEditor.java
@@ -15,6 +15,7 @@ import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.ISourceRange;
@@ -147,9 +148,9 @@ public class FXMLEditor extends EditorPart {
 			if (root != null) {
 				controllerName = root.getFxController();
 			}
-			glossary = new JavaProjectGlossary(controllerName, fxmlUrl,
-					editorWindowController.infoPanelController);
+			glossary = new JavaProjectGlossary(controllerName, fxmlUrl);
 			editorController.setGlossary(glossary);
+			JavaCore.addElementChangedListener(glossary, ElementChangedEvent.POST_CHANGE);
 			
 			copyHandler = new SceneBuilderControlActionHandler(editorController, ControlAction.COPY);
 			cutHandler = new SceneBuilderEditActionHandler(editorController, EditAction.CUT);