Пример #1
0
  private static void patchHiDPI(UIDefaults defaults) {
    if (!JBUI.isHiDPI()) return;

    List<String> myIntKeys = Arrays.asList("Tree.leftChildIndent", "Tree.rightChildIndent");
    List<String> patched = new ArrayList<String>();
    for (Map.Entry<Object, Object> entry : defaults.entrySet()) {
      Object value = entry.getValue();
      String key = entry.getKey().toString();
      if (value instanceof DimensionUIResource) {
        entry.setValue(JBUI.size((DimensionUIResource) value).asUIResource());
      } else if (value instanceof InsetsUIResource) {
        entry.setValue(JBUI.insets(((InsetsUIResource) value)).asUIResource());
      } else if (value instanceof Integer) {
        if (key.endsWith(".maxGutterIconWidth") || myIntKeys.contains(key)) {
          if (!"true".equals(defaults.get(key + ".hidpi.patched"))) {
            entry.setValue(Integer.valueOf(JBUI.scale((Integer) value)));
            patched.add(key);
          }
        }
      }
    }
    for (String key : patched) {
      defaults.put(key + ".hidpi.patched", "true");
    }
  }
  private void updateSystemIcon() {
    Window window = getWindow();
    if (window == null) {
      mySystemIcon = null;
      return;
    }

    List<Image> icons = window.getIconImages();
    assert icons != null;

    if (icons.size() == 0) {
      mySystemIcon = null;
    } else if (icons.size() == 1) {
      mySystemIcon = icons.get(0);
    } else {
      final JBDimension size = JBUI.size(32);
      final Image image = icons.get(0);
      mySystemIcon =
          Scalr.resize(
              ImageUtil.toBufferedImage(image),
              Scalr.Method.ULTRA_QUALITY,
              size.width,
              size.height);
    }
  }
  private JPanel createSignaturePanel() {
    mySignature = new GrMethodSignatureComponent("", myProject);
    myTable =
        new ParameterTablePanel() {
          @Override
          protected void updateSignature() {
            GrIntroduceParameterDialog.this.updateSignature();
          }

          @Override
          protected void doEnterAction() {
            clickDefaultButton();
          }

          @Override
          protected void doCancelAction() {
            GrIntroduceParameterDialog.this.doCancelAction();
          }
        };

    mySignature.setBorder(
        IdeBorderFactory.createTitledBorder(
            GroovyRefactoringBundle.message("signature.preview.border.title"), false));

    Splitter splitter = new Splitter(true);

    splitter.setFirstComponent(myTable);
    splitter.setSecondComponent(mySignature);

    mySignature.setPreferredSize(JBUI.size(500, 100));
    mySignature.setSize(JBUI.size(500, 100));

    splitter.setShowDividerIcon(false);

    final JPanel panel = new JPanel(new BorderLayout());
    panel.add(splitter, BorderLayout.CENTER);
    myForceReturnCheckBox =
        new JCheckBox(UIUtil.replaceMnemonicAmpersand("Use e&xplicit return statement"));
    panel.add(myForceReturnCheckBox, BorderLayout.NORTH);

    return panel;
  }
  private static DialogBuilder createChangeInfoDialog(
      Project project, @NotNull CCNewProjectPanel panel) {
    DialogBuilder builder = new DialogBuilder(project);

    builder.setTitle(ACTION_TEXT);
    JPanel changeInfoPanel = panel.getMainPanel();
    changeInfoPanel.setMinimumSize(JBUI.size(400, 300));
    builder.setCenterPanel(changeInfoPanel);

    return builder;
  }
