public void install(@Nonnull CodeArea area, @Nonnull TabCompleter<T> completer) {
		setArea(area);

		completionPopupFocuser = new CompletionPopupFocuser(this);
		completionPopupUpdater = new CompletionPopupUpdater<>(completer, this);

		area.addEventFilter(KeyEvent.KEY_RELEASED, completionPopupUpdater);
		area.addEventFilter(KeyEvent.KEY_TYPED, completionPopupFocuser);

		// Clicking off of the popup should hide it.
		// - Clicking on the area is not covered by auto-hide.
		//   - But clicking on other components is covered.
		// - Clicking on the area delays the event until after the caret bounds update
		//   which makes the popup jump around when clicking off the popup.
		//   - Which we can bypass by hooking the events of the area's parent node.
		area.getParent().addEventFilter(MouseEvent.MOUSE_PRESSED, e -> hide());

		// When we scroll the caret bounds change.
		area.caretBoundsProperty().addListener((observable, oldValue, newValue) -> {
			if (isShowing() && updateCaretBoundsIndirect())
				show();
		});
	}
Installs this popup into the given editor using the given tab-completer.
<br>
Intended to be called from the {@link TabCompleter#install(Editor)} implementation.

@param area
		Editor code area component to register events within.
@param completer
		Tab completer this popup will be associated with.
recaf-ui/src/main/java/software/coley/recaf/ui/control/richtext/suggest/CompletionPopup.java