diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java index 3c539981df84..60177087d9dd 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereManagerImpl.java @@ -34,6 +34,7 @@ public class SearchEverywhereManagerImpl implements SearchEverywhereManager { private JBPopup myBalloon; private SearchEverywhereUI mySearchEverywhereUI; + private Dimension myBalloonFullSize; private final SearchHistoryList myHistoryList = new SearchHistoryList(); private HistoryIterator myHistoryIterator; @@ -88,14 +89,12 @@ public class SearchEverywhereManagerImpl implements SearchEverywhereManager { myBalloon = JBPopupFactory.getInstance().createComponentPopupBuilder(mySearchEverywhereUI, mySearchEverywhereUI.getSearchField()) .setProject(myProject) - .setResizable(false) .setModalContext(false) .setCancelOnClickOutside(true) .setRequestFocus(true) .setCancelKeyEnabled(false) .setCancelCallback(() -> { saveSearchText(); - saveLocation(); return true; }) .addUserData("SIMPLE_WINDOW") @@ -108,22 +107,51 @@ public class SearchEverywhereManagerImpl implements SearchEverywhereManager { if (project != null) { Disposer.register(project, myBalloon); } - myBalloon.pack(true, true); + + Dimension size = mySearchEverywhereUI.getMinimumSize(); + myBalloon.setMinimumSize(withInsets(size)); myProject.putUserData(SEARCH_EVERYWHERE_POPUP, myBalloon); Disposer.register(myBalloon, () -> { + saveSize(); myProject.putUserData(SEARCH_EVERYWHERE_POPUP, null); mySearchEverywhereUI = null; myBalloon = null; + myBalloonFullSize = null; }); - if (project != null) { - myBalloon.showCenteredInCurrentWindow(project); - } else { - myBalloon.showInFocusCenter(); + calcPositionAndShow(project, myBalloon); + if (mySearchEverywhereUI.getViewType() == SearchEverywhereUI.ViewType.SHORT) { + myBalloonFullSize = DimensionService.getInstance().getSize(LOCATION_SETTINGS_KEY, project); + myBalloon.pack(false, true); } } + private void calcPositionAndShow(Project project, JBPopup balloon) { + Point savedLocation = DimensionService.getInstance().getLocation(LOCATION_SETTINGS_KEY, project); + + if (project != null) { + balloon.showCenteredInCurrentWindow(project); + } else { + balloon.showInFocusCenter(); + } + + //for first show and short mode popup should be shifted to the top screen half + if (savedLocation == null && mySearchEverywhereUI.getViewType() == SearchEverywhereUI.ViewType.SHORT) { + Point location = balloon.getLocationOnScreen(); + location.y /= 2; + balloon.setLocation(location); + } + } + + private Dimension withInsets(Dimension size) { + Insets insets = myBalloon.getContent().getInsets(); + return new Dimension( + size.width + insets.left + insets.right, + size.height + insets.top + insets.bottom + ); + } + @Override public boolean isShown() { return mySearchEverywhereUI != null && myBalloon != null && !myBalloon.isDisposed(); @@ -167,6 +195,22 @@ public class SearchEverywhereManagerImpl implements SearchEverywhereManager { } }); + view.addViewTypeListener(viewType -> { + if (!isShown()) { + return; + } + + if (viewType == SearchEverywhereUI.ViewType.SHORT) { + myBalloonFullSize = myBalloon.getSize(); + myBalloon.pack(false, true); + } else { + if (myBalloonFullSize == null) { + myBalloonFullSize = withInsets(mySearchEverywhereUI.getPreferredSize()); + } + myBalloon.setSize(myBalloonFullSize); + } + }); + DumbAwareAction.create(__ -> showHistoryItem(true)) .registerCustomShortcutSet(SearchTextField.SHOW_HISTORY_SHORTCUT, view); @@ -194,16 +238,10 @@ public class SearchEverywhereManagerImpl implements SearchEverywhereManager { } } - private void saveLocation() { - if (!isShown()) { - return; + private void saveSize() { + if (mySearchEverywhereUI.getViewType() == SearchEverywhereUI.ViewType.SHORT) { + DimensionService.getInstance().setSize(LOCATION_SETTINGS_KEY, myBalloonFullSize, myProject); } - - Dimension size = myBalloon.getSize(); - Point location = myBalloon.getLocationOnScreen(); - DimensionService service = DimensionService.getInstance(); - service.setSize(LOCATION_SETTINGS_KEY, size); - service.setLocation(LOCATION_SETTINGS_KEY, location); } private void showHistoryItem(boolean next) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java index 4d91f852db5a..3d25426b2b29 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/SearchEverywhereUI.java @@ -55,6 +55,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; import javax.swing.event.DocumentEvent; +import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; import java.util.*; @@ -78,6 +79,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, private SETab mySelectedTab; private final JTextField mySearchField; + private final JPanel suggestionsPanel; private final JCheckBox myNonProjectCB; private final List myTabs = new ArrayList<>(); @@ -97,13 +99,13 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, private final Alarm emptyListAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, ApplicationManager.getApplication()); private Runnable searchFinishedHandler = () -> {}; + private final List myViewTypeListeners = new ArrayList<>(); + private ViewType myViewType = ViewType.SHORT; public SearchEverywhereUI(Project project, List serviceContributors, List contributors, Map> filters) { - withMinimumWidth(670); - withPreferredWidth(670); withBackground(JBUI.CurrentTheme.SearchEverywhere.dialogBackground()); myProject = project; @@ -118,7 +120,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, JPanel contributorsPanel = createTabPanel(contributors); JPanel settingsPanel = createSettingsPanel(); mySearchField = createSearchField(); - JPanel suggestionsPanel = createSuggestionsPanel(); + suggestionsPanel = createSuggestionsPanel(); myResultsList.setModel(myListModel); myResultsList.setFocusable(false); @@ -154,6 +156,24 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, initSearchActions(); } + @Override + public Dimension getMinimumSize() { + return calcPrefSize(ViewType.SHORT); + } + + @Override + public Dimension getPreferredSize() { + return calcPrefSize(myViewType); + } + + private Dimension calcPrefSize(ViewType viewType) { + Dimension size = super.getPreferredSize(); + if (viewType == ViewType.SHORT) { + size.height -= suggestionsPanel.getPreferredSize().height; + } + return size; + } + private JPanel createSuggestionsPanel() { JPanel pnl = new JPanel(new BorderLayout()); pnl.setOpaque(false); @@ -180,6 +200,13 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, return pnl; } + private void updateViewType(ViewType viewType) { + if (myViewType != viewType) { + myViewType = viewType; + myViewTypeListeners.forEach(listener -> listener.suggestionsShown(viewType)); + } + } + public JTextField getSearchField() { return mySearchField; } @@ -469,6 +496,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, } String pattern = getSearchPattern(); + updateViewType(pattern.isEmpty() ? ViewType.SHORT : ViewType.FULL); String matcherString = mySelectedTab.getContributor() .map(contributor -> contributor.filterControlSymbols(pattern)) .orElse(pattern); @@ -476,8 +504,6 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, MinusculeMatcher matcher = NameUtil.buildMatcher("*" + matcherString, NameUtil.MatchingCaseSensitivity.NONE); MatcherHolder.associateMatcher(myResultsList, matcher); - //assert project != null; - //myRenderer.myProject = project; synchronized (myWorkerRestartRequestLock) { // this lock together with RestartRequestId should be enough to prevent two CalcThreads running at the same time final int currentRestartRequest = ++myCalcThreadRestartRequestId; myCurrentWorker.doWhenProcessed(() -> { @@ -493,8 +519,11 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, } } + @NotNull private String getSearchPattern() { - return mySearchField != null ? mySearchField.getText() : ""; + return Optional.ofNullable(mySearchField) + .map(JTextComponent::getText) + .orElse(""); } private void initSearchActions() { @@ -541,8 +570,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, @Override protected void textChanged(DocumentEvent e) { String newSearchString = getSearchPattern(); - if (nonProjectCheckBoxAutoSet && isUseNonProjectItems() - && newSearchString != null && !newSearchString.contains(notFoundString)) { + if (nonProjectCheckBoxAutoSet && isUseNonProjectItems() && !newSearchString.contains(notFoundString)) { doSetUseNonProjectItems(false, true); } rebuildList(); @@ -671,7 +699,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, private final ActionCallback myDone = new ActionCallback(); private final SearchEverywhereContributor contributorToExpand; - public CalcThread(@NotNull String pattern, @Nullable SearchEverywhereContributor expand) { + private CalcThread(@NotNull String pattern, @Nullable SearchEverywhereContributor expand) { this.pattern = pattern; contributorToExpand = expand; } @@ -761,6 +789,7 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, .filter(o -> !myListModel.contains(o)) .collect(Collectors.toList()); if (!itemsToAdd.isEmpty()) { + updateViewType(ViewType.FULL); myListModel.addElements(itemsToAdd, contributor, results.hasMoreItems()); ScrollingUtil.ensureSelectionExists(myResultsList); } @@ -1242,6 +1271,24 @@ public class SearchEverywhereUI extends BorderLayoutPanel implements Disposable, } } + public ViewType getViewType() { + return myViewType; + } + + public enum ViewType {FULL, SHORT} + + public interface ViewTypeListener { + void suggestionsShown(ViewType viewType); + } + + public void addViewTypeListener(ViewTypeListener listener) { + myViewTypeListeners.add(listener); + } + + public void removeViewTypeListener(ViewTypeListener listener) { + myViewTypeListeners.remove(listener); + } + private static JLabel groupInfoLabel(String text) { JLabel label = new JLabel(text); label.setForeground(UIUtil.getLabelDisabledForeground());