Ticket #20720: 20720-2021-04-12.patch

File 20720-2021-04-12.patch, 6.7 KB (added by ygramul, 5 years ago)

Updated patch to improve filtering performance in Plugins Preferences tab

  • src/org/openstreetmap/josm/gui/preferences/plugin/PluginListPanel.java

     
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.Component;
    67import java.awt.GridBagConstraints;
    78import java.awt.GridBagLayout;
    89import java.awt.Insets;
    910import java.awt.Rectangle;
    1011import java.awt.event.MouseAdapter;
    1112import java.awt.event.MouseEvent;
     13import java.util.ArrayList;
     14import java.util.HashMap;
     15import java.util.HashSet;
    1216import java.util.List;
     17import java.util.Map;
     18import java.util.Set;
    1319
    1420import javax.swing.JLabel;
    1521import javax.swing.SwingConstants;
     
    3844
    3945    private final transient PluginPreferencesModel model;
    4046
     47    /** Whether the plugin list has been built up already in the UI. */
     48    private boolean pluginListInitialized = false;
     49
    4150    /**
     51     * A map from the plugin information to the UI components that are used to display that information.
     52     *
     53     * Used to selectively hide filtered elements without the filtering code having to
     54     * know about the exact number and order of components belonging to a particular plugin.
     55     */
     56    private final Map<PluginInformation, List<Component>> componentsForPlugin = new HashMap<>();
     57
     58    /**
    4259     * Constructs a new {@code PluginListPanel} with a default model.
    4360     */
    4461    public PluginListPanel() {
     
    104121                        tr("The filter returned no results."))
    105122                + "</html>"
    106123        );
     124        List<Component> components = new ArrayList<>(1);
     125        components.add(hint);
     126        componentsForPlugin.put(null, components);
    107127        add(hint, gbc);
    108128    }
    109129
     
    121141
    122142        int row = -1;
    123143        for (final PluginInformation pi : displayedPlugins) {
     144            List<Component> components = new ArrayList<>(3);
    124145            boolean selected = model.isSelectedPlugin(pi.getName());
    125146            String remoteversion = formatPluginRemoteVersion(pi);
    126147            String localversion = formatPluginLocalVersion(model.getPluginInformation(pi.getName()));
     
    141162            gbc.insets = new Insets(5, 5, 0, 5);
    142163            gbc.weighty = 0.0;
    143164            gbc.weightx = 0.0;
     165            components.add(cbPlugin);
    144166            add(cbPlugin, gbc);
    145167
    146168            gbc.gridx = 1;
    147169            gbc.weightx = 1.0;
     170            components.add(lblPlugin);
    148171            add(lblPlugin, gbc);
    149172
    150173            HtmlPanel description = new HtmlPanel();
     
    156179            gbc.gridy = ++row;
    157180            gbc.insets = new Insets(3, 25, 5, 5);
    158181            gbc.weighty = 1.0;
     182            components.add(description);
    159183            add(description, gbc);
     184            componentsForPlugin.put(pi, components);
    160185        }
     186
     187        pluginListInitialized = true;
    161188    }
    162189
    163190    /**
    164191     * Refreshes the list.
     192     *
     193     * If the list has been changed completely (i.e. not just filtered),
     194     * call {@link #resetDisplayedComponents()} prior to calling this method.
    165195     */
    166196    public void refreshView() {
    167197        final Rectangle visibleRect = getVisibleRect();
    168198        List<PluginInformation> displayedPlugins = model.getDisplayedPlugins();
    169         removeAll();
    170199
    171200        if (displayedPlugins.isEmpty()) {
     201            hidePluginsNotInList(new ArrayList<>());
    172202            displayEmptyPluginListInformation();
     203        } else if (!pluginListInitialized) {
     204            removeAll();
     205            displayPluginList(displayedPlugins);
    173206        } else {
    174             displayPluginList(displayedPlugins);
     207            hidePluginsNotInList(displayedPlugins);
    175208        }
    176209        revalidate();
    177210        repaint();
    178211        SwingUtilities.invokeLater(() -> scrollRectToVisible(visibleRect));
    179212    }
    180213
     214    /**
     215     * Hides components in the list for plugins that are currently filtered away.
     216     *
     217     * Since those components are relatively heavyweight rebuilding them every time
     218     * when the filter changes is fairly slow, so we build them once and just hide
     219     * those that shouldn't be visible.
     220     *
     221     * @param displayedPlugins A collection of plugins that are currently visible.
     222     */
     223    private void hidePluginsNotInList(List<PluginInformation> displayedPlugins) {
     224        Set<PluginInformation> displayedPluginsSet = new HashSet<>(displayedPlugins);
     225        componentsForPlugin.forEach((pi, components) -> {
     226            if (displayedPluginsSet.contains(pi)) {
     227                for (Component component : components) {
     228                    component.setVisible(true);
     229                }
     230            } else {
     231                for (Component component : components) {
     232                    component.setVisible(false);
     233                }
     234            }
     235        });
     236    }
     237
     238    /**
     239     * Causes the components for the list items to be rebuilt from scratch.
     240     *
     241     * Should be called before calling {@link #refreshView()} whenever the
     242     * underlying list changes to display a completely different set of
     243     * plugins instead of merely hiding plugins by a filter.
     244     */
     245    public void resetDisplayedComponents() {
     246        pluginListInitialized = false;
     247        componentsForPlugin.clear();
     248    }
     249
    181250    @Override
    182251    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
    183252        return visibleRect.height / 4;
  • src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java

     
    339339            if (!task.isCanceled()) {
    340340                SwingUtilities.invokeLater(() -> {
    341341                    model.setAvailablePlugins(task.getAvailablePlugins());
     342                    pnlPluginPreferences.resetDisplayedComponents();
    342343                    pnlPluginPreferences.refreshView();
    343344                });
    344345            }
     
    372373                if (!task.isCanceled()) {
    373374                    SwingUtilities.invokeLater(() -> {
    374375                        model.updateAvailablePlugins(task.getAvailablePlugins());
     376                        pnlPluginPreferences.resetDisplayedComponents();
    375377                        pnlPluginPreferences.refreshView();
    376378                        Config.getPref().putInt("pluginmanager.version", Version.getInstance().getVersion()); // fix #7030
    377379                    });