@Override
  public void setBackground(Color bg) {
    super.setBackground(bg);

    myScrollPane.getViewport().setBackground(bg);
    mySearchTextField.setBackground(bg);
    myBreadcrumbs.setBackground(bg);
  }
        @Override
        public boolean apply(@Nullable ComponentDefinition input) {
          if (input == null) {
            return false;
          }

          Breadcrumb breadcrumb = myBreadcrumbs.peek();
          return (breadcrumb == null
              || breadcrumb.myGroup == null
              || breadcrumb.myGroup.equals(input.group));
        }
  public AndroidThemePreviewPanel(@NotNull ThemeEditorContext context, @NotNull Color background) {
    super(BoxLayout.PAGE_AXIS);

    setOpaque(true);
    setMinimumSize(JBUI.size(200, 0));

    myContext = context;
    myAndroidPreviewPanel = new AndroidPreviewPanel(myContext.getConfiguration());
    myContext.addChangeListener(
        new ThemeEditorContext.ChangeListener() {
          @Override
          public void onNewConfiguration(ThemeEditorContext context) {
            refreshConfiguration();
          }
        });
    myAndroidPreviewPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));

    myBreadcrumbs = new NavigationComponent<Breadcrumb>();
    myBreadcrumbs.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));

    myDumbService = DumbService.getInstance(context.getProject());

    myScrollPane =
        new JBScrollPane(
            myAndroidPreviewPanel,
            ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    myScrollPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
    myScrollPane.setBorder(null);
    myScrollPane.setViewportBorder(null);
    mySearchTextField = new SearchTextField(true);
    // Avoid search box stretching more than 1 line.
    mySearchTextField.setMaximumSize(
        new Dimension(Integer.MAX_VALUE, mySearchTextField.getPreferredSize().height));
    mySearchTextField.setBorder(IdeBorderFactory.createEmptyBorder(0, 30, 0, 30));
    final Runnable delayedUpdate =
        new Runnable() {
          @Override
          public void run() {
            rebuild();
          }
        };

    // We use a timer when we detect a change in the search field to avoid re-creating the preview
    // if it's not necessary.
    mySearchTextField.addDocumentListener(
        new DocumentAdapter() {
          @Override
          protected void textChanged(DocumentEvent e) {
            Document document = e.getDocument();
            try {
              String search = document.getText(0, document.getLength());

              // Only use search terms longer than 3 characters.
              String newSearchTerm = search.length() < 3 ? "" : search;
              if (newSearchTerm.equals(mySearchTerm)) {
                return;
              }
              if (myPendingSearch != null) {
                myPendingSearch.cancel(true);
              }
              mySearchTerm = newSearchTerm;
              myPendingSearch =
                  mySearchScheduler.schedule(delayedUpdate, 300, TimeUnit.MILLISECONDS);
            } catch (BadLocationException e1) {
              LOG.error(e1);
            }
          }
        });

    myBreadcrumbs.setRootItem(new Breadcrumb("All components"));

    add(Box.createRigidArea(new Dimension(0, 5)));
    add(myBreadcrumbs);
    add(Box.createRigidArea(new Dimension(0, 10)));
    add(mySearchTextField);
    add(Box.createRigidArea(new Dimension(0, 10)));
    add(myScrollPane);

    setBackground(background);
    reloadComponents();

    myBreadcrumbs.addItemListener(
        new NavigationComponent.ItemListener<Breadcrumb>() {
          @Override
          public void itemSelected(@NotNull Breadcrumb item) {
            myBreadcrumbs.goTo(item);
            rebuild();
          }
        });

    myAndroidPreviewPanel.addMouseListener(
        new MouseAdapter() {
          @Override
          public void mouseClicked(MouseEvent e) {
            ViewInfo view = myAndroidPreviewPanel.findViewAtPoint(e.getPoint());

            if (view == null) {
              return;
            }

            mySearchTextField.setText("");

            Object cookie = view.getCookie();
            if (cookie instanceof MergeCookie) {
              cookie = ((MergeCookie) cookie).getCookie();
            }

            if (!(cookie instanceof Element)) {
              return;
            }

            NamedNodeMap attributes = ((Element) cookie).getAttributes();
            Node group =
                attributes.getNamedItemNS(
                    ThemePreviewBuilder.BUILDER_URI, ThemePreviewBuilder.BUILDER_ATTR_GROUP);

            if (group != null) {
              myBreadcrumbs.push(
                  new Breadcrumb(ThemePreviewBuilder.ComponentGroup.valueOf(group.getNodeValue())));
              rebuild();
            }
          }
        });

    myContext.addConfigurationListener(
        new ConfigurationListener() {
          @Override
          public boolean changed(int flags) {
            refreshConfiguration();

            if ((flags & ConfigurationListener.CFG_THEME) != 0) {
              boolean appCompatTheme = isAppCompatTheme(myContext.getConfiguration());
              if (appCompatTheme != myIsAppCompatTheme) {
                rebuild();
              }
            }

            return true;
          }
        });
  }