Пример #5
0
  @Override
  public UIDefaults getDefaults() {
    try {
      final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults");
      superMethod.setAccessible(true);
      final UIDefaults metalDefaults = (UIDefaults) superMethod.invoke(new MetalLookAndFeel());

      final UIDefaults defaults = (UIDefaults) superMethod.invoke(base);
      if (SystemInfo.isLinux) {
        if (!Registry.is("darcula.use.native.fonts.on.linux")) {
          Font font = findFont("DejaVu Sans");
          if (font != null) {
            for (Object key : defaults.keySet()) {
              if (key instanceof String && ((String) key).endsWith(".font")) {
                defaults.put(key, new FontUIResource(font.deriveFont(13f)));
              }
            }
          }
        } else if (Arrays.asList("CN", "JP", "KR", "TW")
            .contains(Locale.getDefault().getCountry())) {
          for (Object key : defaults.keySet()) {
            if (key instanceof String && ((String) key).endsWith(".font")) {
              final Font font = defaults.getFont(key);
              if (font != null) {
                defaults.put(key, new FontUIResource("Dialog", font.getStyle(), font.getSize()));
              }
            }
          }
        }
      }

      LafManagerImpl.initInputMapDefaults(defaults);
      initIdeaDefaults(defaults);
      patchStyledEditorKit(defaults);
      patchComboBox(metalDefaults, defaults);
      defaults.remove("Spinner.arrowButtonBorder");
      defaults.put("Spinner.arrowButtonSize", JBUI.size(16, 5).asUIResource());
      MetalLookAndFeel.setCurrentTheme(createMetalTheme());
      if (SystemInfo.isWindows && Registry.is("ide.win.frame.decoration")) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);
      }
      if (SystemInfo.isLinux && JBUI.isHiDPI()) {
        applySystemFonts(defaults);
      }
      defaults.put("EditorPane.font", defaults.getFont("TextField.font"));
      return defaults;
    } catch (Exception e) {
      log(e);
    }
    return super.getDefaults();
  }
  public FlatWelcomeFrame() {
    final JRootPane rootPane = getRootPane();
    myScreen = new FlatWelcomeScreen();

    final IdeGlassPaneImpl glassPane =
        new IdeGlassPaneImpl(rootPane) {
          @Override
          public void addNotify() {
            super.addNotify();
            rootPane.remove(getProxyComponent());
            //noinspection SSBasedInspection
            SwingUtilities.invokeLater(
                new Runnable() {
                  public void run() {
                    JBProtocolCommand.handleCurrentCommand();
                  }
                });
          }
        };

    setGlassPane(glassPane);
    glassPane.setVisible(false);
    // setUndecorated(true);
    setContentPane(myScreen.getWelcomePanel());
    setTitle("Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName());
    AppUIUtil.updateWindowIcon(this);
    final int width =
        RecentProjectsManager.getInstance().getRecentProjectsActions(false).length == 0 ? 666 : 777;
    setSize(JBUI.size(width, 460));
    setResizable(false);
    // int x = bounds.x + (bounds.width - getWidth()) / 2;
    // int y = bounds.y + (bounds.height - getHeight()) / 2;
    Point location = DimensionService.getInstance().getLocation(WelcomeFrame.DIMENSION_KEY, null);
    Rectangle screenBounds =
        ScreenUtil.getScreenRectangle(location != null ? location : new Point(0, 0));
    setLocation(
        new Point(
            screenBounds.x + (screenBounds.width - getWidth()) / 2,
            screenBounds.y + (screenBounds.height - getHeight()) / 3));

    // setLocation(x, y);
    ProjectManager.getInstance()
        .addProjectManagerListener(
            new ProjectManagerAdapter() {
              @Override
              public void projectOpened(Project project) {
                dispose();
              }
            });

    myBalloonLayout = new BalloonLayoutImpl(rootPane, JBUI.insets(8));

    WelcomeFrame.setupCloseAction(this);
    MnemonicHelper.init(this);
    Disposer.register(
        ApplicationManager.getApplication(),
        new Disposable() {
          @Override
          public void dispose() {
            FlatWelcomeFrame.this.dispose();
          }
        });
  }
  public ProcessedModulesTable(final Project project) {
    super(new BorderLayout());

    myTableModel = new MyTableModel(project);
    myTable = new JBTable(myTableModel);
    myTable.getEmptyText().setText("No modules configured");

    // myTable.setShowGrid(false);
    myTable.setIntercellSpacing(JBUI.emptySize());
    myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
    myTable.setColumnSelectionAllowed(false);

    final TableColumnModel columnModel = myTable.getColumnModel();

    final TableColumn dirNameColumn = columnModel.getColumn(myTableModel.DIRNAME_COLUMN_INDEX);
    final String title = "Generated Sources Directory Name";
    dirNameColumn.setHeaderValue(title);
    final JTableHeader tableHeader = myTable.getTableHeader();
    final FontMetrics metrics = tableHeader.getFontMetrics(tableHeader.getFont());
    final int preferredWidth = metrics.stringWidth(title) + 12;
    dirNameColumn.setPreferredWidth(preferredWidth);
    dirNameColumn.setMaxWidth(preferredWidth + 20);
    dirNameColumn.setCellRenderer(new MyElementColumnCellRenderer());

    final TableColumn moduleColumn = columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX);
    moduleColumn.setHeaderValue("Module");
    moduleColumn.setCellRenderer(new MyElementColumnCellRenderer());

    final JPanel panel =
        ToolbarDecorator.createDecorator(myTable)
            .disableUpDownActions()
            .setPreferredSize(JBUI.size(100, 155))
            .createPanel();
    add(panel, BorderLayout.CENTER);

    final SpeedSearchBase<JBTable> speedSearch =
        new SpeedSearchBase<JBTable>(myTable) {
          public int getSelectedIndex() {
            return myTable.getSelectedRow();
          }

          @Override
          protected int convertIndexToModel(int viewIndex) {
            return myTable.convertRowIndexToModel(viewIndex);
          }

          public Object[] getAllElements() {
            final int count = myTableModel.getRowCount();
            Object[] elements = new Object[count];
            for (int idx = 0; idx < count; idx++) {
              elements[idx] = myTableModel.getModuleAt(idx);
            }
            return elements;
          }

          public String getElementText(Object element) {
            return ((Module) element).getName()
                + " ("
                + FileUtil.toSystemDependentName(((Module) element).getModuleFilePath())
                + ")";
          }

          public void selectElement(Object element, String selectedText) {
            final int count = myTableModel.getRowCount();
            for (int row = 0; row < count; row++) {
              if (element.equals(myTableModel.getModuleAt(row))) {
                final int viewRow = myTable.convertRowIndexToView(row);
                myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
                TableUtil.scrollSelectionToVisible(myTable);
                break;
              }
            }
          }
        };
    speedSearch.setComparator(new SpeedSearchComparator(false));
  }
  protected JComponent createCenterPanel() {
    JPanel panel = new MyPanel();

    myUiUpdater = new MergingUpdateQueue("FileChooserUpdater", 200, false, panel);
    Disposer.register(myDisposable, myUiUpdater);
    new UiNotifyConnector(panel, myUiUpdater);

    panel.setBorder(JBUI.Borders.empty());

    createTree();

    final DefaultActionGroup group = createActionGroup();
    ActionToolbar toolBar =
        ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
    toolBar.setTargetComponent(panel);

    final JPanel toolbarPanel = new JPanel(new BorderLayout());
    toolbarPanel.add(toolBar.getComponent(), BorderLayout.CENTER);

    myTextFieldAction =
        new TextFieldAction() {
          public void linkSelected(final LinkLabel aSource, final Object aLinkData) {
            toggleShowTextField();
          }
        };
    toolbarPanel.add(myTextFieldAction, BorderLayout.EAST);

    myPathTextFieldWrapper = new JPanel(new BorderLayout());
    myPathTextFieldWrapper.setBorder(JBUI.Borders.emptyBottom(2));
    myPathTextField =
        new FileTextFieldImpl.Vfs(
            FileChooserFactoryImpl.getMacroMap(),
            getDisposable(),
            new LocalFsFinder.FileChooserFilter(myChooserDescriptor, myFileSystemTree)) {
          protected void onTextChanged(final String newValue) {
            myUiUpdater.cancelAllUpdates();
            updateTreeFromPath(newValue);
          }
        };
    Disposer.register(myDisposable, myPathTextField);
    myPathTextFieldWrapper.add(myPathTextField.getField(), BorderLayout.CENTER);
    if (getRecentFiles().length > 0) {
      myPathTextFieldWrapper.add(createHistoryButton(), BorderLayout.EAST);
    }

    myNorthPanel = new JPanel(new BorderLayout());
    myNorthPanel.add(toolbarPanel, BorderLayout.NORTH);

    updateTextFieldShowing();

    panel.add(myNorthPanel, BorderLayout.NORTH);

    registerMouseListener(group);

    JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myFileSystemTree.getTree());
    // scrollPane.setBorder(BorderFactory.createLineBorder(new Color(148, 154, 156)));
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.setPreferredSize(JBUI.size(400));

    panel.add(
        new JLabel(
            "<html><center><small><font color=gray>Drag and drop a file into the space above to quickly locate it in the tree.</font></small></center></html>",
            SwingConstants.CENTER),
        BorderLayout.SOUTH);

    ApplicationManager.getApplication()
        .getMessageBus()
        .connect(getDisposable())
        .subscribe(
            ApplicationActivationListener.TOPIC,
            new ApplicationActivationListener.Adapter() {
              @Override
              public void applicationActivated(IdeFrame ideFrame) {
                ((SaveAndSyncHandlerImpl) SaveAndSyncHandler.getInstance())
                    .maybeRefresh(ModalityState.current());
              }
            });

    return panel;
  }
  public FileColorsConfigurablePanel(@NotNull final FileColorManagerImpl manager) {
    setLayout(new BorderLayout());
    myManager = manager;

    final JPanel topPanel = new JPanel();
    topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));

    myEnabledCheckBox = new JCheckBox("Enable File Colors");
    myEnabledCheckBox.setMnemonic('F');
    topPanel.add(myEnabledCheckBox);

    myTabsEnabledCheckBox = new JCheckBox("Use in Editor Tabs");
    myTabsEnabledCheckBox.setMnemonic('T');
    topPanel.add(myTabsEnabledCheckBox);

    myProjectViewEnabledCheckBox = new JCheckBox("Use in Project View");
    myProjectViewEnabledCheckBox.setMnemonic('P');
    topPanel.add(myProjectViewEnabledCheckBox);

    topPanel.add(Box.createHorizontalGlue());

    add(topPanel, BorderLayout.NORTH);

    final JPanel mainPanel = new JPanel(new GridLayout(2, 1));
    mainPanel.setPreferredSize(JBUI.size(300, 500));
    mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0));

    final List<FileColorConfiguration> localConfigurations =
        manager.getApplicationLevelConfigurations();
    myLocalTable =
        new FileColorSettingsTable(manager, localConfigurations) {
          @Override
          protected void apply(@NotNull List<FileColorConfiguration> configurations) {
            final List<FileColorConfiguration> copied = new ArrayList<FileColorConfiguration>();
            try {
              for (final FileColorConfiguration configuration : configurations) {
                copied.add(configuration.clone());
              }
            } catch (CloneNotSupportedException e) { //
            }
            manager.getModel().setConfigurations(copied, false);
          }
        };

    final JPanel panel =
        ToolbarDecorator.createDecorator(myLocalTable)
            .addExtraAction(
                new AnActionButton("Share", AllIcons.Actions.Share) {
                  @Override
                  public void actionPerformed(AnActionEvent e) {
                    share();
                  }

                  @Override
                  public boolean isEnabled() {
                    return super.isEnabled() && myLocalTable.getSelectedRow() != -1;
                  }
                })
            .createPanel();
    final JPanel localPanel = new JPanel(new BorderLayout());
    localPanel.setBorder(IdeBorderFactory.createTitledBorder("Local colors", false));
    localPanel.add(panel, BorderLayout.CENTER);
    mainPanel.add(localPanel);

    mySharedTable =
        new FileColorSettingsTable(manager, manager.getProjectLevelConfigurations()) {
          @Override
          protected void apply(@NotNull List<FileColorConfiguration> configurations) {
            final List<FileColorConfiguration> copied = new ArrayList<FileColorConfiguration>();
            for (final FileColorConfiguration configuration : configurations) {
              try {
                copied.add(configuration.clone());
              } catch (CloneNotSupportedException e) {
                assert false : "Should not happen!";
              }
            }
            manager.getModel().setConfigurations(copied, true);
          }
        };

    final JPanel sharedPanel = new JPanel(new BorderLayout());
    sharedPanel.setBorder(IdeBorderFactory.createTitledBorder("Shared colors", false));
    final JPanel shared =
        ToolbarDecorator.createDecorator(mySharedTable)
            .addExtraAction(
                new AnActionButton("Unshare", AllIcons.Actions.Unshare) {
                  @Override
                  public void actionPerformed(AnActionEvent e) {
                    unshare();
                  }

                  @Override
                  public boolean isEnabled() {
                    return super.isEnabled() && mySharedTable.getSelectedRow() != -1;
                  }
                })
            .createPanel();

    sharedPanel.add(shared, BorderLayout.CENTER);
    mainPanel.add(sharedPanel);
    add(mainPanel, BorderLayout.CENTER);

    final JPanel infoPanel = new JPanel(new BorderLayout());
    infoPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    infoPanel.add(
        new JLabel(
            "Scopes are processed from top to bottom with Local colors first.",
            MessageType.INFO.getDefaultIcon(),
            SwingConstants.LEFT));
    JButton editScopes = new JButton("Manage Scopes...");
    editScopes.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(@NotNull ActionEvent e) {
            EditScopesDialog.showDialog(myManager.getProject(), null, true);
          }
        });
    infoPanel.add(editScopes, BorderLayout.EAST);
    add(infoPanel, BorderLayout.SOUTH);

    myLocalTable.getEmptyText().setText("No local colors");
    mySharedTable.getEmptyText().setText("No shared colors");
  }
  @Override
  protected JComponent createCenterPanel() {
    final int selectionMode =
        myAllowMultipleSelections
            ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
            : ListSelectionModel.SINGLE_SELECTION;
    myList.setSelectionMode(selectionMode);
    if (myUseIdeaEditor) {
      EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
      myList.setFont(scheme.getFont(EditorFontType.PLAIN));
      Color fg =
          ObjectUtils.chooseNotNull(scheme.getDefaultForeground(), UIUtil.getListForeground());
      Color bg =
          ObjectUtils.chooseNotNull(scheme.getDefaultBackground(), UIUtil.getListBackground());
      myList.setForeground(fg);
      myList.setBackground(bg);
    }

    new DoubleClickListener() {
      @Override
      protected boolean onDoubleClick(MouseEvent e) {
        close(OK_EXIT_CODE);
        return true;
      }
    }.installOn(myList);

    myList.setCellRenderer(new MyListCellRenderer());
    myList.addKeyListener(
        new KeyAdapter() {
          @Override
          public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_DELETE) {
              int newSelectionIndex = -1;
              for (Object o : myList.getSelectedValues()) {
                int i = ((Item) o).index;
                removeContentAt(myAllContents.get(i));
                if (newSelectionIndex < 0) {
                  newSelectionIndex = i;
                }
              }

              rebuildListContent();
              if (myAllContents.isEmpty()) {
                close(CANCEL_EXIT_CODE);
                return;
              }
              newSelectionIndex = Math.min(newSelectionIndex, myAllContents.size() - 1);
              myList.setSelectedIndex(newSelectionIndex);
            } else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
              doOKAction();
            } else {
              final char aChar = e.getKeyChar();
              if (aChar >= '0' && aChar <= '9') {
                int idx = aChar == '0' ? 9 : aChar - '1';
                if (idx < myAllContents.size()) {
                  myList.setSelectedIndex(idx);
                  e.consume();
                  doOKAction();
                }
              }
            }
          }
        });

    mySplitter.setFirstComponent(
        ListWithFilter.wrap(
            myList,
            ScrollPaneFactory.createScrollPane(myList),
            new Function<Object, String>() {
              @Override
              public String fun(Object o) {
                return ((Item) o).longText;
              }
            }));
    mySplitter.setSecondComponent(new JPanel());
    rebuildListContent();

    ScrollingUtil.installActions(myList);
    ScrollingUtil.ensureSelectionExists(myList);
    updateViewerForSelection();
    myList.addListSelectionListener(
        new ListSelectionListener() {
          @Override
          public void valueChanged(ListSelectionEvent e) {
            myUpdateAlarm.cancelAllRequests();
            myUpdateAlarm.addRequest(
                new Runnable() {
                  @Override
                  public void run() {
                    updateViewerForSelection();
                  }
                },
                100);
          }
        });

    mySplitter.setPreferredSize(JBUI.size(500, 500));

    SplitterProportionsData d = new SplitterProportionsDataImpl();
    d.externalizeToDimensionService(getClass().getName());
    d.restoreSplitterProportions(mySplitter);

    return mySplitter;
  }
