|
|
|
@ -8,17 +8,17 @@
|
|
|
|
|
*/ |
|
|
|
|
package com.fr.design.gui.autocomplete; |
|
|
|
|
|
|
|
|
|
import java.awt.*; |
|
|
|
|
import java.awt.event.*; |
|
|
|
|
import java.beans.PropertyChangeEvent; |
|
|
|
|
import java.beans.PropertyChangeListener; |
|
|
|
|
import java.util.List; |
|
|
|
|
import javax.swing.*; |
|
|
|
|
import javax.swing.event.CaretEvent; |
|
|
|
|
import javax.swing.event.CaretListener; |
|
|
|
|
import javax.swing.event.DocumentEvent; |
|
|
|
|
import javax.swing.event.DocumentListener; |
|
|
|
|
import javax.swing.text.*; |
|
|
|
|
import java.awt.*; |
|
|
|
|
import java.awt.event.*; |
|
|
|
|
import java.beans.PropertyChangeEvent; |
|
|
|
|
import java.beans.PropertyChangeListener; |
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; |
|
|
|
|
|
|
|
|
@ -26,10 +26,10 @@ import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_M
|
|
|
|
|
/** |
|
|
|
|
* Adds auto-completion to a text component. Provides a popup window with a |
|
|
|
|
* list of auto-complete choices on a given keystroke, such as Crtrl+Space.<p> |
|
|
|
|
* |
|
|
|
|
* <p> |
|
|
|
|
* Depending on the {@link CompletionProvider} installed, the following |
|
|
|
|
* auto-completion features may be enabled: |
|
|
|
|
* |
|
|
|
|
* <p> |
|
|
|
|
* <ul> |
|
|
|
|
* <li>An auto-complete choices list made visible via e.g. Ctrl+Space</li> |
|
|
|
|
* <li>A "description" window displayed alongside the choices list that |
|
|
|
@ -214,7 +214,7 @@ public class AutoCompletion {
|
|
|
|
|
* Stores how to render auto-completion-specific highlights in text |
|
|
|
|
* components. |
|
|
|
|
*/ |
|
|
|
|
private static final AutoCompletionStyleContext styleContext = |
|
|
|
|
private static final AutoCompletionStyleContext STYLE_CONTEXT = |
|
|
|
|
new AutoCompletionStyleContext(); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -297,7 +297,7 @@ public class AutoCompletion {
|
|
|
|
|
* |
|
|
|
|
* @return Whether debug is enabled. |
|
|
|
|
*/ |
|
|
|
|
static boolean getDebug() { |
|
|
|
|
static boolean isDebug() { |
|
|
|
|
return DEBUG; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -398,7 +398,7 @@ public class AutoCompletion {
|
|
|
|
|
* @return Whether the description window should be shown. |
|
|
|
|
* @see #setShowDescWindow(boolean) |
|
|
|
|
*/ |
|
|
|
|
public boolean getShowDescWindow() { |
|
|
|
|
public boolean isShowDescWindow() { |
|
|
|
|
return showDescWindow; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -410,7 +410,7 @@ public class AutoCompletion {
|
|
|
|
|
* @return The style context. |
|
|
|
|
*/ |
|
|
|
|
public static AutoCompletionStyleContext getStyleContext() { |
|
|
|
|
return styleContext; |
|
|
|
|
return STYLE_CONTEXT; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -433,7 +433,7 @@ public class AutoCompletion {
|
|
|
|
|
* we are not installed on one. |
|
|
|
|
*/ |
|
|
|
|
ComponentOrientation getTextComponentOrientation() { |
|
|
|
|
return textComponent==null ? null : |
|
|
|
|
return textComponent == null ? null : |
|
|
|
|
textComponent.getComponentOrientation(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -468,7 +468,7 @@ public class AutoCompletion {
|
|
|
|
|
* @return Whether any such windows were visible (and thus hidden). |
|
|
|
|
*/ |
|
|
|
|
private boolean hideParameterCompletionPopups() { |
|
|
|
|
if (pcc!=null) { |
|
|
|
|
if (pcc != null) { |
|
|
|
|
pcc.deactivate(); |
|
|
|
|
pcc = null; |
|
|
|
|
return true; |
|
|
|
@ -483,7 +483,7 @@ public class AutoCompletion {
|
|
|
|
|
* @return Whether the popup window was visible. |
|
|
|
|
*/ |
|
|
|
|
private boolean hidePopupWindow() { |
|
|
|
|
if (popupWindow!=null) { |
|
|
|
|
if (popupWindow != null) { |
|
|
|
|
if (popupWindow.isVisible()) { |
|
|
|
|
popupWindow.setVisible(false); |
|
|
|
|
return true; |
|
|
|
@ -540,7 +540,7 @@ public class AutoCompletion {
|
|
|
|
|
|
|
|
|
|
int dot = caret.getDot(); |
|
|
|
|
int len = alreadyEntered.length(); |
|
|
|
|
int start = dot-len; |
|
|
|
|
int start = dot - len; |
|
|
|
|
String replacement = getReplacementText(c, textComp.getDocument(), |
|
|
|
|
start, len); |
|
|
|
|
|
|
|
|
@ -550,7 +550,7 @@ public class AutoCompletion {
|
|
|
|
|
|
|
|
|
|
if (isParameterAssistanceEnabled() && |
|
|
|
|
(c instanceof ParameterizedCompletion)) { |
|
|
|
|
ParameterizedCompletion pc = (ParameterizedCompletion)c; |
|
|
|
|
ParameterizedCompletion pc = (ParameterizedCompletion) c; |
|
|
|
|
startParameterizedCompletionAssistance(pc, typedParamListStartChar); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -567,7 +567,7 @@ public class AutoCompletion {
|
|
|
|
|
*/ |
|
|
|
|
public void install(JTextComponent c) { |
|
|
|
|
|
|
|
|
|
if (textComponent!=null) { |
|
|
|
|
if (textComponent != null) { |
|
|
|
|
uninstall(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -581,7 +581,7 @@ public class AutoCompletion {
|
|
|
|
|
// hoses ctrl+space, shift+space, etc., even though I think it
|
|
|
|
|
// shouldn't...
|
|
|
|
|
char start = provider.getParameterListStart(); |
|
|
|
|
if (start!=0 && start!=' ') { |
|
|
|
|
if (start != 0 && start != ' ') { |
|
|
|
|
InputMap im = c.getInputMap(); |
|
|
|
|
ActionMap am = c.getActionMap(); |
|
|
|
|
KeyStroke ks = KeyStroke.getKeyStroke(start); |
|
|
|
@ -666,7 +666,7 @@ public class AutoCompletion {
|
|
|
|
|
* @return Whether the completion popup window is visible. |
|
|
|
|
*/ |
|
|
|
|
public boolean isPopupVisible() { |
|
|
|
|
return popupWindow!=null && popupWindow.isVisible(); |
|
|
|
|
return popupWindow != null && popupWindow.isVisible(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -681,60 +681,32 @@ public class AutoCompletion {
|
|
|
|
|
* @return The current line number of the caret. |
|
|
|
|
*/ |
|
|
|
|
protected int refreshPopupWindow() { |
|
|
|
|
|
|
|
|
|
// A return value of null => don't suggest completions
|
|
|
|
|
String text = provider.getAlreadyEnteredText(textComponent); |
|
|
|
|
if (text==null && !isPopupVisible()) { |
|
|
|
|
if (text == null && !isPopupVisible()) { |
|
|
|
|
return getLineOfCaret(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If the popup is currently visible, and they type a space (or any
|
|
|
|
|
// character that resets the completion list to "all completions"),
|
|
|
|
|
// the popup window should be hidden instead of being reset to show
|
|
|
|
|
// everything.
|
|
|
|
|
int textLen = text==null ? 0 : text.length(); |
|
|
|
|
if (textLen==0) { |
|
|
|
|
if (isPopupVisible()) { |
|
|
|
|
int textLen = text == null ? 0 : text.length(); |
|
|
|
|
if (textLen == 0 && isPopupVisible()) { |
|
|
|
|
hidePopupWindow(); |
|
|
|
|
return getLineOfCaret(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
final List<Completion> completions = provider. |
|
|
|
|
getCompletions(textComponent); |
|
|
|
|
final List<Completion> completions = provider.getCompletions(textComponent); |
|
|
|
|
int count = completions.size(); |
|
|
|
|
|
|
|
|
|
if (count>1 || (count==1 && (isPopupVisible() || textLen==0)) || |
|
|
|
|
(count==1 && !getAutoCompleteSingleChoices())) { |
|
|
|
|
|
|
|
|
|
if (popupWindow==null) { |
|
|
|
|
popupWindow = new AutoCompletePopupWindow(parentWindow, this); |
|
|
|
|
// Completion is usually done for code, which is always done
|
|
|
|
|
// LTR, so make completion stuff RTL only if text component is
|
|
|
|
|
// also RTL.
|
|
|
|
|
popupWindow.applyComponentOrientation( |
|
|
|
|
getTextComponentOrientation()); |
|
|
|
|
if (renderer!=null) { |
|
|
|
|
popupWindow.setListCellRenderer(renderer); |
|
|
|
|
} |
|
|
|
|
if (preferredChoicesWindowSize!=null) { |
|
|
|
|
popupWindow.setSize(preferredChoicesWindowSize); |
|
|
|
|
} |
|
|
|
|
if (preferredDescWindowSize!=null) { |
|
|
|
|
popupWindow.setDescriptionWindowSize( |
|
|
|
|
preferredDescWindowSize); |
|
|
|
|
} |
|
|
|
|
if (needSetPopupWindow(count, textLen)) { |
|
|
|
|
if (popupWindow == null) { |
|
|
|
|
popupWindow = createAutoCompletePopupWindow(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
popupWindow.setCompletions(completions); |
|
|
|
|
|
|
|
|
|
if (!popupWindow.isVisible()) { |
|
|
|
|
Rectangle r = null; |
|
|
|
|
try { |
|
|
|
|
r = textComponent.modelToView(textComponent. |
|
|
|
|
getCaretPosition()); |
|
|
|
|
r = textComponent.modelToView(textComponent.getCaretPosition()); |
|
|
|
|
} catch (BadLocationException ble) { |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
Point p = new Point(r.x, r.y); |
|
|
|
@ -744,25 +716,43 @@ public class AutoCompletion {
|
|
|
|
|
popupWindow.setLocationRelativeTo(r); |
|
|
|
|
popupWindow.setVisible(true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
else if (count==1) { // !isPopupVisible && autoCompleteSingleChoices
|
|
|
|
|
} else if (count == 1) { // !isPopupVisible && autoCompleteSingleChoices
|
|
|
|
|
SwingUtilities.invokeLater(new Runnable() { |
|
|
|
|
public void run() { |
|
|
|
|
insertCompletion(completions.get(0)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
hidePopupWindow(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return getLineOfCaret(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean needSetPopupWindow(int count, int textLen) { |
|
|
|
|
return (count == 1 && (isPopupVisible() || textLen == 0)) |
|
|
|
|
|| (count == 1 && !getAutoCompleteSingleChoices()) |
|
|
|
|
|| count > 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private AutoCompletePopupWindow createAutoCompletePopupWindow() { |
|
|
|
|
AutoCompletePopupWindow popupWindow = new AutoCompletePopupWindow(parentWindow, this); |
|
|
|
|
// Completion is usually done for code, which is always done
|
|
|
|
|
// LTR, so make completion stuff RTL only if text component is
|
|
|
|
|
// also RTL.
|
|
|
|
|
popupWindow.applyComponentOrientation( |
|
|
|
|
getTextComponentOrientation()); |
|
|
|
|
if (renderer != null) { |
|
|
|
|
popupWindow.setListCellRenderer(renderer); |
|
|
|
|
} |
|
|
|
|
if (preferredChoicesWindowSize != null) { |
|
|
|
|
popupWindow.setSize(preferredChoicesWindowSize); |
|
|
|
|
} |
|
|
|
|
if (preferredDescWindowSize != null) { |
|
|
|
|
popupWindow.setDescriptionWindowSize( |
|
|
|
|
preferredDescWindowSize); |
|
|
|
|
} |
|
|
|
|
return popupWindow; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the delay between when the user types a character and when the |
|
|
|
@ -787,13 +777,12 @@ public class AutoCompletion {
|
|
|
|
|
* @see #setAutoActivationDelay(int) |
|
|
|
|
*/ |
|
|
|
|
public void setAutoActivationEnabled(boolean enabled) { |
|
|
|
|
if (enabled!=autoActivationEnabled) { |
|
|
|
|
if (enabled != autoActivationEnabled) { |
|
|
|
|
autoActivationEnabled = enabled; |
|
|
|
|
if (textComponent!=null) { |
|
|
|
|
if (textComponent != null) { |
|
|
|
|
if (autoActivationEnabled) { |
|
|
|
|
autoActivationListener.addTo(textComponent); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
autoActivationListener.removeFrom(textComponent); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -808,7 +797,7 @@ public class AutoCompletion {
|
|
|
|
|
* @see #isAutoCompleteEnabled() |
|
|
|
|
*/ |
|
|
|
|
public void setAutoCompleteEnabled(boolean enabled) { |
|
|
|
|
if (enabled!=autoCompleteEnabled) { |
|
|
|
|
if (enabled != autoCompleteEnabled) { |
|
|
|
|
autoCompleteEnabled = enabled; |
|
|
|
|
hidePopupWindow(); |
|
|
|
|
} |
|
|
|
@ -836,7 +825,7 @@ public class AutoCompletion {
|
|
|
|
|
* <code>null</code>. |
|
|
|
|
*/ |
|
|
|
|
public void setCompletionProvider(CompletionProvider provider) { |
|
|
|
|
if (provider==null) { |
|
|
|
|
if (provider == null) { |
|
|
|
|
throw new IllegalArgumentException("provider cannot be null"); |
|
|
|
|
} |
|
|
|
|
this.provider = provider; |
|
|
|
@ -853,7 +842,7 @@ public class AutoCompletion {
|
|
|
|
|
*/ |
|
|
|
|
public void setChoicesWindowSize(int w, int h) { |
|
|
|
|
preferredChoicesWindowSize = new Dimension(w, h); |
|
|
|
|
if (popupWindow!=null) { |
|
|
|
|
if (popupWindow != null) { |
|
|
|
|
popupWindow.setSize(preferredChoicesWindowSize); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -868,7 +857,7 @@ public class AutoCompletion {
|
|
|
|
|
*/ |
|
|
|
|
public void setDescriptionWindowSize(int w, int h) { |
|
|
|
|
preferredDescWindowSize = new Dimension(w, h); |
|
|
|
|
if (popupWindow!=null) { |
|
|
|
|
if (popupWindow != null) { |
|
|
|
|
popupWindow.setDescriptionWindowSize(preferredDescWindowSize); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -915,7 +904,7 @@ public class AutoCompletion {
|
|
|
|
|
*/ |
|
|
|
|
public void setListCellRenderer(ListCellRenderer renderer) { |
|
|
|
|
this.renderer = renderer; |
|
|
|
|
if (popupWindow!=null) { |
|
|
|
|
if (popupWindow != null) { |
|
|
|
|
popupWindow.setListCellRenderer(renderer); |
|
|
|
|
hidePopupWindow(); |
|
|
|
|
} |
|
|
|
@ -957,7 +946,7 @@ public class AutoCompletion {
|
|
|
|
|
* completion window. |
|
|
|
|
* |
|
|
|
|
* @param show Whether to show the description window. |
|
|
|
|
* @see #getShowDescWindow() |
|
|
|
|
* @see #isShowDescWindow() |
|
|
|
|
*/ |
|
|
|
|
public void setShowDescWindow(boolean show) { |
|
|
|
|
hidePopupWindow(); // Needed to force it to take effect
|
|
|
|
@ -974,11 +963,11 @@ public class AutoCompletion {
|
|
|
|
|
* @see #getTriggerKey() |
|
|
|
|
*/ |
|
|
|
|
public void setTriggerKey(KeyStroke ks) { |
|
|
|
|
if (ks==null) { |
|
|
|
|
if (ks == null) { |
|
|
|
|
throw new IllegalArgumentException("trigger key cannot be null"); |
|
|
|
|
} |
|
|
|
|
if (!ks.equals(trigger)) { |
|
|
|
|
if (textComponent!=null) { |
|
|
|
|
if (textComponent != null) { |
|
|
|
|
// Put old trigger action back.
|
|
|
|
|
uninstallTriggerKey(); |
|
|
|
|
// Grab current action for new trigger and replace it.
|
|
|
|
@ -1004,17 +993,16 @@ public class AutoCompletion {
|
|
|
|
|
|
|
|
|
|
// Don't bother with a tool tip if there are no parameters, but if
|
|
|
|
|
// they typed e.g. the opening '(', make them overtype the ')'.
|
|
|
|
|
if (pc.getParamCount()==0 && !(pc instanceof TemplateCompletion)) { |
|
|
|
|
if (pc.getParamCount() == 0 && !(pc instanceof TemplateCompletion)) { |
|
|
|
|
CompletionProvider p = pc.getProvider(); |
|
|
|
|
char end = p.getParameterListEnd(); // Might be '\0'
|
|
|
|
|
String text = end=='\0' ? "" : Character.toString(end); |
|
|
|
|
String text = end == '\0' ? "" : Character.toString(end); |
|
|
|
|
if (typedParamListStartChar) { |
|
|
|
|
String template = "${}" + text + "${cursor}"; |
|
|
|
|
textComponent.replaceSelection(Character.toString(p.getParameterListStart())); |
|
|
|
|
TemplateCompletion tc = new TemplateCompletion(p, null, null, template); |
|
|
|
|
pc = tc; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
text = p.getParameterListStart() + text; |
|
|
|
|
textComponent.replaceSelection(text); |
|
|
|
|
return; |
|
|
|
@ -1035,7 +1023,7 @@ public class AutoCompletion {
|
|
|
|
|
*/ |
|
|
|
|
public void uninstall() { |
|
|
|
|
|
|
|
|
|
if (textComponent!=null) { |
|
|
|
|
if (textComponent != null) { |
|
|
|
|
|
|
|
|
|
hidePopupWindow(); // Unregisters listeners, actions, etc.
|
|
|
|
|
|
|
|
|
@ -1043,7 +1031,7 @@ public class AutoCompletion {
|
|
|
|
|
|
|
|
|
|
// Uninstall the function completion key.
|
|
|
|
|
char start = provider.getParameterListStart(); |
|
|
|
|
if (start!=0) { |
|
|
|
|
if (start != 0) { |
|
|
|
|
KeyStroke ks = KeyStroke.getKeyStroke(start); |
|
|
|
|
InputMap im = textComponent.getInputMap(); |
|
|
|
|
im.put(ks, oldParenKey); |
|
|
|
@ -1052,7 +1040,7 @@ public class AutoCompletion {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
textComponentListener.removeFrom(textComponent); |
|
|
|
|
if (parentWindow!=null) { |
|
|
|
|
if (parentWindow != null) { |
|
|
|
|
parentWindowListener.removeFrom(parentWindow); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1090,15 +1078,15 @@ public class AutoCompletion {
|
|
|
|
|
* at runtime. |
|
|
|
|
*/ |
|
|
|
|
private void updateUI() { |
|
|
|
|
if (popupWindow!=null) { |
|
|
|
|
if (popupWindow != null) { |
|
|
|
|
popupWindow.updateUI(); |
|
|
|
|
} |
|
|
|
|
if (pcc!=null) { |
|
|
|
|
if (pcc != null) { |
|
|
|
|
pcc.updateUI(); |
|
|
|
|
} |
|
|
|
|
// Will practically always be a JComponent (a JLabel)
|
|
|
|
|
if (paramChoicesRenderer instanceof JComponent) { |
|
|
|
|
((JComponent)paramChoicesRenderer).updateUI(); |
|
|
|
|
((JComponent) paramChoicesRenderer).updateUI(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1131,8 +1119,7 @@ public class AutoCompletion {
|
|
|
|
|
public void caretUpdate(CaretEvent e) { |
|
|
|
|
if (justInserted) { |
|
|
|
|
justInserted = false; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
timer.stop(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1150,16 +1137,14 @@ public class AutoCompletion {
|
|
|
|
|
public void insertUpdate(DocumentEvent e) { |
|
|
|
|
justInserted = false; |
|
|
|
|
if (isAutoCompleteEnabled() && isAutoActivationEnabled() && |
|
|
|
|
e.getLength()==1) { |
|
|
|
|
e.getLength() == 1) { |
|
|
|
|
if (provider.isAutoActivateOkay(textComponent)) { |
|
|
|
|
timer.restart(); |
|
|
|
|
justInserted = true; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
timer.stop(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
timer.stop(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1188,8 +1173,7 @@ public class AutoCompletion {
|
|
|
|
|
public void actionPerformed(ActionEvent e) { |
|
|
|
|
if (isAutoCompleteEnabled()) { |
|
|
|
|
refreshPopupWindow(); |
|
|
|
|
} |
|
|
|
|
else if (oldTriggerAction!=null) { |
|
|
|
|
} else if (oldTriggerAction != null) { |
|
|
|
|
oldTriggerAction.actionPerformed(e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1323,11 +1307,11 @@ public class AutoCompletion {
|
|
|
|
|
|
|
|
|
|
Window oldParentWindow = parentWindow; |
|
|
|
|
parentWindow = SwingUtilities.getWindowAncestor(textComponent); |
|
|
|
|
if (parentWindow!=oldParentWindow) { |
|
|
|
|
if (oldParentWindow!=null) { |
|
|
|
|
if (parentWindow != oldParentWindow) { |
|
|
|
|
if (oldParentWindow != null) { |
|
|
|
|
parentWindowListener.removeFrom(oldParentWindow); |
|
|
|
|
} |
|
|
|
|
if (parentWindow!=null) { |
|
|
|
|
if (parentWindow != null) { |
|
|
|
|
parentWindowListener.addTo(parentWindow); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|