public RInstalledPackagesPanelBase()

in src/org/jetbrains/r/packages/remote/ui/RInstalledPackagesPanelBase.java [102:291]


  public RInstalledPackagesPanelBase(@NotNull Project project, @NotNull PackagesNotificationPanel area) {
    super(new BorderLayout());
    myProject = project;
    myNotificationArea = area;

    myPackagesTableModel = new DefaultTableModel(new String[]{"", "Package", "Description", "Version", "", ""}, 0) {
      @Override
      public boolean isCellEditable(int i, int i1) {
        return false;
      }
    };
    myPackageFilteringModel = new MyFilteringTableModel(myPackagesTableModel);
    final TableCellRenderer tableCellRenderer = new MyTableCellRenderer();
    myPackagesTable = new JBTable(myPackageFilteringModel) {
      @Override
      public TableCellRenderer getCellRenderer(int row, int column) {
        return tableCellRenderer;
      }
    };
    myPackagesTable.setShowVerticalLines(false);
    myPackagesTable.setShowHorizontalLines(false);
    myPackagesTable.setTableHeader(null);
    myPackagesTable.setPreferredScrollableViewportSize(null);
    myPackagesTable.setCellSelectionEnabled(false);
    myPackagesTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
    initColumnWidth();

    MessageBusConnection connect = project.getMessageBus().connect();
    connect.subscribe(EditorColorsManager.TOPIC, scheme -> {
      IJSwingUtilities.updateComponentTreeUI(myLabel);
      IJSwingUtilities.updateComponentTreeUI(myPackageNameLinkLabel);
      IJSwingUtilities.updateComponentTreeUI(myIsLoadedCheckBox);
    });

    connect.subscribe(RInteropImplKt.getLOADED_LIBRARIES_UPDATED(), myPackagesTable::repaint);
    AnAction upgradeAction = new DumbAwareAction() {
      @Override
      public @NotNull ActionUpdateThread getActionUpdateThread() {
        return ActionUpdateThread.EDT;
      }

      @Override
      public void update(@NotNull AnActionEvent e) {
        e.getPresentation().setEnabled(myUpgradeEnabled);
      }

      @Override
      public void actionPerformed(@NotNull AnActionEvent e) {
        upgradeAction();
      }
    };
    AnAction installAction = new DumbAwareAction() {
      @Override
      public @NotNull ActionUpdateThread getActionUpdateThread() {
        return ActionUpdateThread.EDT;
      }

      @Override
      public void update(@NotNull AnActionEvent e) {
        e.getPresentation().setEnabled(myInstallEnabled);
      }

      @Override
      public void actionPerformed(@NotNull AnActionEvent e) {
        installAction();
      }
    };
    ActionUtil.copyFrom(upgradeAction, UPGRADE_ACTION_ID);
    ActionUtil.copyFrom(installAction, INSTALL_ACTION_ID);

    MyTextSearchField textSearchFieldAction = new MyTextSearchField();
    installAction.setShortcutSet(CommonShortcuts.getNew());
    ToolbarDecorator decorator =
      ToolbarDecorator.createDecorator(myPackagesTable).disableUpDownActions().disableAddAction().disableRemoveAction()
        .addExtraAction(textSearchFieldAction)
        .addExtraAction(installAction)
        .addExtraAction(upgradeAction);
    decorator.setToolbarPosition(ActionToolbarPosition.TOP);

    DocumentAdapter listener = new DocumentAdapter() {
      @Override
      protected void textChanged(@NotNull DocumentEvent e) {
        String text = textSearchFieldAction.myField.getText();
        if (StringUtil.isEmpty(text)) {
          myPackageFilteringModel.setFilter(null);
          return;
        }

        //MinusculeMatcher matcher = NameUtil.buildMatcher("*" + mySearchField.getText(), NameUtil.MatchingCaseSensitivity.NONE);
        myPackageFilteringModel.setFilter(text);
      }
    };
    textSearchFieldAction.myField.getTextEditor().getDocument().addDocumentListener(listener);

    decorator.addExtraActions(getExtraActions());
    add(decorator.createPanel());

    myPackagesTable.getSelectionModel().addListSelectionListener(event -> updateUninstallUpgrade());

    myPackagesTable.addMouseMotionListener( new MouseMotionAdapter() {
      boolean hit = false;

      @Override
      public void mouseMoved(MouseEvent e) {
        Point columnRow = getMouseColumnRow(e.getLocationOnScreen(), myPackagesTable);
        if (columnRow.x == PACKAGE_NAME_COLUMN) {
          myPackagesTable.repaint();
          hit = true;
        } else if (hit) {
          myPackagesTable.repaint();
          hit = false;
        }

      }
    });

    myPackagesTable.addMouseListener(new MouseInputAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        Point columnRow = getMouseColumnRow(e.getLocationOnScreen(), myPackagesTable);
        if (columnRow.x == IS_LOADED_COLUMN) {
          doRecorded(LOAD_UNLOAD_ACTION_ID, e, () -> loadUnloadPackage(columnRow));
        }
        if (columnRow.x == PACKAGE_NAME_COLUMN) {
          doRecorded(NAVIGATE_TO_DOCUMENTATION_ACTION_ID, e, () -> navigateToDocumentation(columnRow));
        }
        if (columnRow.x == BROWSE_COLUMN) {
          doRecorded(OPEN_LINK_ACTION_ID, e, () -> openLink(columnRow));
        }
        if (columnRow.x == UNINSTALL_COLUMN) {
          // Note: recorded inside `uninstallPackage()`
          uninstallPackage(e, columnRow);
        }
      }

      private void loadUnloadPackage(Point columnRow) {
        RInstalledPackage aPackage = getInstalledPackageAt(columnRow.y);
        if (aPackage != null) {
          var packageName = aPackage.getName();
          if (myPackageManagementService.isPackageLoaded(packageName)) {
            myPackageManagementService.launchUnloadPackage(packageName, false);
          } else {
            myPackageManagementService.launchLoadPackage(packageName);
          }
        }
      }

      private void navigateToDocumentation(Point columnRow) {
        RInstalledPackage aPackage = getInstalledPackageAt(columnRow.y);
        if (aPackage != null) {
          myPackageManagementService.navigateToPackageDocumentation(aPackage);
        }
      }

      private void uninstallPackage(MouseEvent e, Point columnRow) {
        RInstalledPackage aPackage = getInstalledPackageAt(columnRow.y);
        if (aPackage != null && myPackageManagementService.canUninstallPackage(aPackage)) {
          int yesNo = Messages.showYesNoDialog(myPackagesTable,
                                               RBundle.INSTANCE
                                                 .message("install.package.dialog.message.are.you.sure.you.wish.to.uninstall.package",
                                                          aPackage.getName()),
                                               RBundle.INSTANCE.message("install.package.dialog.title.uninstall", aPackage.getName()),
                                               AllIcons.Diff.Remove);
          if (yesNo == Messages.YES) {
            doRecorded(UNINSTALL_ACTION_ID, e, () -> uninstallAction(Collections.singletonList(aPackage)));
          }
        }
      }

      private void openLink(Point columnRow) {
        RInstalledPackage installedPackage = getInstalledPackageAt(columnRow.y);
        if (installedPackage != null) {
          String url = installedPackage.getDescription().get("URL");
          String link = null;
          if (url != null && (url.startsWith("http"))) {
            int firstLinkEnded = url.indexOf(", ");
            if (firstLinkEnded == -1) {
              link = url;
            } else {
              link = url.substring(0, firstLinkEnded);
            }
          }
          if (link == null) {
            link = "https://cran.r-project.org/package=" + installedPackage.getName();
          }
          BrowserLauncher.getInstance().browse(link, null);
        }
      }
    });
  }