private boolean isHandleSelectionEnabled(@NotNull KeyType selected, boolean processIfUnfocused) {
   return myEnabled
       && myComponent.isEnabled()
       && myComponent.isShowing()
       && myComponent.getVisibleRect().intersects(getVisibleRect(selected))
       && (processIfUnfocused || myComponent.isFocusOwner())
       && !isPopup();
 }
  private void doHandleSelectionChange(@NotNull KeyType selected, boolean processIfUnfocused) {
    if (!myEnabled
        || !myComponent.isEnabled()
        || !myComponent.isShowing()
        || !myComponent.getVisibleRect().intersects(getVisibleRect(selected))
        || !myComponent.isFocusOwner() && !processIfUnfocused
        || isPopup()) {
      hideHint();
      return;
    }

    myKey = selected;

    Point location = createToolTipImage(myKey);

    if (location == null) {
      hideHint();
    } else {
      Rectangle bounds = new Rectangle(location, myTipComponent.getPreferredSize());
      myPopup.setBounds(bounds);
      myPopup.setVisible(noIntersections(bounds));
      repaintKeyItem();
    }
  }
  protected AbstractExpandableItemsHandler(@NotNull final ComponentType component) {
    myComponent = component;
    myComponent.add(myRendererPane);
    myComponent.validate();
    myPopup = new MovablePopup(myComponent, myTipComponent);

    myTipComponent.addMouseWheelListener(
        new MouseWheelListener() {
          @Override
          public void mouseWheelMoved(MouseWheelEvent e) {
            dispatchEvent(myComponent, e);
          }
        });

    myTipComponent.addMouseListener(
        new MouseListener() {
          @Override
          public void mouseClicked(MouseEvent e) {
            dispatchEvent(myComponent, e);
          }

          @Override
          public void mousePressed(MouseEvent e) {
            dispatchEvent(myComponent, e);
          }

          @Override
          public void mouseReleased(MouseEvent e) {
            dispatchEvent(myComponent, e);
          }

          @Override
          public void mouseEntered(MouseEvent e) {}

          @Override
          public void mouseExited(MouseEvent e) {
            // don't hide the hint if mouse exited to owner component
            if (myComponent.getMousePosition() == null) {
              hideHint();
            }
          }
        });

    myTipComponent.addMouseMotionListener(
        new MouseMotionListener() {
          @Override
          public void mouseMoved(MouseEvent e) {
            dispatchEvent(myComponent, e);
          }

          @Override
          public void mouseDragged(MouseEvent e) {
            dispatchEvent(myComponent, e);
          }
        });

    myComponent.addMouseListener(
        new MouseListener() {
          @Override
          public void mouseEntered(MouseEvent e) {
            handleMouseEvent(e);
          }

          @Override
          public void mouseExited(MouseEvent e) {
            // don't hide the hint if mouse exited to it
            if (myTipComponent.getMousePosition() == null) {
              hideHint();
            }
          }

          @Override
          public void mouseClicked(MouseEvent e) {}

          @Override
          public void mousePressed(MouseEvent e) {
            handleMouseEvent(e);
          }

          @Override
          public void mouseReleased(MouseEvent e) {
            handleMouseEvent(e);
          }
        });

    myComponent.addMouseMotionListener(
        new MouseMotionListener() {
          @Override
          public void mouseDragged(MouseEvent e) {
            handleMouseEvent(e);
          }

          @Override
          public void mouseMoved(MouseEvent e) {
            handleMouseEvent(e, false);
          }
        });

    myComponent.addFocusListener(
        new FocusAdapter() {
          @Override
          public void focusLost(FocusEvent e) {
            onFocusLost();
          }

          @Override
          public void focusGained(FocusEvent e) {
            updateCurrentSelection();
          }
        });

    myComponent.addComponentListener(
        new ComponentAdapter() {
          @Override
          public void componentHidden(ComponentEvent e) {
            hideHint();
          }

          @Override
          public void componentMoved(ComponentEvent e) {
            updateCurrentSelection();
          }

          @Override
          public void componentResized(ComponentEvent e) {
            updateCurrentSelection();
          }
        });

    myComponent.addHierarchyBoundsListener(
        new HierarchyBoundsAdapter() {
          @Override
          public void ancestorMoved(HierarchyEvent e) {
            updateCurrentSelection();
          }

          @Override
          public void ancestorResized(HierarchyEvent e) {
            updateCurrentSelection();
          }
        });

    myComponent.addHierarchyListener(
        new HierarchyListener() {
          @Override
          public void hierarchyChanged(HierarchyEvent e) {
            hideHint();
          }
        });
  }
 protected Rectangle getVisibleRect(KeyType key) {
   return myComponent.getVisibleRect();
 }
 protected void doFillBackground(int height, int width, Graphics2D g) {
   g.setColor(myComponent.getBackground());
   g.fillRect(0, 0, width, height);
 }
 private void repaintKeyItem() {
   if (myKeyItemBounds != null) {
     myComponent.repaint(myKeyItemBounds);
   }
 }