mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
added option to show list for empty pattern after completion key stroke (PY-384)
This commit is contained in:
@@ -74,7 +74,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ChooseByNameBase{
|
||||
public abstract class ChooseByNameBase {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.ChooseByNameBase");
|
||||
|
||||
protected final Project myProject;
|
||||
@@ -86,11 +86,13 @@ public abstract class ChooseByNameBase{
|
||||
protected Component myPreviouslyFocusedComponent;
|
||||
|
||||
protected JPanelProvider myTextFieldPanel;// Located in the layered pane
|
||||
protected JTextField myTextField;
|
||||
protected MyTextField myTextField;
|
||||
private JPanel myCardContainer;
|
||||
private CardLayout myCard;
|
||||
protected JCheckBox myCheckBox;
|
||||
/** the tool area of the popup, it is just after card box */
|
||||
/**
|
||||
* the tool area of the popup, it is just after card box
|
||||
*/
|
||||
protected JComponent myToolArea;
|
||||
|
||||
protected JScrollPane myListScrollPane; // Located in the layered pane
|
||||
@@ -121,6 +123,7 @@ public abstract class ChooseByNameBase{
|
||||
private static final int REBUILD_DELAY = 300;
|
||||
|
||||
private final Alarm myHideAlarm = new Alarm();
|
||||
private boolean myShowListAfterCompletionKeyStroke = false;
|
||||
|
||||
private static class MatchesComparator implements Comparator<String> {
|
||||
private final String myOriginalPattern;
|
||||
@@ -158,18 +161,25 @@ public abstract class ChooseByNameBase{
|
||||
myPreselectInitialText = preselectInitialText;
|
||||
}
|
||||
|
||||
public void setShowListAfterCompletionKeyStroke(boolean showListAfterCompletionKeyStroke) {
|
||||
myShowListAfterCompletionKeyStroke = showListAfterCompletionKeyStroke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tool area. The method may be called only before invoke.
|
||||
*
|
||||
* @param toolArea a tool area component
|
||||
*/
|
||||
public void setToolArea(JComponent toolArea) {
|
||||
if(myCard != null) {
|
||||
if (myCard != null) {
|
||||
throw new IllegalStateException("Tool area is modifiable only before invoke()");
|
||||
}
|
||||
myToolArea = toolArea;
|
||||
}
|
||||
|
||||
public void invoke(final ChooseByNamePopupComponent.Callback callback, final ModalityState modalityState, boolean allowMultipleSelection) {
|
||||
public void invoke(final ChooseByNamePopupComponent.Callback callback,
|
||||
final ModalityState modalityState,
|
||||
boolean allowMultipleSelection) {
|
||||
initUI(callback, modalityState, allowMultipleSelection);
|
||||
}
|
||||
|
||||
@@ -217,7 +227,7 @@ public abstract class ChooseByNameBase{
|
||||
}
|
||||
|
||||
public void registerHint(JBPopup h) {
|
||||
if (myHint != null && myHint.isVisible() && myHint != h){
|
||||
if (myHint != null && myHint.isVisible() && myHint != h) {
|
||||
myHint.cancel();
|
||||
}
|
||||
myHint = h;
|
||||
@@ -252,7 +262,7 @@ public abstract class ChooseByNameBase{
|
||||
public void updateHint(PsiElement element) {
|
||||
if (myHint == null || !myHint.isVisible()) return;
|
||||
final PopupUpdateProcessor updateProcessor = myHint.getUserData(PopupUpdateProcessor.class);
|
||||
if (updateProcessor != null){
|
||||
if (updateProcessor != null) {
|
||||
myHint.cancel();
|
||||
updateProcessor.updatePopup(element);
|
||||
}
|
||||
@@ -261,10 +271,12 @@ public abstract class ChooseByNameBase{
|
||||
|
||||
/**
|
||||
* @param callback
|
||||
* @param modalityState - if not null rebuilds list in given {@link ModalityState}
|
||||
* @param modalityState - if not null rebuilds list in given {@link ModalityState}
|
||||
* @param allowMultipleSelection
|
||||
*/
|
||||
protected void initUI(final ChooseByNamePopupComponent.Callback callback, final ModalityState modalityState, boolean allowMultipleSelection) {
|
||||
protected void initUI(final ChooseByNamePopupComponent.Callback callback,
|
||||
final ModalityState modalityState,
|
||||
boolean allowMultipleSelection) {
|
||||
myPreviouslyFocusedComponent = WindowManagerEx.getInstanceEx().getFocusedComponent(myProject);
|
||||
|
||||
myActionListener = callback;
|
||||
@@ -279,7 +291,7 @@ public abstract class ChooseByNameBase{
|
||||
hBox.add(label);
|
||||
}
|
||||
|
||||
myCard = new CardLayout();
|
||||
myCard = new CardLayout();
|
||||
myCardContainer = new JPanel(myCard);
|
||||
|
||||
final JPanel checkBoxPanel = new JPanel();
|
||||
@@ -287,17 +299,18 @@ public abstract class ChooseByNameBase{
|
||||
myCheckBox = new JCheckBox(myModel.getCheckBoxName());
|
||||
myCheckBox.setSelected(myModel.loadInitialCheckBoxState());
|
||||
|
||||
if (myModel.getPromptText() != null){
|
||||
if (myModel.getPromptText() != null) {
|
||||
checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.X_AXIS));
|
||||
checkBoxPanel.add (new JLabel (" ("));
|
||||
checkBoxPanel.add (myCheckBox);
|
||||
checkBoxPanel.add (new JLabel (")"));
|
||||
} else {
|
||||
checkBoxPanel.add(new JLabel(" ("));
|
||||
checkBoxPanel.add(myCheckBox);
|
||||
checkBoxPanel.add(new JLabel(")"));
|
||||
}
|
||||
else {
|
||||
checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.LINE_AXIS));
|
||||
checkBoxPanel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
|
||||
checkBoxPanel.add (new JLabel (")"));
|
||||
checkBoxPanel.add (myCheckBox);
|
||||
checkBoxPanel.add (new JLabel (" ("));
|
||||
checkBoxPanel.add(new JLabel(")"));
|
||||
checkBoxPanel.add(myCheckBox);
|
||||
checkBoxPanel.add(new JLabel(" ("));
|
||||
}
|
||||
checkBoxPanel.setVisible(myModel.getCheckBoxName() != null);
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
@@ -322,7 +335,7 @@ public abstract class ChooseByNameBase{
|
||||
//hBox.add(myCaseCheckBox);
|
||||
//hBox.add(myCamelCheckBox);
|
||||
}
|
||||
if(myToolArea != null) {
|
||||
if (myToolArea != null) {
|
||||
// if too area was set, add it to hbox
|
||||
hBox.add(myToolArea);
|
||||
}
|
||||
@@ -372,7 +385,8 @@ public abstract class ChooseByNameBase{
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
hideHint();
|
||||
}
|
||||
}
|
||||
@@ -417,7 +431,7 @@ public abstract class ChooseByNameBase{
|
||||
case KeyEvent.VK_ENTER:
|
||||
if (myList.getSelectedValue() == EXTRA_ELEM) {
|
||||
myMaximumListSizeLimit += MAXIMUM_LIST_SIZE_LIMIT;
|
||||
rebuildList(myList.getSelectedIndex(), REBUILD_DELAY, null, ModalityState.current());
|
||||
rebuildList(myList.getSelectedIndex(), REBUILD_DELAY, null, ModalityState.current(), e);
|
||||
e.consume();
|
||||
}
|
||||
break;
|
||||
@@ -445,7 +459,7 @@ public abstract class ChooseByNameBase{
|
||||
if (e.getClickCount() == 2) {
|
||||
if (myList.getSelectedValue() == EXTRA_ELEM) {
|
||||
myMaximumListSizeLimit += MAXIMUM_LIST_SIZE_LIMIT;
|
||||
rebuildList(myList.getSelectedIndex(), REBUILD_DELAY, null, ModalityState.current());
|
||||
rebuildList(myList.getSelectedIndex(), REBUILD_DELAY, null, ModalityState.current(), e);
|
||||
e.consume();
|
||||
}
|
||||
else {
|
||||
@@ -475,7 +489,7 @@ public abstract class ChooseByNameBase{
|
||||
showTextFieldPanel();
|
||||
|
||||
if (modalityState != null) {
|
||||
rebuildList(0, 0, null, modalityState);
|
||||
rebuildList(0, 0, null, modalityState, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,7 +505,7 @@ public abstract class ChooseByNameBase{
|
||||
*/
|
||||
public void rebuildList() {
|
||||
// TODO this method is public, because the chooser does not listed for the model.
|
||||
rebuildList(0, REBUILD_DELAY, null, ModalityState.current());
|
||||
rebuildList(0, REBUILD_DELAY, null, ModalityState.current(), null);
|
||||
}
|
||||
|
||||
private void updateDocumentation() {
|
||||
@@ -500,7 +514,8 @@ public abstract class ChooseByNameBase{
|
||||
if (hint != null) {
|
||||
if (element instanceof PsiElement) {
|
||||
myTextFieldPanel.updateHint((PsiElement)element);
|
||||
} else if (element instanceof DataProvider) {
|
||||
}
|
||||
else if (element instanceof DataProvider) {
|
||||
final Object o = ((DataProvider)element).getData(LangDataKeys.PSI_ELEMENT.getName());
|
||||
if (o instanceof PsiElement) {
|
||||
myTextFieldPanel.updateHint((PsiElement)o);
|
||||
@@ -590,7 +605,7 @@ public abstract class ChooseByNameBase{
|
||||
doClose(false);
|
||||
}
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW
|
||||
);
|
||||
|
||||
myList.registerKeyboardAction(new AbstractAction() {
|
||||
@@ -598,7 +613,7 @@ public abstract class ChooseByNameBase{
|
||||
doClose(false);
|
||||
}
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW
|
||||
);
|
||||
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(myTextField, true);
|
||||
@@ -627,9 +642,13 @@ public abstract class ChooseByNameBase{
|
||||
return layeredPane;
|
||||
}
|
||||
|
||||
private final Object myRebuildMutex = new Object ();
|
||||
private final Object myRebuildMutex = new Object();
|
||||
|
||||
protected void rebuildList(final int pos, final int delay, final Runnable postRunnable, final ModalityState modalityState) {
|
||||
protected void rebuildList(final int pos,
|
||||
final int delay,
|
||||
final Runnable postRunnable,
|
||||
final ModalityState modalityState,
|
||||
final @Nullable ComponentEvent e) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
myListIsUpToDate = false;
|
||||
myAlarm.cancelAllRequests();
|
||||
@@ -639,7 +658,8 @@ public abstract class ChooseByNameBase{
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
final String text = myTextField.getText();
|
||||
if (!isShowListForEmptyPattern() && (text == null || text.trim().length() == 0)) {
|
||||
if (!canShowListForEmptyPattern() &&
|
||||
(text == null || text.trim().length() == 0)) {
|
||||
myListModel.clear();
|
||||
hideList();
|
||||
myCard.show(myCardContainer, CHECK_BOX_CARD);
|
||||
@@ -684,6 +704,10 @@ public abstract class ChooseByNameBase{
|
||||
}, modalityState);
|
||||
}
|
||||
|
||||
private boolean isShowListAfterCompletionKeyStroke() {
|
||||
return myShowListAfterCompletionKeyStroke;
|
||||
}
|
||||
|
||||
private void cancelCalcElementsThread() {
|
||||
if (myCalcElementsThread != null) {
|
||||
myCalcElementsThread.cancel();
|
||||
@@ -768,7 +792,7 @@ public abstract class ChooseByNameBase{
|
||||
|
||||
@NonNls
|
||||
protected String statisticsContext() {
|
||||
return "choose_by_name#"+myModel.getPromptText()+"#"+ myCheckBox.isSelected() + "#" + myTextField.getText();
|
||||
return "choose_by_name#" + myModel.getPromptText() + "#" + myCheckBox.isSelected() + "#" + myTextField.getText();
|
||||
}
|
||||
|
||||
private String getQualifierPattern(String pattern) {
|
||||
@@ -858,10 +882,11 @@ public abstract class ChooseByNameBase{
|
||||
int pos = selectionPos == 0 ? detectBestStatisticalPosition() : selectionPos;
|
||||
ListScrollingUtil.selectItem(myList, Math.min(pos, myListModel.size() - 1));
|
||||
}
|
||||
|
||||
|
||||
if (!myCommands.isEmpty()) {
|
||||
myAlarm.addRequest(this, DELAY);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
doPostponedOkIfNeeded();
|
||||
}
|
||||
if (!myDisposedFlag) {
|
||||
@@ -885,7 +910,8 @@ public abstract class ChooseByNameBase{
|
||||
if (myPosponedOkAction != null) {
|
||||
if (success) {
|
||||
myPosponedOkAction.setDone();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
myPosponedOkAction.setRejected();
|
||||
}
|
||||
}
|
||||
@@ -935,11 +961,13 @@ public abstract class ChooseByNameBase{
|
||||
protected void choosenElementMightChange() {
|
||||
}
|
||||
|
||||
private final class MyTextField extends JTextField implements PopupOwner {
|
||||
protected final class MyTextField extends JTextField implements PopupOwner {
|
||||
private final KeyStroke myCompletionKeyStroke;
|
||||
private final KeyStroke forwardStroke;
|
||||
private final KeyStroke backStroke;
|
||||
|
||||
private boolean completionKeyStrokeHappened = false;
|
||||
|
||||
private MyTextField() {
|
||||
super(40);
|
||||
enableEvents(AWTEvent.KEY_EVENT_MASK);
|
||||
@@ -961,7 +989,9 @@ public abstract class ChooseByNameBase{
|
||||
|
||||
protected void processKeyEvent(KeyEvent e) {
|
||||
final KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
|
||||
|
||||
if (myCompletionKeyStroke != null && keyStroke.equals(myCompletionKeyStroke)) {
|
||||
completionKeyStrokeHappened = true;
|
||||
e.consume();
|
||||
final String pattern = myTextField.getText();
|
||||
final String oldText = myTextField.getText();
|
||||
@@ -972,7 +1002,7 @@ public abstract class ChooseByNameBase{
|
||||
fillInCommonPrefix(pattern);
|
||||
}
|
||||
};
|
||||
rebuildList(0, 0, postRunnable, ModalityState.current());
|
||||
rebuildList(0, 0, postRunnable, ModalityState.current(), e);
|
||||
return;
|
||||
}
|
||||
if (backStroke != null && keyStroke.equals(backStroke)) {
|
||||
@@ -983,7 +1013,7 @@ public abstract class ChooseByNameBase{
|
||||
final Pair<String, Integer> last = myHistory.remove(myHistory.size() - 1);
|
||||
myTextField.setText(last.first);
|
||||
myFuture.add(Pair.create(oldText, oldPos));
|
||||
rebuildList(0, 0, null, ModalityState.current());
|
||||
rebuildList(0, 0, null, ModalityState.current(), e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -995,7 +1025,7 @@ public abstract class ChooseByNameBase{
|
||||
final Pair<String, Integer> next = myFuture.remove(myFuture.size() - 1);
|
||||
myTextField.setText(next.first);
|
||||
myHistory.add(Pair.create(oldText, oldPos));
|
||||
rebuildList(0, 0, null, ModalityState.current());
|
||||
rebuildList(0, 0, null, ModalityState.current(), e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1017,7 +1047,7 @@ public abstract class ChooseByNameBase{
|
||||
final String oldText = myTextField.getText();
|
||||
final int oldPos = myList.getSelectedIndex();
|
||||
|
||||
String commonPrefix = null;
|
||||
String commonPrefix = null;
|
||||
if (!list.isEmpty()) {
|
||||
for (String name : list) {
|
||||
final String string = name.toLowerCase();
|
||||
@@ -1071,6 +1101,10 @@ public abstract class ChooseByNameBase{
|
||||
UISettings.setupAntialiasing(g);
|
||||
super.paintComponent(g);
|
||||
}
|
||||
|
||||
public boolean isCompletionKeyStroke() {
|
||||
return completionKeyStrokeHappened;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String EXTRA_ELEM = "...";
|
||||
@@ -1086,7 +1120,11 @@ public abstract class ChooseByNameBase{
|
||||
private volatile boolean myCancelled = false;
|
||||
private final boolean myCanCancel;
|
||||
|
||||
private CalcElementsThread(String pattern, boolean checkboxState, CalcElementsCallback callback, ModalityState modalityState, boolean canCancel) {
|
||||
private CalcElementsThread(String pattern,
|
||||
boolean checkboxState,
|
||||
CalcElementsCallback callback,
|
||||
ModalityState modalityState,
|
||||
boolean canCancel) {
|
||||
myPattern = pattern;
|
||||
myCheckboxState = checkboxState;
|
||||
myCallback = callback;
|
||||
@@ -1095,6 +1133,7 @@ public abstract class ChooseByNameBase{
|
||||
}
|
||||
|
||||
private final Alarm myShowCardAlarm = new Alarm();
|
||||
|
||||
public void run() {
|
||||
showCard(SEARCHING_CARD, 200);
|
||||
|
||||
@@ -1160,7 +1199,7 @@ public abstract class ChooseByNameBase{
|
||||
String qualifierPattern = getQualifierPattern(pattern);
|
||||
|
||||
boolean empty = namePattern.length() == 0 || namePattern.equals("@"); // TODO[yole]: remove implicit dependency
|
||||
if (empty && !isShowListForEmptyPattern()) return;
|
||||
if (empty && !canShowListForEmptyPattern()) return;
|
||||
|
||||
List<String> namesList = new ArrayList<String>();
|
||||
getNamesByPattern(myCheckboxState, this, namesList, namePattern);
|
||||
@@ -1188,7 +1227,7 @@ public abstract class ChooseByNameBase{
|
||||
for (Object element : sameNameElements) {
|
||||
elementsArray.add(element);
|
||||
if (elementsArray.size() >= myMaximumListSizeLimit) {
|
||||
overflow = true;
|
||||
overflow = true;
|
||||
break All;
|
||||
}
|
||||
}
|
||||
@@ -1225,7 +1264,7 @@ public abstract class ChooseByNameBase{
|
||||
answer.add(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return answer.isEmpty() ? Collections.singletonList(s) : answer;
|
||||
}
|
||||
|
||||
@@ -1234,14 +1273,15 @@ public abstract class ChooseByNameBase{
|
||||
if (name == null) return false;
|
||||
|
||||
final List<String> suspects = split(name);
|
||||
final List<Pair<String, NameUtil.Matcher>> patternsAndMatchers = ContainerUtil.map2List(split(qualifierPattern), new Function<String, Pair<String, NameUtil.Matcher>>() {
|
||||
public Pair<String, NameUtil.Matcher> fun(String s) {
|
||||
final String pattern = getNamePattern(s);
|
||||
final NameUtil.Matcher matcher = buildPatternMatcher(pattern);
|
||||
final List<Pair<String, NameUtil.Matcher>> patternsAndMatchers =
|
||||
ContainerUtil.map2List(split(qualifierPattern), new Function<String, Pair<String, NameUtil.Matcher>>() {
|
||||
public Pair<String, NameUtil.Matcher> fun(String s) {
|
||||
final String pattern = getNamePattern(s);
|
||||
final NameUtil.Matcher matcher = buildPatternMatcher(pattern);
|
||||
|
||||
return new Pair<String, NameUtil.Matcher>(pattern, matcher);
|
||||
}
|
||||
});
|
||||
return new Pair<String, NameUtil.Matcher>(pattern, matcher);
|
||||
}
|
||||
});
|
||||
|
||||
int matchPosition = 0;
|
||||
|
||||
@@ -1262,7 +1302,8 @@ public abstract class ChooseByNameBase{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Do nothing. No matches appears valid result for "bad" pattern
|
||||
return false;
|
||||
}
|
||||
@@ -1274,7 +1315,7 @@ public abstract class ChooseByNameBase{
|
||||
CalcElementsThread calcElementsThread,
|
||||
final List<String> list,
|
||||
String pattern) throws ProcessCanceledException {
|
||||
if (!isShowListForEmptyPattern()) {
|
||||
if (!canShowListForEmptyPattern()) {
|
||||
LOG.assertTrue(pattern.length() > 0);
|
||||
}
|
||||
|
||||
@@ -1300,6 +1341,14 @@ public abstract class ChooseByNameBase{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canShowListForEmptyPattern() {
|
||||
return isShowListForEmptyPattern() || (isShowListAfterCompletionKeyStroke() && lastKeyStrokeIsCompletion());
|
||||
}
|
||||
|
||||
protected boolean lastKeyStrokeIsCompletion() {
|
||||
return myTextField.isCompletionKeyStroke();
|
||||
}
|
||||
|
||||
private boolean matches(String pattern, NameUtil.Matcher matcher, String name) {
|
||||
boolean matches = false;
|
||||
if (name != null) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.regex.Pattern;
|
||||
public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNamePopupComponent{
|
||||
private static final Key<ChooseByNamePopup> CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY = new Key<ChooseByNamePopup>("ChooseByNamePopup");
|
||||
private Component myOldFocusOwner = null;
|
||||
private boolean myShowListForEmptyPattern = false;
|
||||
|
||||
private ChooseByNamePopup(final Project project, final ChooseByNameModel model, final ChooseByNamePopup oldPopup,
|
||||
final PsiElement context, @Nullable final String predefinedText) {
|
||||
@@ -56,7 +57,7 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
|
||||
super.initUI(callback, modalityState, allowMultipleSelection);
|
||||
//LaterInvocator.enterModal(myTextFieldPanel);
|
||||
if (myInitialText != null) {
|
||||
rebuildList(0, 0, null, ModalityState.current());
|
||||
rebuildList(0, 0, null, ModalityState.current(), null);
|
||||
}
|
||||
if (myOldFocusOwner != null){
|
||||
myPreviouslyFocusedComponent = myOldFocusOwner;
|
||||
@@ -69,7 +70,11 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
|
||||
}
|
||||
|
||||
protected boolean isShowListForEmptyPattern(){
|
||||
return false;
|
||||
return myShowListForEmptyPattern;
|
||||
}
|
||||
|
||||
public void setShowListForEmptyPattern(boolean showListForEmptyPattern) {
|
||||
myShowListForEmptyPattern = showListForEmptyPattern;
|
||||
}
|
||||
|
||||
protected boolean isCloseByFocusLost(){
|
||||
|
||||
Reference in New Issue
Block a user