Пример #11
0
 protected Dimension getPanelPreferredSize() {
   return JBUI.size(800, 600);
 }
Пример #12
0
 @Override
 public Dimension getPreferredSize() {
   return JBUI.size(100, 32);
 }
Пример #13
0
 @Override
 public Dimension getMinimumSize() {
   return JBUI.size(300, 300);
 }
  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;
          }
        });
  }
  private void updateViewerForSelection() {
    if (myAllContents.isEmpty()) return;
    String fullString = getSelectedText();

    if (myViewer != null) {
      EditorFactory.getInstance().releaseEditor(myViewer);
    }

    if (myUseIdeaEditor) {
      myViewer = createIdeaEditor(fullString);
      JComponent component = myViewer.getComponent();
      component.setPreferredSize(JBUI.size(300, 500));
      mySplitter.setSecondComponent(component);
    } else {
      final JTextArea textArea = new JTextArea(fullString);
      textArea.setRows(3);
      textArea.setWrapStyleWord(true);
      textArea.setLineWrap(true);
      textArea.setSelectionStart(0);
      textArea.setSelectionEnd(textArea.getText().length());
      textArea.setEditable(false);
      mySplitter.setSecondComponent(ScrollPaneFactory.createScrollPane(textArea));
    }
    mySplitter.revalidate();
  }