public ComponentValidator installOn(@NotNull JComponent component) {
    Component fc = getFocusable(component).orElse(outlineProvider.apply(component));
    component.putClientProperty(PROPERTY_NAME, this);

    FocusListener focusListener = new ValidationFocusListener();
    MouseListener mouseListener = new ValidationMouseListener();

    ComponentListener componentListener = new ComponentAdapter() {
      @Override public void componentMoved(ComponentEvent e) {
        if (popup != null && popup.isVisible() && popupLocation != null) {
          popup.setLocation(popupLocation.getScreenPoint());
        }
      }
    };

    PropertyChangeListener ancestorListener = e -> {
      Window w = (Window)ComponentUtil.findParentByCondition((Component)e.getSource(), v -> v instanceof Window);
      if (w != null) {
        if (e.getNewValue() != null) {
          w.addComponentListener(componentListener);
        } else {
          w.removeComponentListener(componentListener);
        }
      }
    };

    Window w = (Window)ComponentUtil.findParentByCondition(component, v -> v instanceof Window);
    if (w != null) {
      w.addComponentListener(componentListener);
    } else {
      component.addPropertyChangeListener("ancestor", ancestorListener);
    }

    fc.addFocusListener(focusListener);
    fc.addMouseListener(mouseListener);
    Disposer.register(parentDisposable, () -> {
      fc.removeFocusListener(focusListener);
      fc.removeMouseListener(mouseListener);

      if (w != null) {
        w.removeComponentListener(componentListener);
      }

      reset();
    });
    return this;
  }
public ComponentValidator installOn(@NotNull JComponent component)