mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
IJPL-159035 refactor SettingsFilter
GitOrigin-RevId: 9a0bbd9b4a2fe83daac024b968220ef863161cb8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b86c156997
commit
6d64659fc3
@@ -16311,8 +16311,12 @@ f:com.intellij.openapi.options.newEditor.SettingsDialogFactory$Companion
|
||||
- f:getInstance():com.intellij.openapi.options.newEditor.SettingsDialogFactory
|
||||
a:com.intellij.openapi.options.newEditor.SettingsFilter
|
||||
- com.intellij.ui.speedSearch.ElementFilter$Active$Impl
|
||||
- isEmptyFilter():Z
|
||||
- f:contains(com.intellij.openapi.options.Configurable):Z
|
||||
- f:isEmptyFilter():Z
|
||||
- f:reload():V
|
||||
- f:setFilterText(java.lang.String):V
|
||||
- shouldBeShowing(com.intellij.ui.treeStructure.SimpleNode):Z
|
||||
- f:update(java.lang.String):V
|
||||
c:com.intellij.openapi.options.newEditor.SettingsTreeView
|
||||
- javax.swing.JComponent
|
||||
- com.intellij.openapi.Disposable
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.awt.*;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public abstract class AbstractEditor extends JPanel implements Disposable {
|
||||
volatile boolean myDisposed;
|
||||
volatile boolean isDisposed;
|
||||
|
||||
AbstractEditor(@NotNull Disposable parent) {
|
||||
super(new BorderLayout());
|
||||
@@ -22,8 +22,8 @@ public abstract class AbstractEditor extends JPanel implements Disposable {
|
||||
|
||||
@Override
|
||||
public final void dispose() {
|
||||
if (!myDisposed) {
|
||||
myDisposed = true;
|
||||
if (!isDisposed) {
|
||||
isDisposed = true;
|
||||
disposeOnce();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.ui.ComponentUtil;
|
||||
import com.intellij.ui.LightColors;
|
||||
import com.intellij.ui.RelativeFont;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
@@ -45,10 +42,6 @@ import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.intellij.openapi.options.newEditor.ConfigurablesListPanelKt.createConfigurablesListPanel;
|
||||
import static com.intellij.ui.ScrollPaneFactory.createScrollPane;
|
||||
import static java.awt.Toolkit.getDefaultToolkit;
|
||||
import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;
|
||||
import static javax.swing.SwingUtilities.isDescendingFrom;
|
||||
|
||||
class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWTEventListener {
|
||||
private final MergingUpdateQueue myQueue = new MergingUpdateQueue("SettingsModification", 1000, false, this, this, this);
|
||||
@@ -103,7 +96,7 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
|
||||
MessageBusConnection messageBus = ApplicationManager.getApplication().getMessageBus().connect(this);
|
||||
messageBus.subscribe(AnActionListener.TOPIC, this);
|
||||
messageBus.subscribe(ExternalUpdateRequest.TOPIC, conf -> updateCurrent(conf, false));
|
||||
getDefaultToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.KEY_EVENT_MASK);
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.KEY_EVENT_MASK);
|
||||
if (configurable != null) {
|
||||
myConfigurable = configurable;
|
||||
myCardPanel.select(configurable, true).doWhenDone(() -> postUpdateCurrent(configurable));
|
||||
@@ -113,7 +106,7 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
|
||||
|
||||
@Override
|
||||
void disposeOnce() {
|
||||
getDefaultToolkit().removeAWTEventListener(this);
|
||||
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
|
||||
myCardPanel.removeAll();
|
||||
}
|
||||
|
||||
@@ -174,13 +167,13 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
|
||||
switch (event.getID()) {
|
||||
case MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, MouseEvent.MOUSE_DRAGGED -> {
|
||||
MouseEvent me = (MouseEvent)event;
|
||||
if (isDescendingFrom(me.getComponent(), this) || isPopupOverEditor(me.getComponent())) {
|
||||
if (SwingUtilities.isDescendingFrom(me.getComponent(), this) || isPopupOverEditor(me.getComponent())) {
|
||||
requestUpdate();
|
||||
}
|
||||
}
|
||||
case KeyEvent.KEY_PRESSED, KeyEvent.KEY_RELEASED -> {
|
||||
KeyEvent ke = (KeyEvent)event;
|
||||
if (isDescendingFrom(ke.getComponent(), this)) {
|
||||
if (SwingUtilities.isDescendingFrom(ke.getComponent(), this)) {
|
||||
requestUpdate();
|
||||
}
|
||||
}
|
||||
@@ -240,7 +233,7 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
|
||||
}
|
||||
|
||||
final @NotNull Promise<? super Object> select(final Configurable configurable) {
|
||||
assert !myDisposed : "Already disposed";
|
||||
assert !isDisposed : "Already disposed";
|
||||
long startTime = System.currentTimeMillis();
|
||||
final boolean loadedFromCache = myCardPanel.getValue(configurable, false) != null;
|
||||
ActionCallback callback = myCardPanel.select(configurable, false);
|
||||
@@ -303,8 +296,8 @@ class ConfigurableEditor extends AbstractEditor implements AnActionListener, AWT
|
||||
content.add(BorderLayout.CENTER, createConfigurablesListPanel(description, Arrays.asList(compositeGroup.getConfigurables()), this));
|
||||
}
|
||||
|
||||
JScrollPane pane = createScrollPane(content, true);
|
||||
pane.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER);
|
||||
JScrollPane pane = ScrollPaneFactory.createScrollPane(content, true);
|
||||
pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,36 +40,36 @@ import static com.intellij.openapi.actionSystem.IdeActions.ACTION_FIND;
|
||||
public class SettingsDialog extends DialogWrapper implements UiCompatibleDataProvider {
|
||||
public static final String DIMENSION_KEY = "SettingsEditor";
|
||||
|
||||
private final String myDimensionServiceKey;
|
||||
private final AbstractEditor myEditor;
|
||||
private final boolean myApplyButtonNeeded;
|
||||
private final boolean myResetButtonNeeded;
|
||||
private final String dimensionServiceKey;
|
||||
private final AbstractEditor editor;
|
||||
private final boolean isApplyButtonNeeded;
|
||||
private final boolean isResetButtonNeeded;
|
||||
private final JLabel myHintLabel = new JLabel();
|
||||
|
||||
public SettingsDialog(Project project, String key, @NotNull Configurable configurable, boolean showApplyButton, boolean showResetButton) {
|
||||
super(project, true);
|
||||
myDimensionServiceKey = key;
|
||||
myEditor = new SingleSettingEditor(myDisposable, configurable);
|
||||
myApplyButtonNeeded = showApplyButton;
|
||||
myResetButtonNeeded = showResetButton;
|
||||
dimensionServiceKey = key;
|
||||
editor = new SingleSettingEditor(myDisposable, configurable);
|
||||
isApplyButtonNeeded = showApplyButton;
|
||||
isResetButtonNeeded = showResetButton;
|
||||
init(configurable, project);
|
||||
}
|
||||
|
||||
public SettingsDialog(@NotNull Component parent, String key, @NotNull Configurable configurable, boolean showApplyButton, boolean showResetButton) {
|
||||
super(parent, true);
|
||||
myDimensionServiceKey = key;
|
||||
myEditor = new SingleSettingEditor(myDisposable, configurable);
|
||||
myApplyButtonNeeded = showApplyButton;
|
||||
myResetButtonNeeded = showResetButton;
|
||||
dimensionServiceKey = key;
|
||||
editor = new SingleSettingEditor(myDisposable, configurable);
|
||||
isApplyButtonNeeded = showApplyButton;
|
||||
isResetButtonNeeded = showResetButton;
|
||||
init(configurable, null);
|
||||
}
|
||||
|
||||
public SettingsDialog(@NotNull Project project, @NotNull List<? extends ConfigurableGroup> groups, @Nullable Configurable configurable, @Nullable String filter) {
|
||||
super(project, true);
|
||||
myDimensionServiceKey = DIMENSION_KEY;
|
||||
myEditor = new SettingsEditor(myDisposable, project, groups, configurable, filter, this::treeViewFactory, this::spotlightPainterFactory);
|
||||
myApplyButtonNeeded = true;
|
||||
myResetButtonNeeded = false;
|
||||
dimensionServiceKey = DIMENSION_KEY;
|
||||
editor = new SettingsEditor(myDisposable, project, groups, configurable, filter, this::treeViewFactory, this::spotlightPainterFactory);
|
||||
isApplyButtonNeeded = true;
|
||||
isResetButtonNeeded = false;
|
||||
init(null, project);
|
||||
}
|
||||
|
||||
@@ -79,15 +79,15 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
@Nullable Configurable configurable,
|
||||
@Nullable String filter) {
|
||||
super(project, parentComponent, true, IdeModalityType.IDE);
|
||||
myDimensionServiceKey = DIMENSION_KEY;
|
||||
myEditor = new SettingsEditor(myDisposable, project, groups, configurable, filter, this::treeViewFactory, this::spotlightPainterFactory);
|
||||
myApplyButtonNeeded = true;
|
||||
myResetButtonNeeded = false;
|
||||
dimensionServiceKey = DIMENSION_KEY;
|
||||
editor = new SettingsEditor(myDisposable, project, groups, configurable, filter, this::treeViewFactory, this::spotlightPainterFactory);
|
||||
isApplyButtonNeeded = true;
|
||||
isResetButtonNeeded = false;
|
||||
init(null, project);
|
||||
}
|
||||
|
||||
protected final AbstractEditor getEditor() {
|
||||
return myEditor;
|
||||
return editor;
|
||||
}
|
||||
|
||||
protected @NotNull SettingsTreeView treeViewFactory(@NotNull SettingsFilter filter, @NotNull List<? extends ConfigurableGroup> groups) {
|
||||
@@ -132,17 +132,17 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
|
||||
@Override
|
||||
public void uiDataSnapshot(@NotNull DataSink sink) {
|
||||
DataSink.uiDataSnapshot(sink, myEditor);
|
||||
DataSink.uiDataSnapshot(sink, editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDimensionServiceKey() {
|
||||
return myDimensionServiceKey;
|
||||
return dimensionServiceKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myEditor.getPreferredFocusedComponent();
|
||||
return editor.getPreferredFocusedComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,7 +152,7 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myEditor;
|
||||
return editor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,8 +166,8 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
|
||||
@SuppressWarnings("unused") // used in Rider
|
||||
protected void tryAddOptionsListener(OptionsEditorColleague colleague) {
|
||||
if (myEditor instanceof SettingsEditor) {
|
||||
((SettingsEditor)myEditor).addOptionsListener(colleague);
|
||||
if (editor instanceof SettingsEditor) {
|
||||
((SettingsEditor)editor).addOptionsListener(colleague);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,12 +176,12 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
ArrayList<Action> actions = new ArrayList<>();
|
||||
actions.add(getOKAction());
|
||||
actions.add(getCancelAction());
|
||||
Action apply = myEditor.getApplyAction();
|
||||
if (apply != null && myApplyButtonNeeded) {
|
||||
Action apply = editor.getApplyAction();
|
||||
if (apply != null && isApplyButtonNeeded) {
|
||||
actions.add(new ApplyActionWrapper(apply));
|
||||
}
|
||||
Action reset = myEditor.getResetAction();
|
||||
if (reset != null && myResetButtonNeeded) {
|
||||
Action reset = editor.getResetAction();
|
||||
if (reset != null && isResetButtonNeeded) {
|
||||
actions.add(reset);
|
||||
}
|
||||
if (getHelpId() != null) {
|
||||
@@ -192,7 +192,7 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
|
||||
@Override
|
||||
protected @Nullable String getHelpId() {
|
||||
return myEditor.getHelpTopic();
|
||||
return editor.getHelpTopic();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,7 +205,7 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
if (window != null) {
|
||||
UIUtil.stopFocusedEditing(window);
|
||||
}
|
||||
if (myEditor.apply()) {
|
||||
if (editor.apply()) {
|
||||
if (scheduleSave) {
|
||||
SaveAndSyncHandler.getInstance().scheduleSave(new SaveAndSyncHandler.SaveTask(null, /* forceSavingAllSettings = */ true));
|
||||
}
|
||||
@@ -216,7 +216,7 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
@Override
|
||||
public void doCancelAction(AWTEvent source) {
|
||||
if (source instanceof KeyEvent || source instanceof ActionEvent) {
|
||||
if (!myEditor.cancel(source)) {
|
||||
if (!editor.cancel(source)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -257,7 +257,7 @@ public class SettingsDialog extends DialogWrapper implements UiCompatibleDataPro
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
delegate.actionPerformed(e);
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(SettingsDialogListener.getTOPIC()).afterApply(myEditor);
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(SettingsDialogListener.getTOPIC()).afterApply(editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -60,9 +60,9 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
private final PropertiesComponent myProperties;
|
||||
private final Settings mySettings;
|
||||
private final SettingsSearch mySearch;
|
||||
private final SettingsFilter myFilter;
|
||||
private final SettingsTreeView myTreeView;
|
||||
private final ConfigurableEditor myEditor;
|
||||
private final SettingsFilter filter;
|
||||
private final SettingsTreeView treeView;
|
||||
private final ConfigurableEditor editor;
|
||||
private final OnePixelSplitter mySplitter;
|
||||
private final SpotlightPainter mySpotlightPainter;
|
||||
private final LoadingDecorator myLoadingDecorator;
|
||||
@@ -85,20 +85,20 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
mySettings = new Settings(groups) {
|
||||
@Override
|
||||
protected @NotNull Promise<? super Object> selectImpl(Configurable configurable) {
|
||||
myFilter.update(null);
|
||||
return myTreeView.select(configurable);
|
||||
SettingsEditor.this.filter.update(null);
|
||||
return treeView.select(configurable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Configurable getConfigurableWithInitializedUiComponentImpl(@Nullable Configurable configurable,
|
||||
boolean initializeUiComponentIfNotYet) {
|
||||
JComponent content = myEditor.getContent(configurable);
|
||||
JComponent content = editor.getContent(configurable);
|
||||
if (!initializeUiComponentIfNotYet || content != null) {
|
||||
return content == null ? null : configurable;
|
||||
}
|
||||
|
||||
myEditor.readContent(configurable); // calls Configurable.createComponent() and Configurable.reset()
|
||||
|
||||
// calls Configurable.createComponent() and Configurable.reset()
|
||||
editor.readContent(configurable);
|
||||
return configurable;
|
||||
}
|
||||
|
||||
@@ -109,23 +109,24 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@Override
|
||||
protected void setSearchText(String search) {
|
||||
myFilter.update(search);
|
||||
SettingsEditor.this.filter.update(search);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revalidate() {
|
||||
myEditor.requestUpdate();
|
||||
editor.requestUpdate();
|
||||
}
|
||||
};
|
||||
mySearch = new SettingsSearch() {
|
||||
@Override
|
||||
void onTextKeyEvent(KeyEvent event) {
|
||||
myTreeView.getTree().processKeyEvent(event);
|
||||
treeView.getTree().processKeyEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
JPanel searchPanel = new JPanel(new VerticalLayout(0));
|
||||
searchPanel.add(VerticalLayout.CENTER, mySearch);
|
||||
myFilter = new SettingsFilter(project, groups, mySearch) {
|
||||
this.filter = new SettingsFilter(project, groups, mySearch) {
|
||||
@Override
|
||||
protected Configurable getConfigurable(SimpleNode node) {
|
||||
return SettingsTreeView.getConfigurable(node);
|
||||
@@ -133,12 +134,12 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@Override
|
||||
protected SimpleNode findNode(Configurable configurable) {
|
||||
return myTreeView.findNode(configurable);
|
||||
return treeView.findNode(configurable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSpotlight(boolean now) {
|
||||
if (!myDisposed && mySpotlightPainter != null) {
|
||||
if (!isDisposed && mySpotlightPainter != null) {
|
||||
if (!now) {
|
||||
mySpotlightPainter.updateLater();
|
||||
}
|
||||
@@ -148,7 +149,7 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
}
|
||||
};
|
||||
myFilter.myContext.addColleague(new OptionsEditorColleague() {
|
||||
this.filter.context.addColleague(new OptionsEditorColleague() {
|
||||
@Override
|
||||
public @NotNull Promise<? super Object> onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) {
|
||||
if (configurable != null) {
|
||||
@@ -157,7 +158,7 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
myLoadingDecorator.startLoading(false);
|
||||
}
|
||||
checkModified(oldConfigurable);
|
||||
Promise<? super Object> result = myEditor.select(configurable);
|
||||
Promise<? super Object> result = editor.select(configurable);
|
||||
result.onSuccess(it -> {
|
||||
updateController(configurable);
|
||||
//requestFocusToEditor(); // TODO
|
||||
@@ -178,11 +179,11 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@Override
|
||||
public @NotNull Promise<? super Object> onErrorsChanged() {
|
||||
return updateIfCurrent(myFilter.myContext.getCurrentConfigurable());
|
||||
return updateIfCurrent(SettingsEditor.this.filter.context.getCurrentConfigurable());
|
||||
}
|
||||
|
||||
private @NotNull Promise<? super Object> updateIfCurrent(@Nullable Configurable configurable) {
|
||||
if (configurable != null && configurable == myFilter.myContext.getCurrentConfigurable()) {
|
||||
if (configurable != null && configurable == SettingsEditor.this.filter.context.getCurrentConfigurable()) {
|
||||
updateStatus(configurable);
|
||||
return Promises.resolvedPromise();
|
||||
}
|
||||
@@ -191,27 +192,27 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
}
|
||||
});
|
||||
myTreeView = factory.createTreeView(myFilter, groups);
|
||||
myTreeView.getTree().addKeyListener(mySearch);
|
||||
myEditor = new ConfigurableEditor(this, null) {
|
||||
treeView = factory.createTreeView(this.filter, groups);
|
||||
treeView.getTree().addKeyListener(mySearch);
|
||||
editor = new ConfigurableEditor(this, null) {
|
||||
@Override
|
||||
boolean apply() {
|
||||
checkModified(myFilter.myContext.getCurrentConfigurable());
|
||||
if (myFilter.myContext.getModified().isEmpty()) {
|
||||
checkModified(SettingsEditor.this.filter.context.getCurrentConfigurable());
|
||||
if (SettingsEditor.this.filter.context.getModified().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Map<Configurable, ConfigurationException> map = new LinkedHashMap<>();
|
||||
for (Configurable configurable : myFilter.myContext.getModified()) {
|
||||
for (Configurable configurable : SettingsEditor.this.filter.context.getModified()) {
|
||||
ConfigurationException exception = ConfigurableEditor.apply(configurable);
|
||||
if (exception != null) {
|
||||
map.put(configurable, exception);
|
||||
}
|
||||
else if (!configurable.isModified()) {
|
||||
myFilter.myContext.fireModifiedRemoved(configurable, null);
|
||||
SettingsEditor.this.filter.context.fireModifiedRemoved(configurable, null);
|
||||
}
|
||||
}
|
||||
mySearch.updateToolTipText();
|
||||
myFilter.myContext.fireErrorsChanged(map, null);
|
||||
SettingsEditor.this.filter.context.fireErrorsChanged(map, null);
|
||||
if (!map.isEmpty()) {
|
||||
Configurable targetConfigurable = map.keySet().iterator().next();
|
||||
ConfigurationException exception = map.get(targetConfigurable);
|
||||
@@ -219,17 +220,17 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
if (originator != null) {
|
||||
targetConfigurable = originator;
|
||||
}
|
||||
myTreeView.select(targetConfigurable);
|
||||
treeView.select(targetConfigurable);
|
||||
return false;
|
||||
}
|
||||
updateStatus(myFilter.myContext.getCurrentConfigurable());
|
||||
updateStatus(SettingsEditor.this.filter.context.getCurrentConfigurable());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateCurrent(Configurable configurable, boolean reset) {
|
||||
if (reset && configurable != null) {
|
||||
myFilter.myContext.fireReset(configurable);
|
||||
SettingsEditor.this.filter.context.fireReset(configurable);
|
||||
}
|
||||
checkModified(configurable);
|
||||
}
|
||||
@@ -239,17 +240,17 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
mySettings.select(configurable);
|
||||
}
|
||||
};
|
||||
myEditor.setPreferredSize(JBUI.size(800, 600));
|
||||
myLoadingDecorator = new LoadingDecorator(myEditor, this, 10, true);
|
||||
editor.setPreferredSize(JBUI.size(800, 600));
|
||||
myLoadingDecorator = new LoadingDecorator(editor, this, 10, true);
|
||||
myLoadingDecorator.setOverlayBackground(LoadingDecorator.OVERLAY_BACKGROUND);
|
||||
myBanner = new Banner(myEditor.getResetAction());
|
||||
myBanner = new Banner(editor.getResetAction());
|
||||
searchPanel.setBorder(JBUI.Borders.empty(7, 5, 6, 5));
|
||||
myBanner.setBorder(JBUI.Borders.empty(11, 6, 0, 10));
|
||||
mySearch.setBackground(UIUtil.SIDE_PANEL_BACKGROUND);
|
||||
searchPanel.setBackground(UIUtil.SIDE_PANEL_BACKGROUND);
|
||||
JComponent left = new JPanel(new BorderLayout());
|
||||
left.add(BorderLayout.NORTH, searchPanel);
|
||||
left.add(BorderLayout.CENTER, myTreeView);
|
||||
left.add(BorderLayout.CENTER, treeView);
|
||||
JComponent right = new JPanel(new BorderLayout());
|
||||
right.add(BorderLayout.NORTH, withHistoryToolbar(myBanner));
|
||||
right.add(BorderLayout.CENTER, myLoadingDecorator.getComponent());
|
||||
@@ -263,10 +264,10 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
mySplitter.getDivider().setOpaque(false);
|
||||
}
|
||||
|
||||
mySpotlightPainter = spotlightPainterFactory.createSpotlightPainter(project, myEditor, this, (painter) -> {
|
||||
Configurable currentConfigurable = myFilter.myContext.getCurrentConfigurable();
|
||||
if (myTreeView.getTree().hasFocus() || mySearch.getTextEditor().hasFocus()) {
|
||||
painter.update(myFilter, currentConfigurable, myEditor.getContent(currentConfigurable));
|
||||
mySpotlightPainter = spotlightPainterFactory.createSpotlightPainter(project, editor, this, (painter) -> {
|
||||
Configurable currentConfigurable = this.filter.context.getCurrentConfigurable();
|
||||
if (treeView.getTree().hasFocus() || mySearch.getTextEditor().hasFocus()) {
|
||||
painter.update(this.filter, currentConfigurable, editor.getContent(currentConfigurable));
|
||||
}
|
||||
});
|
||||
add(BorderLayout.CENTER, mySplitter);
|
||||
@@ -279,13 +280,13 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
}
|
||||
|
||||
myTreeView.select(configurable).onProcessed(it -> myFilter.update(filter));
|
||||
treeView.select(configurable).onProcessed(it -> this.filter.update(filter));
|
||||
|
||||
Disposer.register(this, myTreeView);
|
||||
Disposer.register(this, treeView);
|
||||
installSpotlightRemover();
|
||||
//noinspection CodeBlock2Expr
|
||||
mySearch.getTextEditor().addActionListener(event -> {
|
||||
myTreeView.select(myFilter.myContext.getCurrentConfigurable()).onProcessed(o -> requestFocusToEditor());
|
||||
treeView.select(this.filter.context.getCurrentConfigurable()).onProcessed(o -> requestFocusToEditor());
|
||||
});
|
||||
|
||||
for (ConfigurableGroup group : groups) {
|
||||
@@ -298,24 +299,24 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void select(Configurable configurable) {
|
||||
myTreeView.select(configurable);
|
||||
myEditor.select(configurable);
|
||||
treeView.select(configurable);
|
||||
editor.select(configurable);
|
||||
updateController(configurable);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public @NotNull SettingsTreeView getTreeView() {
|
||||
return myTreeView;
|
||||
return treeView;
|
||||
}
|
||||
|
||||
private @NotNull MutableConfigurableGroup.Listener createReloadListener(List<? extends ConfigurableGroup> groups) {
|
||||
return new MutableConfigurableGroup.Listener() {
|
||||
@Override
|
||||
public void handleUpdate() {
|
||||
Configurable selected = myEditor.getConfigurable();
|
||||
Configurable selected = editor.getConfigurable();
|
||||
String id = selected instanceof SearchableConfigurable ? ((SearchableConfigurable)selected).getId() : null;
|
||||
myEditor.reload();
|
||||
myFilter.reload();
|
||||
editor.reload();
|
||||
filter.reload();
|
||||
myControllers.clear();
|
||||
myLastController = null;
|
||||
|
||||
@@ -323,8 +324,8 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
if (candidate == null) {
|
||||
candidate = ConfigurableVisitor.findById(PluginManagerConfigurable.ID, groups);
|
||||
}
|
||||
myEditor.init(candidate, false);
|
||||
myTreeView.reloadWithSelection(candidate);
|
||||
editor.init(candidate, false);
|
||||
treeView.reloadWithSelection(candidate);
|
||||
mySettings.reload();
|
||||
invalidate();
|
||||
repaint();
|
||||
@@ -333,7 +334,7 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
|
||||
private void requestFocusToEditor() {
|
||||
JComponent component = myEditor.getPreferredFocusedComponent();
|
||||
JComponent component = editor.getPreferredFocusedComponent();
|
||||
if (component != null) {
|
||||
IdeFocusManager.findInstanceByComponent(component).requestFocus(component, true);
|
||||
}
|
||||
@@ -344,7 +345,7 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
final Component comp = e.getOppositeComponent();
|
||||
if (comp == mySearch.getTextEditor() || comp == myTreeView.getTree()) {
|
||||
if (comp == mySearch.getTextEditor() || comp == treeView.getTree()) {
|
||||
return;
|
||||
}
|
||||
mySpotlightPainter.update(null, null, null);
|
||||
@@ -357,7 +358,7 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
}
|
||||
};
|
||||
myTreeView.getTree().addFocusListener(spotlightRemover);
|
||||
treeView.getTree().addFocusListener(spotlightRemover);
|
||||
mySearch.getTextEditor().addFocusListener(spotlightRemover);
|
||||
}
|
||||
|
||||
@@ -406,7 +407,7 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@Override
|
||||
Action getApplyAction() {
|
||||
return myEditor.getApplyAction();
|
||||
return editor.getApplyAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -416,29 +417,29 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@Override
|
||||
String getHelpTopic() {
|
||||
Configurable configurable = myFilter.myContext.getCurrentConfigurable();
|
||||
Configurable configurable = filter.context.getCurrentConfigurable();
|
||||
while (configurable != null) {
|
||||
String topic = configurable.getHelpTopic();
|
||||
if (topic != null) {
|
||||
return topic;
|
||||
}
|
||||
configurable = myFilter.myContext.getParentConfigurable(configurable);
|
||||
configurable = filter.context.getParentConfigurable(configurable);
|
||||
}
|
||||
return "preferences";
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean apply() {
|
||||
return myEditor.apply();
|
||||
return editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean cancel(AWTEvent source) {
|
||||
if (source instanceof KeyEvent && myFilter.myContext.isHoldingFilter()) {
|
||||
if (source instanceof KeyEvent && filter.context.isHoldingFilter()) {
|
||||
mySearch.setText("");
|
||||
return false;
|
||||
}
|
||||
for (Configurable configurable : myFilter.myContext.getModified()) {
|
||||
for (Configurable configurable : filter.context.getModified()) {
|
||||
configurable.cancel();
|
||||
}
|
||||
return super.cancel(source);
|
||||
@@ -446,30 +447,30 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
@Override
|
||||
JComponent getPreferredFocusedComponent() {
|
||||
return myTreeView != null ? myTreeView.getTree() : myEditor;
|
||||
return treeView != null ? treeView.getTree() : editor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Collection<@NlsContexts.ConfigurableName String> getPathNames() {
|
||||
return myTreeView == null ? null : myTreeView.getPathNames(myFilter.myContext.getCurrentConfigurable());
|
||||
return treeView == null ? null : treeView.getPathNames(filter.context.getCurrentConfigurable());
|
||||
}
|
||||
|
||||
public void addOptionsListener(OptionsEditorColleague colleague) {
|
||||
myFilter.myContext.addColleague(colleague);
|
||||
filter.context.addColleague(colleague);
|
||||
}
|
||||
|
||||
void updateStatus(Configurable configurable) {
|
||||
myFilter.updateSpotlight(configurable == null);
|
||||
if (myEditor != null) {
|
||||
ConfigurationException exception = myFilter.myContext.getErrors().get(configurable);
|
||||
myEditor.getApplyAction().setEnabled(!myFilter.myContext.getModified().isEmpty());
|
||||
myEditor.getResetAction().setEnabled(myFilter.myContext.isModified(configurable) || exception != null);
|
||||
myEditor.setError(exception);
|
||||
myEditor.revalidate();
|
||||
filter.updateSpotlight(configurable == null);
|
||||
if (editor != null) {
|
||||
ConfigurationException exception = filter.context.getErrors().get(configurable);
|
||||
editor.getApplyAction().setEnabled(!filter.context.getModified().isEmpty());
|
||||
editor.getResetAction().setEnabled(filter.context.isModified(configurable) || exception != null);
|
||||
editor.setError(exception);
|
||||
editor.revalidate();
|
||||
}
|
||||
if (configurable != null) {
|
||||
EdtScheduler.getInstance().schedule(300, () -> {
|
||||
if (!myDisposed && mySpotlightPainter != null) {
|
||||
if (!isDisposed && mySpotlightPainter != null) {
|
||||
mySpotlightPainter.updateNow();
|
||||
}
|
||||
});
|
||||
@@ -477,9 +478,9 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
|
||||
private void updateController(@Nullable Configurable configurable) {
|
||||
Project project = myTreeView.findConfigurableProject(configurable);
|
||||
Project project = treeView.findConfigurableProject(configurable);
|
||||
myBanner.setProjectText(project != null ? getProjectText(project) : null);
|
||||
myBanner.setText(myTreeView.getPathNames(configurable));
|
||||
myBanner.setText(treeView.getPathNames(configurable));
|
||||
|
||||
if (myLastController != null) {
|
||||
myLastController.setBanner(null);
|
||||
@@ -494,10 +495,10 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
}
|
||||
|
||||
void checkModified(Configurable configurable) {
|
||||
Configurable parent = myFilter.myContext.getParentConfigurable(configurable);
|
||||
Configurable parent = filter.context.getParentConfigurable(configurable);
|
||||
if (ConfigurableWrapper.hasOwnContent(parent)) {
|
||||
checkModifiedForItem(parent);
|
||||
for (Configurable child : myFilter.myContext.getChildren(parent)) {
|
||||
for (Configurable child : filter.context.getChildren(parent)) {
|
||||
checkModifiedForItem(child);
|
||||
}
|
||||
}
|
||||
@@ -509,9 +510,9 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
private void checkModifiedForItem(final Configurable configurable) {
|
||||
if (configurable != null) {
|
||||
JComponent component = myEditor.getContent(configurable);
|
||||
JComponent component = editor.getContent(configurable);
|
||||
if (component == null && ConfigurableWrapper.hasOwnContent(configurable)) {
|
||||
component = myEditor.readContent(configurable);
|
||||
component = editor.readContent(configurable);
|
||||
}
|
||||
if (component != null) {
|
||||
checkModifiedInternal(configurable);
|
||||
@@ -521,10 +522,10 @@ public final class SettingsEditor extends AbstractEditor implements UiDataProvid
|
||||
|
||||
private void checkModifiedInternal(Configurable configurable) {
|
||||
if (configurable.isModified()) {
|
||||
myFilter.myContext.fireModifiedAdded(configurable, null);
|
||||
filter.context.fireModifiedAdded(configurable, null);
|
||||
}
|
||||
else if (!myFilter.myContext.getErrors().containsKey(configurable)) {
|
||||
myFilter.myContext.fireModifiedRemoved(configurable, null);
|
||||
else if (!filter.context.getErrors().containsKey(configurable)) {
|
||||
filter.context.fireModifiedRemoved(configurable, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,279 +1,249 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.options.newEditor;
|
||||
package com.intellij.openapi.options.newEditor
|
||||
|
||||
import com.intellij.ide.ui.search.ConfigurableHit;
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
|
||||
import com.intellij.internal.statistic.collectors.fus.ui.SettingsCounterUsagesCollector;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurableGroup;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
import com.intellij.openapi.options.ex.ConfigurableWrapper;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.LightColors;
|
||||
import com.intellij.ui.SearchTextField;
|
||||
import com.intellij.ui.speedSearch.ElementFilter;
|
||||
import com.intellij.ui.treeStructure.SimpleNode;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.ide.ui.search.ConfigurableHit
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrar
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl
|
||||
import com.intellij.internal.statistic.collectors.fus.ui.SettingsCounterUsagesCollector
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.components.serviceIfCreated
|
||||
import com.intellij.openapi.options.Configurable
|
||||
import com.intellij.openapi.options.ConfigurableGroup
|
||||
import com.intellij.openapi.options.SearchableConfigurable
|
||||
import com.intellij.openapi.options.UnnamedConfigurable
|
||||
import com.intellij.openapi.options.ex.ConfigurableWrapper
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.IdeFocusManager
|
||||
import com.intellij.ui.DocumentAdapter
|
||||
import com.intellij.ui.LightColors
|
||||
import com.intellij.ui.SearchTextField
|
||||
import com.intellij.ui.speedSearch.ElementFilter
|
||||
import com.intellij.ui.treeStructure.SimpleNode
|
||||
import com.intellij.util.Alarm
|
||||
import com.intellij.util.concurrency.AppExecutorUtil
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import javax.swing.event.DocumentEvent
|
||||
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
abstract class SettingsFilter @ApiStatus.Internal protected constructor(
|
||||
project: Project?,
|
||||
groups: List<ConfigurableGroup>,
|
||||
search: SearchTextField
|
||||
) : ElementFilter.Active.Impl<SimpleNode?>() {
|
||||
@JvmField
|
||||
internal val context: OptionsEditorContext = OptionsEditorContext()
|
||||
private val project: Project?
|
||||
|
||||
public abstract class SettingsFilter extends ElementFilter.Active.Impl<SimpleNode> {
|
||||
final OptionsEditorContext myContext = new OptionsEditorContext();
|
||||
private final @Nullable Project myProject;
|
||||
private val search: SearchTextField
|
||||
private val groups: List<ConfigurableGroup>
|
||||
|
||||
private final SearchTextField mySearch;
|
||||
private final List<? extends ConfigurableGroup> myGroups;
|
||||
private var filtered: Set<Configurable>? = null
|
||||
private var hits: ConfigurableHit? = null
|
||||
|
||||
private Set<Configurable> myFiltered;
|
||||
private ConfigurableHit myHits;
|
||||
private var isUpdateRejected = false
|
||||
private var isLastSelected: Configurable? = null
|
||||
|
||||
private boolean myUpdateRejected;
|
||||
private Configurable myLastSelected;
|
||||
@Volatile
|
||||
private var searchableOptionRegistrar: SearchableOptionsRegistrar? = null
|
||||
private val updatingAlarm = Alarm(if (project == null) ApplicationManager.getApplication() else project)
|
||||
|
||||
private volatile SearchableOptionsRegistrar searchableOptionRegistrar;
|
||||
private final Alarm myUpdatingAlarm;
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected SettingsFilter(@Nullable Project project, @NotNull List<? extends ConfigurableGroup> groups, SearchTextField search) {
|
||||
myUpdatingAlarm = new Alarm(project != null ? project : ApplicationManager.getApplication());
|
||||
SearchableOptionsRegistrarImpl optionRegistrar =
|
||||
(SearchableOptionsRegistrarImpl)ApplicationManager.getApplication().getServiceIfCreated(SearchableOptionsRegistrar.class);
|
||||
if (optionRegistrar == null || !optionRegistrar.isInitialized()) {
|
||||
init {
|
||||
val optionRegistrar = serviceIfCreated<SearchableOptionsRegistrar>() as SearchableOptionsRegistrarImpl?
|
||||
if (optionRegistrar == null || !optionRegistrar.isInitialized) {
|
||||
// if not yet computed, preload it to ensure that will be no delay on user typing
|
||||
AppExecutorUtil.getAppExecutorService().execute(() -> {
|
||||
SearchableOptionsRegistrarImpl r = (SearchableOptionsRegistrarImpl)SearchableOptionsRegistrar.getInstance();
|
||||
r.initialize();
|
||||
AppExecutorUtil.getAppExecutorService().execute {
|
||||
val r = SearchableOptionsRegistrar.getInstance() as SearchableOptionsRegistrarImpl
|
||||
r.initialize()
|
||||
// must be set only after initializing (to avoid concurrent modifications)
|
||||
searchableOptionRegistrar = r;
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
update(DocumentEvent.EventType.CHANGE, false, true);
|
||||
}, ModalityState.any(), project == null ? ApplicationManager.getApplication().getDisposed() : project.getDisposed());
|
||||
});
|
||||
searchableOptionRegistrar = r
|
||||
ApplicationManager.getApplication().invokeLater(Runnable {
|
||||
update(type = DocumentEvent.EventType.CHANGE, adjustSelection = false, now = true)
|
||||
}, ModalityState.any(), if (project == null) ApplicationManager.getApplication().getDisposed() else project.getDisposed())
|
||||
}
|
||||
}
|
||||
else {
|
||||
searchableOptionRegistrar = optionRegistrar;
|
||||
searchableOptionRegistrar = optionRegistrar
|
||||
}
|
||||
|
||||
myProject = project;
|
||||
myGroups = groups;
|
||||
mySearch = search;
|
||||
mySearch.addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(@NotNull DocumentEvent event) {
|
||||
update(event.getType(), true, false);
|
||||
this@SettingsFilter.project = project
|
||||
this@SettingsFilter.groups = groups
|
||||
this@SettingsFilter.search = search
|
||||
search.addDocumentListener(object : DocumentAdapter() {
|
||||
override fun textChanged(event: DocumentEvent) {
|
||||
update(type = event.type, adjustSelection = true, now = false)
|
||||
// request focus if needed on changing the filter text
|
||||
IdeFocusManager manager = IdeFocusManager.findInstanceByComponent(mySearch);
|
||||
if (manager.getFocusedDescendantFor(mySearch) == null) {
|
||||
manager.requestFocus(mySearch, true);
|
||||
val manager = IdeFocusManager.findInstanceByComponent(this@SettingsFilter.search)
|
||||
if (manager.getFocusedDescendantFor(this@SettingsFilter.search) == null) {
|
||||
manager.requestFocus(this@SettingsFilter.search, true)
|
||||
}
|
||||
}
|
||||
});
|
||||
mySearch.getTextEditor().addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent event) {
|
||||
if (!mySearch.getText().isEmpty()) {
|
||||
if (!myContext.isHoldingFilter()) {
|
||||
setHoldingFilter(true);
|
||||
})
|
||||
search.textEditor.addMouseListener(object : MouseAdapter() {
|
||||
override fun mousePressed(event: MouseEvent?) {
|
||||
if (!search.text.isEmpty()) {
|
||||
if (!context.isHoldingFilter) {
|
||||
setHoldingFilter(true)
|
||||
}
|
||||
if (!mySearch.getTextEditor().isFocusOwner()) {
|
||||
mySearch.selectText();
|
||||
if (!search.textEditor.isFocusOwner) {
|
||||
search.selectText()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected abstract Configurable getConfigurable(SimpleNode node);
|
||||
protected abstract fun getConfigurable(node: SimpleNode?): Configurable?
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected abstract SimpleNode findNode(Configurable configurable);
|
||||
protected abstract fun findNode(configurable: Configurable?): SimpleNode?
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected abstract void updateSpotlight(boolean now);
|
||||
protected abstract fun updateSpotlight(now: Boolean)
|
||||
|
||||
@Override
|
||||
public boolean shouldBeShowing(SimpleNode node) {
|
||||
if (myFiltered != null) {
|
||||
Configurable configurable = getConfigurable(node);
|
||||
if (configurable != null) {
|
||||
if (!myFiltered.contains(configurable)) {
|
||||
if (myHits != null) {
|
||||
Set<Configurable> configurables = myHits.getNameFullHits();
|
||||
while (node != null) {
|
||||
if (configurable != null) {
|
||||
if (configurables.contains(configurable)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
node = node.getParent();
|
||||
configurable = getConfigurable(node);
|
||||
override fun shouldBeShowing(node: SimpleNode?): Boolean {
|
||||
var node = node
|
||||
val filtered = filtered ?: return true
|
||||
var configurable = getConfigurable(node)
|
||||
if (configurable != null) {
|
||||
if (!filtered.contains(configurable)) {
|
||||
if (hits != null) {
|
||||
val configurables = hits!!.nameFullHits
|
||||
while (node != null) {
|
||||
if (configurable != null && configurables.contains(configurable)) {
|
||||
return true
|
||||
}
|
||||
node = node.parent
|
||||
configurable = getConfigurable(node)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
void setFilterText(@NotNull String text) {
|
||||
mySearch.setText(text);
|
||||
fun setFilterText(text: String) {
|
||||
search.text = text
|
||||
}
|
||||
|
||||
public boolean isEmptyFilter() {
|
||||
return StringUtil.isEmpty(mySearch.getText());
|
||||
}
|
||||
fun isEmptyFilter(): Boolean = search.text.isNullOrEmpty()
|
||||
|
||||
@NotNull
|
||||
@ApiStatus.Internal
|
||||
public String getFilterText() {
|
||||
String text = mySearch.getText();
|
||||
return text == null ? "" : text.trim();
|
||||
}
|
||||
fun getFilterText(): String = search.text?.trim() ?: ""
|
||||
|
||||
@NotNull
|
||||
@ApiStatus.Internal
|
||||
public String getSpotlightFilterText() {
|
||||
if (myHits != null) {
|
||||
return myHits.getSpotlightFilter();
|
||||
}
|
||||
return getFilterText();
|
||||
fun getSpotlightFilterText(): String = if (hits == null) getFilterText() else hits!!.spotlightFilter
|
||||
|
||||
private fun setHoldingFilter(holding: Boolean) {
|
||||
context.isHoldingFilter = holding
|
||||
updateSpotlight(false)
|
||||
}
|
||||
|
||||
private void setHoldingFilter(boolean holding) {
|
||||
myContext.setHoldingFilter(holding);
|
||||
updateSpotlight(false);
|
||||
}
|
||||
fun contains(configurable: Configurable): Boolean = hits != null && hits!!.nameHits.contains(configurable)
|
||||
|
||||
boolean contains(@NotNull Configurable configurable) {
|
||||
return myHits != null && myHits.getNameHits().contains(configurable);
|
||||
}
|
||||
|
||||
void update(@Nullable String text) {
|
||||
fun update(text: String?) {
|
||||
try {
|
||||
myUpdateRejected = true;
|
||||
mySearch.setText(text);
|
||||
isUpdateRejected = true
|
||||
search.text = text
|
||||
}
|
||||
finally {
|
||||
myUpdateRejected = false;
|
||||
isUpdateRejected = false
|
||||
}
|
||||
update(DocumentEvent.EventType.CHANGE, false, true);
|
||||
update(type = DocumentEvent.EventType.CHANGE, adjustSelection = false, now = true)
|
||||
}
|
||||
|
||||
private void update(@NotNull DocumentEvent.EventType type, boolean adjustSelection, boolean now) {
|
||||
myUpdatingAlarm.cancelAllRequests();
|
||||
myUpdatingAlarm.addRequest(() -> {
|
||||
SearchableOptionsRegistrar registrar = searchableOptionRegistrar;
|
||||
if (registrar != null) update(registrar, type, adjustSelection, now);
|
||||
}, 100, ModalityState.any());
|
||||
private fun update(type: DocumentEvent.EventType, adjustSelection: Boolean, now: Boolean) {
|
||||
updatingAlarm.cancelAllRequests()
|
||||
updatingAlarm.addRequest(Runnable {
|
||||
val registrar = searchableOptionRegistrar
|
||||
if (registrar != null) update(registrar, type, adjustSelection, now)
|
||||
}, 100, ModalityState.any())
|
||||
}
|
||||
|
||||
private void update(@NotNull SearchableOptionsRegistrar optionRegistrar, @NotNull DocumentEvent.EventType type, boolean adjustSelection, boolean now) {
|
||||
if (myUpdateRejected) {
|
||||
return;
|
||||
private fun update(optionRegistrar: SearchableOptionsRegistrar, type: DocumentEvent.EventType, adjustSelection: Boolean, now: Boolean) {
|
||||
if (isUpdateRejected) {
|
||||
return
|
||||
}
|
||||
|
||||
String text = getFilterText();
|
||||
val text = getFilterText()
|
||||
if (text.isEmpty()) {
|
||||
myContext.setHoldingFilter(false);
|
||||
myHits = null;
|
||||
myFiltered = null;
|
||||
context.isHoldingFilter = false
|
||||
hits = null
|
||||
filtered = null
|
||||
}
|
||||
else {
|
||||
myContext.setHoldingFilter(true);
|
||||
myHits = optionRegistrar.getConfigurables(myGroups, type, null, text, myProject);
|
||||
myFiltered = myHits.getAll();
|
||||
context.isHoldingFilter = true
|
||||
hits = optionRegistrar.getConfigurables(groups, type, null, text, project)
|
||||
filtered = hits!!.all
|
||||
}
|
||||
mySearch.getTextEditor().setBackground(myFiltered != null && myFiltered.isEmpty()
|
||||
? LightColors.RED
|
||||
: UIUtil.getTextFieldBackground());
|
||||
search.textEditor.setBackground(if (filtered != null && filtered!!.isEmpty())LightColors.RED else UIUtil.getTextFieldBackground())
|
||||
|
||||
|
||||
Configurable current = myContext.getCurrentConfigurable();
|
||||
val current = context.currentConfigurable
|
||||
var shouldMoveSelection = hits == null || !hits!!.nameFullHits.contains(current) && !hits!!.contentHits.contains(current)
|
||||
|
||||
boolean shouldMoveSelection = myHits == null || !myHits.getNameFullHits().contains(current) &&
|
||||
!myHits.getContentHits().contains(current);
|
||||
|
||||
if (shouldMoveSelection && type != DocumentEvent.EventType.INSERT && (myFiltered == null || myFiltered.contains(current))) {
|
||||
shouldMoveSelection = false;
|
||||
if (shouldMoveSelection && type != DocumentEvent.EventType.INSERT && (filtered == null || filtered!!.contains(current))) {
|
||||
shouldMoveSelection = false
|
||||
}
|
||||
|
||||
Configurable candidate = adjustSelection ? current : null;
|
||||
if (shouldMoveSelection && myHits != null) {
|
||||
if (!myHits.getNameHits().isEmpty()) {
|
||||
candidate = findConfigurable(myHits.getNameHits(), myHits.getNameFullHits());
|
||||
var candidate = if (adjustSelection) current else null
|
||||
if (shouldMoveSelection && hits != null) {
|
||||
if (!hits!!.nameHits.isEmpty()) {
|
||||
candidate = findConfigurable(hits!!.nameHits, hits!!.nameFullHits)
|
||||
}
|
||||
else if (!myHits.getContentHits().isEmpty()) {
|
||||
candidate = findConfigurable(myHits.getContentHits(), null);
|
||||
else if (!hits!!.contentHits.isEmpty()) {
|
||||
candidate = findConfigurable(hits!!.contentHits, null)
|
||||
}
|
||||
}
|
||||
updateSpotlight(false);
|
||||
updateSpotlight(false)
|
||||
|
||||
if ((myFiltered == null || !myFiltered.isEmpty()) && candidate == null && myLastSelected != null) {
|
||||
candidate = myLastSelected;
|
||||
myLastSelected = null;
|
||||
if ((filtered == null || !filtered!!.isEmpty()) && candidate == null && isLastSelected != null) {
|
||||
candidate = isLastSelected
|
||||
isLastSelected = null
|
||||
}
|
||||
if (candidate == null && current != null) {
|
||||
myLastSelected = current;
|
||||
isLastSelected = current
|
||||
}
|
||||
|
||||
if (myFiltered != null &&
|
||||
candidate != null) {
|
||||
SettingsCounterUsagesCollector.SEARCH.log(getUnnamedConfigurable(candidate).getClass(),
|
||||
myFiltered.size(),
|
||||
text.length());
|
||||
if (filtered != null && candidate != null) {
|
||||
SettingsCounterUsagesCollector.SEARCH.log(getUnnamedConfigurable(candidate).javaClass, filtered!!.size, text.length)
|
||||
}
|
||||
|
||||
SimpleNode node = !adjustSelection ? null : findNode(candidate);
|
||||
fireUpdate(node, adjustSelection, now);
|
||||
val node = if (adjustSelection) findNode(candidate) else null
|
||||
fireUpdate(node, adjustSelection, now)
|
||||
}
|
||||
|
||||
private static @NotNull UnnamedConfigurable getUnnamedConfigurable(@NotNull Configurable candidate) {
|
||||
return candidate instanceof ConfigurableWrapper ?
|
||||
((ConfigurableWrapper)candidate).getConfigurable() :
|
||||
candidate;
|
||||
}
|
||||
|
||||
private static Configurable findConfigurable(Set<? extends Configurable> configurables, Set<? extends Configurable> hits) {
|
||||
Configurable candidate = null;
|
||||
for (Configurable configurable : configurables) {
|
||||
if (hits != null && hits.contains(configurable)) {
|
||||
return configurable;
|
||||
}
|
||||
if (candidate == null && !isEmptyParent(configurable)) {
|
||||
candidate = configurable;
|
||||
}
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
private static boolean isEmptyParent(Configurable configurable) {
|
||||
SearchableConfigurable.Parent parent = ConfigurableWrapper.cast(SearchableConfigurable.Parent.class, configurable);
|
||||
return parent != null && !parent.hasOwnContent();
|
||||
}
|
||||
|
||||
void reload() {
|
||||
myLastSelected = null;
|
||||
myFiltered = null;
|
||||
myHits = null;
|
||||
mySearch.setText("");
|
||||
myContext.reload();
|
||||
fun reload() {
|
||||
isLastSelected = null
|
||||
filtered = null
|
||||
hits = null
|
||||
search.text = ""
|
||||
context.reload()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnnamedConfigurable(candidate: Configurable): UnnamedConfigurable {
|
||||
return if (candidate is ConfigurableWrapper) candidate.getConfigurable() else candidate
|
||||
}
|
||||
|
||||
private fun findConfigurable(configurables: Set<Configurable>, hits: Set<Configurable>?): Configurable? {
|
||||
var candidate: Configurable? = null
|
||||
for (configurable in configurables) {
|
||||
if (hits != null && hits.contains(configurable)) {
|
||||
return configurable
|
||||
}
|
||||
if (candidate == null && !isEmptyParent(configurable)) {
|
||||
candidate = configurable
|
||||
}
|
||||
}
|
||||
return candidate
|
||||
}
|
||||
|
||||
private fun isEmptyParent(configurable: Configurable?): Boolean {
|
||||
val parent = ConfigurableWrapper.cast(SearchableConfigurable.Parent::class.java, configurable)
|
||||
return parent != null && !parent.hasOwnContent()
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab
|
||||
}
|
||||
|
||||
private @NotNull Promise<? super Object> fireSelected(Configurable configurable) {
|
||||
return myFilter.myContext.fireSelected(configurable, this);
|
||||
return myFilter.context.fireSelected(configurable, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -564,7 +564,7 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab
|
||||
SimpleNode[] result = new SimpleNode[configurables.length];
|
||||
for (int i = 0; i < configurables.length; i++) {
|
||||
result[i] = new MyNode(this, configurables[i], myLevel + 1);
|
||||
myFilter.myContext.registerKid(myConfigurable, configurables[i]);
|
||||
myFilter.context.registerKid(myConfigurable, configurables[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -637,10 +637,10 @@ public class SettingsTreeView extends JComponent implements Accessible, Disposab
|
||||
myTextLabel.setForeground(selected ? UIUtil.getTreeSelectionForeground(true) : UIUtil.getTreeForeground());
|
||||
if (!selected && node != null) {
|
||||
Configurable configurable = node.myConfigurable;
|
||||
if (myFilter.myContext.getErrors().containsKey(configurable)) {
|
||||
if (myFilter.context.getErrors().containsKey(configurable)) {
|
||||
myTextLabel.setForeground(WRONG_CONTENT);
|
||||
}
|
||||
else if (myFilter.myContext.getModified().contains(configurable)) {
|
||||
else if (myFilter.context.getModified().contains(configurable)) {
|
||||
myTextLabel.setForeground(MODIFIED_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user