mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-66333 Quick documentation lookup on mouse hover
1. 'Auto quick doc' is closed on pressing any key; 2. Don't show auto quick doc if any modifier key is set (e.g. prevent it from popping out when we want to navigate via Ctrl+click or evaluate via Alt+click);
This commit is contained in:
+2
-2
@@ -49,9 +49,9 @@ public abstract class DockablePopupManager<T extends JComponent & Disposable> {
|
||||
protected ToolWindow myToolWindow = null;
|
||||
protected boolean myAutoUpdateDocumentation = PropertiesComponent.getInstance().isTrueValue(getAutoUpdateEnabledProperty());
|
||||
protected Runnable myAutoUpdateRequest;
|
||||
protected final Project myProject;
|
||||
@NotNull protected final Project myProject;
|
||||
|
||||
public DockablePopupManager(Project project) {
|
||||
public DockablePopupManager(@NotNull Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
|
||||
+49
-6
@@ -61,6 +61,7 @@ import com.intellij.ui.popup.NotLookupOrSearchCondition;
|
||||
import com.intellij.ui.popup.PopupPositionManager;
|
||||
import com.intellij.ui.popup.PopupUpdateProcessor;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.BooleanFunction;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -71,6 +72,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -94,6 +96,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
@NonNls private static final String DOC_ELEMENT_PROTOCOL = "doc_element://";
|
||||
|
||||
private final ActionManagerEx myActionManagerEx;
|
||||
private boolean myCloseOnSneeze;
|
||||
|
||||
private static final int ourFlagsForTargetElements = TargetElementUtilBase.getInstance().getAllAccepted();
|
||||
|
||||
@@ -135,11 +138,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
if (action == myActionManagerEx.getAction(IdeActions.ACTION_EDITOR_MOVE_CARET_PAGE_UP)) return;
|
||||
if (action == ActionManagerEx.getInstanceEx().getAction(IdeActions.ACTION_EDITOR_ESCAPE)) return;
|
||||
if (ActionPlaces.JAVADOC_INPLACE_SETTINGS.equals(event.getPlace())) return;
|
||||
Component toFocus = myPreviouslyFocused;
|
||||
hint.cancel();
|
||||
if (toFocus != null) {
|
||||
IdeFocusManager.getInstance(project).requestFocus(toFocus, true);
|
||||
}
|
||||
closeDocHint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,12 +157,46 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
myUpdateDocAlarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD,myProject);
|
||||
}
|
||||
|
||||
private void closeDocHint() {
|
||||
JBPopup hint = getDocInfoHint();
|
||||
if (hint == null) {
|
||||
return;
|
||||
}
|
||||
myCloseOnSneeze = false;
|
||||
hint.cancel();
|
||||
Component toFocus = myPreviouslyFocused;
|
||||
hint.cancel();
|
||||
if (toFocus != null) {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(toFocus, true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasDockedDocWindow() {
|
||||
return myToolWindow != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks to show quick doc for the target element.
|
||||
*
|
||||
* @param editor editor with an element for which quick do should be shown
|
||||
* @param element target element which documentation should be shown
|
||||
* @param original element that was used as a quick doc anchor. Example: consider a code like {@code Runnable task;}.
|
||||
* A user wants to see javadoc for the {@code Runnable}, so, original element is a class name from the variable
|
||||
* declaration but <code>'element'</code> argument is a {@code Runnable} descriptor
|
||||
* @param closeCallback callback to be notified on target hint close (if any)
|
||||
* @param closeOnSneeze flag that defines whether quick doc control should be as non-obtrusive as possible. E.g. there are at least
|
||||
* two possible situations - the quick doc is shown automatically on mouse over element; the quick doc is shown
|
||||
* on explicit action call (Ctrl+Q). We want to close the doc on, say, editor viewport position change
|
||||
* at the first situation but don't want to do that at the second
|
||||
*/
|
||||
public void showJavaDocInfo(@NotNull Editor editor,
|
||||
@NotNull final PsiElement element,
|
||||
@NotNull final PsiElement original,
|
||||
@Nullable Runnable closeCallback)
|
||||
@Nullable Runnable closeCallback,
|
||||
boolean closeOnSneeze)
|
||||
{
|
||||
myEditor = editor;
|
||||
myCloseOnSneeze = closeOnSneeze;
|
||||
showJavaDocInfo(element, original, closeCallback);
|
||||
}
|
||||
|
||||
@@ -360,6 +393,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
.setModalContext(false)
|
||||
.setCancelCallback(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
myCloseOnSneeze = false;
|
||||
if (closeCallback != null) {
|
||||
closeCallback.run();
|
||||
}
|
||||
@@ -374,6 +408,15 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
})
|
||||
.setKeyEventHandler(new BooleanFunction<KeyEvent>() {
|
||||
@Override
|
||||
public boolean fun(KeyEvent event) {
|
||||
if (myCloseOnSneeze) {
|
||||
closeDocHint();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.createPopup();
|
||||
|
||||
|
||||
|
||||
+8
-2
@@ -103,6 +103,12 @@ public class QuickDocOnMouseOverManager {
|
||||
closeAutoQuickDocComponentIfNecessary();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.getMouseEvent().getModifiers() != 0) {
|
||||
// Don't show the control when any modifier is active (e.g. Ctrl or Alt is hold). There is a common situation that a user
|
||||
// wants to navigate via Ctrl+click or perform quick evaluate by Alt+click.
|
||||
return;
|
||||
}
|
||||
|
||||
Editor editor = e.getEditor();
|
||||
Project project = editor.getProject();
|
||||
@@ -218,7 +224,7 @@ public class QuickDocOnMouseOverManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myHintManager.hasShownHintsThatWillHideByOtherHint(true)) {
|
||||
if (!info.docManager.hasDockedDocWindow() && myHintManager.hasShownHintsThatWillHideByOtherHint(false)) {
|
||||
// We don't want to show a quick doc control if there is an active hint (e.g. the mouse is under an invalid element
|
||||
// and corresponding error info is shown).
|
||||
myAlarm.addRequest(this, EditorSettingsExternalizable.getInstance().getQuickDocOnMouseOverElementDelayMillis());
|
||||
@@ -228,7 +234,7 @@ public class QuickDocOnMouseOverManager {
|
||||
info.editor.putUserData(PopupFactoryImpl.ANCHOR_POPUP_POSITION,
|
||||
info.editor.offsetToVisualPosition(info.originalElement.getTextRange().getStartOffset()));
|
||||
try {
|
||||
info.docManager.showJavaDocInfo(info.editor, info.targetElement, info.originalElement, myHintCloseCallback);
|
||||
info.docManager.showJavaDocInfo(info.editor, info.targetElement, info.originalElement, myHintCloseCallback, true);
|
||||
myDocumentationManager = new WeakReference<DocumentationManager>(info.docManager);
|
||||
}
|
||||
finally {
|
||||
|
||||
+154
-143
@@ -1,143 +1,154 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.openapi.ui.popup;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public interface ComponentPopupBuilder {
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setTitle(String title);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setResizable(final boolean forceResizable);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setMovable(final boolean forceMovable);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setRequestFocus(boolean requestFocus);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setFocusable(boolean focusable);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setRequestFocusCondition(Project project, Condition<Project> condition);
|
||||
|
||||
/**
|
||||
* @deprecated all popups are heavyweight now, lightweight popups no linger supported
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setForceHeavyweight(boolean forceHeavyweight);
|
||||
|
||||
/**
|
||||
* @see com.intellij.openapi.util.DimensionService
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setDimensionServiceKey(@Nullable final Project project, @NonNls final String dimensionServiceKey, final boolean useForXYLocation);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelCallback(final Computable<Boolean> shouldProceed);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelOnClickOutside(boolean cancel);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder addListener(JBPopupListener listener);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelOnMouseOutCallback(final MouseChecker shouldCancel);
|
||||
|
||||
@NotNull
|
||||
JBPopup createPopup();
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelButton(@NotNull IconButton cancelButton);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelOnOtherWindowOpen(boolean cancelOnWindow);
|
||||
|
||||
@NotNull ComponentPopupBuilder setTitleIcon(@NotNull ActiveIcon icon);
|
||||
|
||||
@NotNull ComponentPopupBuilder setCancelKeyEnabled(boolean enabled);
|
||||
|
||||
@NotNull ComponentPopupBuilder setLocateByContent(boolean byContent);
|
||||
|
||||
@NotNull ComponentPopupBuilder setLocateWithinScreenBounds(boolean within);
|
||||
|
||||
@NotNull ComponentPopupBuilder setMinSize(Dimension minSize);
|
||||
|
||||
@NotNull ComponentPopupBuilder setAlpha(float alpha);
|
||||
|
||||
@NotNull ComponentPopupBuilder setBelongsToGlobalPopupStack(boolean isInStack);
|
||||
|
||||
@NotNull ComponentPopupBuilder setProject(Project project);
|
||||
|
||||
@NotNull ComponentPopupBuilder addUserData(Object object);
|
||||
|
||||
@NotNull ComponentPopupBuilder setModalContext(boolean modal);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setFocusOwners(@NotNull Component[] focusOwners);
|
||||
|
||||
/**
|
||||
* Adds "advertising" text to the bottom (e.g.: hints in code completion popup).
|
||||
*
|
||||
* @param text Text to set.
|
||||
* @return This.
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setAdText(@Nullable String text);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setAdText(@Nullable String text, int textAlignment);
|
||||
|
||||
@NotNull ComponentPopupBuilder setShowShadow(boolean show);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCommandButton(@NotNull InplaceButton commandButton);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCouldPin(@Nullable Processor<JBPopup> callback);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setKeyboardActions(@NotNull List<Pair<ActionListener, KeyStroke>> keyboardActions);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setSettingButtons(@NotNull Component button);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setMayBeParent(boolean mayBeParent);
|
||||
|
||||
ComponentPopupBuilder setCancelOnWindowDeactivation(boolean cancelOnWindowDeactivation);
|
||||
}
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.openapi.ui.popup;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.util.BooleanFunction;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public interface ComponentPopupBuilder {
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setTitle(String title);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setResizable(final boolean forceResizable);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setMovable(final boolean forceMovable);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setRequestFocus(boolean requestFocus);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setFocusable(boolean focusable);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setRequestFocusCondition(Project project, Condition<Project> condition);
|
||||
|
||||
/**
|
||||
* @deprecated all popups are heavyweight now, lightweight popups no linger supported
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setForceHeavyweight(boolean forceHeavyweight);
|
||||
|
||||
/**
|
||||
* @see com.intellij.openapi.util.DimensionService
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setDimensionServiceKey(@Nullable final Project project, @NonNls final String dimensionServiceKey, final boolean useForXYLocation);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelCallback(final Computable<Boolean> shouldProceed);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelOnClickOutside(boolean cancel);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder addListener(JBPopupListener listener);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelOnMouseOutCallback(final MouseChecker shouldCancel);
|
||||
|
||||
@NotNull
|
||||
JBPopup createPopup();
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelButton(@NotNull IconButton cancelButton);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCancelOnOtherWindowOpen(boolean cancelOnWindow);
|
||||
|
||||
@NotNull ComponentPopupBuilder setTitleIcon(@NotNull ActiveIcon icon);
|
||||
|
||||
@NotNull ComponentPopupBuilder setCancelKeyEnabled(boolean enabled);
|
||||
|
||||
@NotNull ComponentPopupBuilder setLocateByContent(boolean byContent);
|
||||
|
||||
@NotNull ComponentPopupBuilder setLocateWithinScreenBounds(boolean within);
|
||||
|
||||
@NotNull ComponentPopupBuilder setMinSize(Dimension minSize);
|
||||
|
||||
@NotNull ComponentPopupBuilder setAlpha(float alpha);
|
||||
|
||||
@NotNull ComponentPopupBuilder setBelongsToGlobalPopupStack(boolean isInStack);
|
||||
|
||||
@NotNull ComponentPopupBuilder setProject(Project project);
|
||||
|
||||
@NotNull ComponentPopupBuilder addUserData(Object object);
|
||||
|
||||
@NotNull ComponentPopupBuilder setModalContext(boolean modal);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setFocusOwners(@NotNull Component[] focusOwners);
|
||||
|
||||
/**
|
||||
* Adds "advertising" text to the bottom (e.g.: hints in code completion popup).
|
||||
*
|
||||
* @param text Text to set.
|
||||
* @return This.
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setAdText(@Nullable String text);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setAdText(@Nullable String text, int textAlignment);
|
||||
|
||||
@NotNull ComponentPopupBuilder setShowShadow(boolean show);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCommandButton(@NotNull InplaceButton commandButton);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setCouldPin(@Nullable Processor<JBPopup> callback);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setKeyboardActions(@NotNull List<Pair<ActionListener, KeyStroke>> keyboardActions);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setSettingButtons(@NotNull Component button);
|
||||
|
||||
@NotNull
|
||||
ComponentPopupBuilder setMayBeParent(boolean mayBeParent);
|
||||
|
||||
ComponentPopupBuilder setCancelOnWindowDeactivation(boolean cancelOnWindowDeactivation);
|
||||
|
||||
/**
|
||||
* Allows to define custom strategy for processing {@link JBPopup#dispatchKeyEvent(KeyEvent)}
|
||||
*
|
||||
* @param handler strategy to use
|
||||
* @return <code>this</code>
|
||||
*/
|
||||
@NotNull
|
||||
ComponentPopupBuilder setKeyEventHandler(@NotNull BooleanFunction<KeyEvent> handler);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
/**
|
||||
* Base interface for popup windows.
|
||||
@@ -190,4 +191,15 @@ public interface JBPopup extends Disposable, LightweightWindow {
|
||||
void setAdText(String s, @JdkConstants.HorizontalAlignment int alignment);
|
||||
|
||||
void setDataProvider(@NotNull DataProvider dataProvider);
|
||||
|
||||
/**
|
||||
* This callback is called when new key event from the event queue is being processed.
|
||||
* <p/>
|
||||
* The popup has a right to decide if its further processing should be continued (method return value).
|
||||
*
|
||||
* @param e new key event being processed
|
||||
* @return <code>true</code> if the event is completely dispatched, i.e. no further processing is necessary;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean dispatchKeyEvent(@NotNull KeyEvent e);
|
||||
}
|
||||
|
||||
@@ -1,324 +1,334 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.ui.popup;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.*;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 15-Mar-2006
|
||||
*/
|
||||
public class ComponentPopupBuilderImpl implements ComponentPopupBuilder {
|
||||
private String myTitle = "";
|
||||
private boolean myResizable;
|
||||
private boolean myMovable;
|
||||
private final JComponent myComponent;
|
||||
private final JComponent myPreferredFocusedComponent;
|
||||
private boolean myRequestFocus;
|
||||
private boolean myForceHeavyweight;
|
||||
private String myDimensionServiceKey = null;
|
||||
private Computable<Boolean> myCallback = null;
|
||||
private Project myProject;
|
||||
private boolean myCancelOnClickOutside = true;
|
||||
private boolean myCancelOnWindowDeactivation = true;
|
||||
private final Set<JBPopupListener> myListeners = new LinkedHashSet<JBPopupListener>();
|
||||
private boolean myUseDimServiceForXYLocation;
|
||||
|
||||
private IconButton myCancelButton;
|
||||
private MouseChecker myCancelOnMouseOutCallback;
|
||||
private boolean myCancelOnWindow;
|
||||
private ActiveIcon myTitleIcon = new ActiveIcon(EmptyIcon.ICON_0);
|
||||
private boolean myCancelKeyEnabled = true;
|
||||
private boolean myLocateByContent = false;
|
||||
private boolean myPlacewithinScreen = true;
|
||||
private Processor<JBPopup> myPinCallback = null;
|
||||
private Dimension myMinSize;
|
||||
private MaskProvider myMaskProvider;
|
||||
private float myAlpha;
|
||||
private ArrayList<Object> myUserData;
|
||||
|
||||
private boolean myInStack = true;
|
||||
private boolean myModalContext = true;
|
||||
private Component[] myFocusOwners = new Component[0];
|
||||
|
||||
private String myAd;
|
||||
private boolean myShowShadow = true;
|
||||
private boolean myFocusable = true;
|
||||
private boolean myHeaderAlwaysFocusable;
|
||||
private InplaceButton myCommandButton;
|
||||
private List<Pair<ActionListener, KeyStroke>> myKeyboardActions = Collections.emptyList();
|
||||
private Component mySettingsButtons;
|
||||
private boolean myMayBeParent;
|
||||
private int myAdAlignment = SwingUtilities.LEFT;
|
||||
|
||||
public ComponentPopupBuilderImpl(final JComponent component,
|
||||
final JComponent preferredFocusedComponent) {
|
||||
myComponent = component;
|
||||
myPreferredFocusedComponent = preferredFocusedComponent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMayBeParent(boolean mayBeParent) {
|
||||
myMayBeParent = mayBeParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setTitle(String title) {
|
||||
myTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setResizable(final boolean resizable) {
|
||||
myResizable = resizable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMovable(final boolean movable) {
|
||||
myMovable = movable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelOnClickOutside(final boolean cancel) {
|
||||
myCancelOnClickOutside = cancel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelOnMouseOutCallback(final MouseChecker shouldCancel) {
|
||||
myCancelOnMouseOutCallback = shouldCancel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder addListener(final JBPopupListener listener) {
|
||||
myListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setRequestFocus(final boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setFocusable(final boolean focusable) {
|
||||
myFocusable = focusable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setForceHeavyweight(final boolean forceHeavyweight) {
|
||||
myForceHeavyweight = forceHeavyweight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setDimensionServiceKey(final Project project, final String dimensionServiceKey, final boolean useForXYLocation) {
|
||||
myDimensionServiceKey = dimensionServiceKey;
|
||||
myUseDimServiceForXYLocation = useForXYLocation;
|
||||
myProject = project;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelCallback(final Computable<Boolean> shouldProceed) {
|
||||
myCallback = shouldProceed;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelButton(@NotNull final IconButton cancelButton) {
|
||||
myCancelButton = cancelButton;
|
||||
return this;
|
||||
}
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCommandButton(@NotNull InplaceButton button) {
|
||||
myCommandButton = button;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCouldPin(@Nullable final Processor<JBPopup> callback) {
|
||||
myPinCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setKeyboardActions(@NotNull List<Pair<ActionListener, KeyStroke>> keyboardActions) {
|
||||
myKeyboardActions = keyboardActions;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setSettingButtons(@NotNull Component button) {
|
||||
mySettingsButtons = button;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelOnOtherWindowOpen(final boolean cancelOnWindow) {
|
||||
myCancelOnWindow = cancelOnWindow;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentPopupBuilder setCancelOnWindowDeactivation(boolean cancelOnWindowDeactivation) {
|
||||
myCancelOnWindowDeactivation = cancelOnWindowDeactivation;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setProject(Project project) {
|
||||
myProject = project;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JBPopup createPopup() {
|
||||
final AbstractPopup popup = new AbstractPopup().init(myProject, myComponent, myPreferredFocusedComponent, myRequestFocus, myFocusable, myForceHeavyweight,
|
||||
myMovable, myDimensionServiceKey, myResizable, myTitle,
|
||||
myCallback, myCancelOnClickOutside, myListeners, myUseDimServiceForXYLocation, myCommandButton,
|
||||
myCancelButton,
|
||||
myCancelOnMouseOutCallback, myCancelOnWindow, myTitleIcon, myCancelKeyEnabled, myLocateByContent,
|
||||
myPlacewithinScreen, myMinSize, myAlpha, myMaskProvider, myInStack, myModalContext, myFocusOwners, myAd, myAdAlignment,
|
||||
myHeaderAlwaysFocusable, myKeyboardActions, mySettingsButtons, myPinCallback, myMayBeParent,
|
||||
myShowShadow, myCancelOnWindowDeactivation);
|
||||
if (myUserData != null) {
|
||||
popup.setUserData(myUserData);
|
||||
}
|
||||
//default disposable parent
|
||||
Disposer.register(ApplicationManager.getApplication(), popup);
|
||||
return popup;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setRequestFocusCondition(Project project, Condition<Project> condition) {
|
||||
myRequestFocus = condition.value(project);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setTitleIcon(@NotNull final ActiveIcon icon) {
|
||||
myTitleIcon = icon;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelKeyEnabled(final boolean enabled) {
|
||||
myCancelKeyEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setLocateByContent(final boolean byContent) {
|
||||
myLocateByContent = byContent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setLocateWithinScreenBounds(final boolean within) {
|
||||
myPlacewithinScreen = within;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMinSize(final Dimension minSize) {
|
||||
myMinSize = minSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMaskProvider(MaskProvider maskProvider) {
|
||||
myMaskProvider = maskProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setAlpha(final float alpha) {
|
||||
myAlpha = alpha;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setBelongsToGlobalPopupStack(final boolean isInStack) {
|
||||
myInStack = isInStack;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder addUserData(final Object object) {
|
||||
if (myUserData == null) {
|
||||
myUserData = new ArrayList<Object>();
|
||||
}
|
||||
myUserData.add(object);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setModalContext(final boolean modal) {
|
||||
myModalContext = modal;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setFocusOwners(@NotNull final Component[] focusOwners) {
|
||||
myFocusOwners = focusOwners;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setAdText(@Nullable final String text) {
|
||||
return setAdText(text, SwingUtilities.LEFT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ComponentPopupBuilder setAdText(@Nullable String text, int textAlignment) {
|
||||
myAd = text;
|
||||
myAdAlignment = textAlignment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ComponentPopupBuilder setShowShadow(boolean show) {
|
||||
myShowShadow = show;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.ui.popup;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.*;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.util.BooleanFunction;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 15-Mar-2006
|
||||
*/
|
||||
public class ComponentPopupBuilderImpl implements ComponentPopupBuilder {
|
||||
private String myTitle = "";
|
||||
private boolean myResizable;
|
||||
private boolean myMovable;
|
||||
private final JComponent myComponent;
|
||||
private final JComponent myPreferredFocusedComponent;
|
||||
private boolean myRequestFocus;
|
||||
private boolean myForceHeavyweight;
|
||||
private String myDimensionServiceKey = null;
|
||||
private Computable<Boolean> myCallback = null;
|
||||
private Project myProject;
|
||||
private boolean myCancelOnClickOutside = true;
|
||||
private boolean myCancelOnWindowDeactivation = true;
|
||||
private final Set<JBPopupListener> myListeners = new LinkedHashSet<JBPopupListener>();
|
||||
private boolean myUseDimServiceForXYLocation;
|
||||
|
||||
private IconButton myCancelButton;
|
||||
private MouseChecker myCancelOnMouseOutCallback;
|
||||
private boolean myCancelOnWindow;
|
||||
private ActiveIcon myTitleIcon = new ActiveIcon(EmptyIcon.ICON_0);
|
||||
private boolean myCancelKeyEnabled = true;
|
||||
private boolean myLocateByContent = false;
|
||||
private boolean myPlacewithinScreen = true;
|
||||
private Processor<JBPopup> myPinCallback = null;
|
||||
private Dimension myMinSize;
|
||||
private MaskProvider myMaskProvider;
|
||||
private float myAlpha;
|
||||
private ArrayList<Object> myUserData;
|
||||
|
||||
private boolean myInStack = true;
|
||||
private boolean myModalContext = true;
|
||||
private Component[] myFocusOwners = new Component[0];
|
||||
|
||||
private String myAd;
|
||||
private boolean myShowShadow = true;
|
||||
private boolean myFocusable = true;
|
||||
private boolean myHeaderAlwaysFocusable;
|
||||
private InplaceButton myCommandButton;
|
||||
private List<Pair<ActionListener, KeyStroke>> myKeyboardActions = Collections.emptyList();
|
||||
private Component mySettingsButtons;
|
||||
private boolean myMayBeParent;
|
||||
private int myAdAlignment = SwingUtilities.LEFT;
|
||||
private BooleanFunction<KeyEvent> myKeyEventHandler;
|
||||
|
||||
public ComponentPopupBuilderImpl(final JComponent component,
|
||||
final JComponent preferredFocusedComponent) {
|
||||
myComponent = component;
|
||||
myPreferredFocusedComponent = preferredFocusedComponent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMayBeParent(boolean mayBeParent) {
|
||||
myMayBeParent = mayBeParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setTitle(String title) {
|
||||
myTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setResizable(final boolean resizable) {
|
||||
myResizable = resizable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMovable(final boolean movable) {
|
||||
myMovable = movable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelOnClickOutside(final boolean cancel) {
|
||||
myCancelOnClickOutside = cancel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelOnMouseOutCallback(final MouseChecker shouldCancel) {
|
||||
myCancelOnMouseOutCallback = shouldCancel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder addListener(final JBPopupListener listener) {
|
||||
myListeners.add(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setRequestFocus(final boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setFocusable(final boolean focusable) {
|
||||
myFocusable = focusable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setForceHeavyweight(final boolean forceHeavyweight) {
|
||||
myForceHeavyweight = forceHeavyweight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setDimensionServiceKey(final Project project, final String dimensionServiceKey, final boolean useForXYLocation) {
|
||||
myDimensionServiceKey = dimensionServiceKey;
|
||||
myUseDimServiceForXYLocation = useForXYLocation;
|
||||
myProject = project;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelCallback(final Computable<Boolean> shouldProceed) {
|
||||
myCallback = shouldProceed;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelButton(@NotNull final IconButton cancelButton) {
|
||||
myCancelButton = cancelButton;
|
||||
return this;
|
||||
}
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCommandButton(@NotNull InplaceButton button) {
|
||||
myCommandButton = button;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCouldPin(@Nullable final Processor<JBPopup> callback) {
|
||||
myPinCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setKeyboardActions(@NotNull List<Pair<ActionListener, KeyStroke>> keyboardActions) {
|
||||
myKeyboardActions = keyboardActions;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setSettingButtons(@NotNull Component button) {
|
||||
mySettingsButtons = button;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelOnOtherWindowOpen(final boolean cancelOnWindow) {
|
||||
myCancelOnWindow = cancelOnWindow;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentPopupBuilder setCancelOnWindowDeactivation(boolean cancelOnWindowDeactivation) {
|
||||
myCancelOnWindowDeactivation = cancelOnWindowDeactivation;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ComponentPopupBuilder setKeyEventHandler(@NotNull BooleanFunction<KeyEvent> handler) {
|
||||
myKeyEventHandler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setProject(Project project) {
|
||||
myProject = project;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JBPopup createPopup() {
|
||||
final AbstractPopup popup = new AbstractPopup().init(myProject, myComponent, myPreferredFocusedComponent, myRequestFocus, myFocusable, myForceHeavyweight,
|
||||
myMovable, myDimensionServiceKey, myResizable, myTitle,
|
||||
myCallback, myCancelOnClickOutside, myListeners, myUseDimServiceForXYLocation, myCommandButton,
|
||||
myCancelButton,
|
||||
myCancelOnMouseOutCallback, myCancelOnWindow, myTitleIcon, myCancelKeyEnabled, myLocateByContent,
|
||||
myPlacewithinScreen, myMinSize, myAlpha, myMaskProvider, myInStack, myModalContext, myFocusOwners, myAd, myAdAlignment,
|
||||
myHeaderAlwaysFocusable, myKeyboardActions, mySettingsButtons, myPinCallback, myMayBeParent,
|
||||
myShowShadow, myCancelOnWindowDeactivation, myKeyEventHandler);
|
||||
if (myUserData != null) {
|
||||
popup.setUserData(myUserData);
|
||||
}
|
||||
//default disposable parent
|
||||
Disposer.register(ApplicationManager.getApplication(), popup);
|
||||
return popup;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setRequestFocusCondition(Project project, Condition<Project> condition) {
|
||||
myRequestFocus = condition.value(project);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setTitleIcon(@NotNull final ActiveIcon icon) {
|
||||
myTitleIcon = icon;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setCancelKeyEnabled(final boolean enabled) {
|
||||
myCancelKeyEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setLocateByContent(final boolean byContent) {
|
||||
myLocateByContent = byContent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setLocateWithinScreenBounds(final boolean within) {
|
||||
myPlacewithinScreen = within;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMinSize(final Dimension minSize) {
|
||||
myMinSize = minSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setMaskProvider(MaskProvider maskProvider) {
|
||||
myMaskProvider = maskProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setAlpha(final float alpha) {
|
||||
myAlpha = alpha;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setBelongsToGlobalPopupStack(final boolean isInStack) {
|
||||
myInStack = isInStack;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder addUserData(final Object object) {
|
||||
if (myUserData == null) {
|
||||
myUserData = new ArrayList<Object>();
|
||||
}
|
||||
myUserData.add(object);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setModalContext(final boolean modal) {
|
||||
myModalContext = modal;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setFocusOwners(@NotNull final Component[] focusOwners) {
|
||||
myFocusOwners = focusOwners;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ComponentPopupBuilder setAdText(@Nullable final String text) {
|
||||
return setAdText(text, SwingUtilities.LEFT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ComponentPopupBuilder setAdText(@Nullable String text, int textAlignment) {
|
||||
myAd = text;
|
||||
myAdAlignment = textAlignment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ComponentPopupBuilder setShowShadow(boolean show) {
|
||||
myShowShadow = show;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,449 +1,449 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.popup;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.*;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.PopupBorder;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import com.intellij.ui.popup.tree.TreePopupImpl;
|
||||
import com.intellij.ui.popup.util.MnemonicsSearch;
|
||||
import com.intellij.ui.speedSearch.ElementFilter;
|
||||
import com.intellij.ui.speedSearch.SpeedSearch;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Collections;
|
||||
|
||||
public abstract class WizardPopup extends AbstractPopup implements ActionListener, ElementFilter {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.popup.WizardPopup");
|
||||
|
||||
private static final int AUTO_POPUP_DELAY = 750;
|
||||
private static final Dimension MAX_SIZE = new Dimension(Integer.MAX_VALUE, 600);
|
||||
|
||||
protected static final int STEP_X_PADDING = 2;
|
||||
|
||||
private final WizardPopup myParent;
|
||||
|
||||
protected final PopupStep<Object> myStep;
|
||||
protected WizardPopup myChild;
|
||||
|
||||
private final Timer myAutoSelectionTimer = UIUtil.createNamedTimer("Wizard autoselection",AUTO_POPUP_DELAY, this);
|
||||
|
||||
private MnemonicsSearch myMnemonicsSearch;
|
||||
private Object myParentValue;
|
||||
|
||||
private Point myLastOwnerPoint;
|
||||
private Window myOwnerWindow;
|
||||
private MyComponentAdapter myOwnerListener;
|
||||
|
||||
private final ActionMap myActionMap = new ActionMap();
|
||||
private final InputMap myInputMap = new InputMap();
|
||||
|
||||
public WizardPopup(PopupStep<Object> aStep) {
|
||||
this(null, aStep);
|
||||
}
|
||||
|
||||
public WizardPopup(JBPopup aParent, PopupStep<Object> aStep) {
|
||||
myParent = (WizardPopup) aParent;
|
||||
myStep = aStep;
|
||||
|
||||
mySpeedSearch.setEnabled(myStep.isSpeedSearchEnabled());
|
||||
|
||||
final JComponent content = createContent();
|
||||
|
||||
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(content);
|
||||
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.getHorizontalScrollBar().setBorder(null);
|
||||
|
||||
scrollPane.getActionMap().get("unitScrollLeft").setEnabled(false);
|
||||
scrollPane.getActionMap().get("unitScrollRight").setEnabled(false);
|
||||
|
||||
scrollPane.setBorder(null);
|
||||
|
||||
final Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
|
||||
init(project, scrollPane, getPreferredFocusableComponent(), true, true, true, true, null,
|
||||
false, aStep.getTitle(), null, true, null, false, null, null, null, false, null, true, false, true, null, 0f,
|
||||
null, true, false, new Component[0], null, SwingUtilities.LEFT, true, Collections.<Pair<ActionListener, KeyStroke>>emptyList(), null, null, false, true,
|
||||
true);
|
||||
|
||||
registerAction("disposeAll", KeyEvent.VK_ESCAPE, InputEvent.SHIFT_MASK, new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (mySpeedSearch.isHoldingFilter()) {
|
||||
mySpeedSearch.reset();
|
||||
}
|
||||
else {
|
||||
disposeAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AbstractAction goBackAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
goBack();
|
||||
}
|
||||
};
|
||||
|
||||
registerAction("goBack3", KeyEvent.VK_ESCAPE, 0, goBackAction);
|
||||
|
||||
myMnemonicsSearch = new MnemonicsSearch(this) {
|
||||
protected void select(Object value) {
|
||||
onSelectByMnemonic(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void disposeAll() {
|
||||
WizardPopup root = PopupDispatcher.getActiveRoot();
|
||||
disposeAllParents(null);
|
||||
root.getStep().canceled();
|
||||
}
|
||||
|
||||
public void goBack() {
|
||||
if (mySpeedSearch.isHoldingFilter()) {
|
||||
mySpeedSearch.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (myParent != null) {
|
||||
myParent.disposeChildren();
|
||||
}
|
||||
else {
|
||||
disposeAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract JComponent createContent();
|
||||
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
||||
myAutoSelectionTimer.stop();
|
||||
|
||||
PopupDispatcher.unsetShowing(this);
|
||||
PopupDispatcher.clearRootIfNeeded(this);
|
||||
|
||||
|
||||
if (myOwnerWindow != null && myOwnerListener != null) {
|
||||
myOwnerWindow.removeComponentListener(myOwnerListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void disposeChildren() {
|
||||
if (myChild != null) {
|
||||
myChild.disposeChildren();
|
||||
Disposer.dispose(myChild);
|
||||
myChild = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void show(final Component owner, final int aScreenX, final int aScreenY, final boolean considerForcedXY) {
|
||||
LOG.assertTrue (!isDisposed());
|
||||
|
||||
Rectangle targetBounds = new Rectangle(new Point(aScreenX, aScreenY), getContent().getPreferredSize());
|
||||
ScreenUtil.moveRectangleToFitTheScreen(targetBounds);
|
||||
|
||||
if (getParent() != null) {
|
||||
final Rectangle parentBounds = getParent().getBounds();
|
||||
parentBounds.x += STEP_X_PADDING;
|
||||
parentBounds.width -= STEP_X_PADDING * 2;
|
||||
if (parentBounds.intersects(targetBounds)) {
|
||||
targetBounds.x = getParent().getBounds().x - targetBounds.width - STEP_X_PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
if (getParent() == null) {
|
||||
PopupDispatcher.setActiveRoot(this);
|
||||
}
|
||||
else {
|
||||
PopupDispatcher.setShowing(this);
|
||||
}
|
||||
|
||||
LOG.assertTrue (!isDisposed(), "Disposed popup, parent="+getParent());
|
||||
super.show(owner, targetBounds.x, targetBounds.y, true);
|
||||
}
|
||||
|
||||
protected void afterShow() {
|
||||
super.afterShow();
|
||||
registerAutoMove();
|
||||
|
||||
if (!myFocusTrackback.isMustBeShown()) {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerAutoMove() {
|
||||
if (myOwner != null) {
|
||||
myOwnerWindow = SwingUtilities.getWindowAncestor(myOwner);
|
||||
if (myOwnerWindow != null) {
|
||||
myLastOwnerPoint = myOwnerWindow.getLocationOnScreen();
|
||||
myOwnerListener = new MyComponentAdapter();
|
||||
myOwnerWindow.addComponentListener(myOwnerListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processParentWindowMoved() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
final Point newOwnerPoint = myOwnerWindow.getLocationOnScreen();
|
||||
|
||||
int deltaX = myLastOwnerPoint.x - newOwnerPoint.x;
|
||||
int deltaY = myLastOwnerPoint.y - newOwnerPoint.y;
|
||||
|
||||
myLastOwnerPoint = newOwnerPoint;
|
||||
|
||||
final Window wnd = SwingUtilities.getWindowAncestor(getContent());
|
||||
final Point current = wnd.getLocationOnScreen();
|
||||
|
||||
setLocation(new Point(current.x - deltaX, current.y - deltaY));
|
||||
}
|
||||
|
||||
protected abstract JComponent getPreferredFocusableComponent();
|
||||
|
||||
public void cancel(InputEvent e) {
|
||||
super.cancel(e);
|
||||
disposeChildren();
|
||||
Disposer.dispose(this);
|
||||
getStep().canceled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelKeyEnabled() {
|
||||
return super.isCancelKeyEnabled() && !mySpeedSearch.isHoldingFilter();
|
||||
}
|
||||
|
||||
protected void disposeAllParents(InputEvent e) {
|
||||
myDisposeEvent = e;
|
||||
dispose();
|
||||
if (myParent != null) {
|
||||
myParent.disposeAllParents(null);
|
||||
}
|
||||
}
|
||||
|
||||
public final void registerAction(@NonNls String aActionName, int aKeyCode, @JdkConstants.InputEventMask int aModifier, Action aAction) {
|
||||
myInputMap.put(KeyStroke.getKeyStroke(aKeyCode, aModifier), aActionName);
|
||||
myActionMap.put(aActionName, aAction);
|
||||
}
|
||||
|
||||
protected String getActionForKeyStroke(final KeyStroke keyStroke) {
|
||||
return (String) myInputMap.get(keyStroke);
|
||||
}
|
||||
|
||||
public final void registerAction(@NonNls String aActionName, KeyStroke keyStroke, Action aAction) {
|
||||
myInputMap.put(keyStroke, aActionName);
|
||||
myActionMap.put(aActionName, aAction);
|
||||
}
|
||||
|
||||
protected abstract InputMap getInputMap();
|
||||
|
||||
protected abstract ActionMap getActionMap();
|
||||
|
||||
protected final void setParentValue(Object parentValue) {
|
||||
myParentValue = parentValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected MyContentPanel createContentPanel(final boolean resizable, final PopupBorder border, final boolean isToDrawMacCorner) {
|
||||
return new MyContainer(resizable, border, isToDrawMacCorner);
|
||||
}
|
||||
|
||||
private static class MyContainer extends MyContentPanel {
|
||||
|
||||
private MyContainer(final boolean resizable, final PopupBorder border, final boolean drawMacCorner) {
|
||||
super(resizable, border, drawMacCorner);
|
||||
setOpaque(true);
|
||||
setFocusCycleRoot(true);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
Point p = null;
|
||||
if (focusOwner != null && focusOwner.isShowing()) {
|
||||
p = focusOwner.getLocationOnScreen();
|
||||
}
|
||||
|
||||
return computeNotBiggerDimension(super.getPreferredSize().getSize(), p);
|
||||
}
|
||||
|
||||
private static Dimension computeNotBiggerDimension(Dimension ofContent, final Point locationOnScreen) {
|
||||
int resultHeight = ofContent.height > MAX_SIZE.height + 50 ? MAX_SIZE.height : ofContent.height;
|
||||
if (locationOnScreen != null) {
|
||||
final Rectangle r = ScreenUtil.getScreenRectangle(locationOnScreen);
|
||||
resultHeight = ofContent.height > r.height - (r.height / 4) ? r.height - (r.height / 4) : ofContent.height;
|
||||
}
|
||||
|
||||
int resultWidth = ofContent.width > MAX_SIZE.width ? MAX_SIZE.width : ofContent.width;
|
||||
|
||||
if (ofContent.height > MAX_SIZE.height) {
|
||||
resultWidth += ScrollPaneFactory.createScrollPane().getVerticalScrollBar().getPreferredSize().getWidth();
|
||||
}
|
||||
|
||||
return new Dimension(resultWidth, resultHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public WizardPopup getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
public PopupStep getStep() {
|
||||
return myStep;
|
||||
}
|
||||
|
||||
public final void dispatch(KeyEvent event) {
|
||||
if (event.getID() != KeyEvent.KEY_PRESSED && event.getID() != KeyEvent.KEY_RELEASED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getID() == KeyEvent.KEY_PRESSED) {
|
||||
final KeyStroke stroke = KeyStroke.getKeyStroke(event.getKeyCode(), event.getModifiers(), false);
|
||||
if (proceedKeyEvent(event, stroke)) return;
|
||||
}
|
||||
|
||||
if (event.getID() == KeyEvent.KEY_RELEASED) {
|
||||
final KeyStroke stroke = KeyStroke.getKeyStroke(event.getKeyCode(), event.getModifiers(), true);
|
||||
proceedKeyEvent(event, stroke);
|
||||
return;
|
||||
}
|
||||
|
||||
myMnemonicsSearch.process(event);
|
||||
mySpeedSearch.process(event);
|
||||
|
||||
if (event.isConsumed()) return;
|
||||
process(event);
|
||||
}
|
||||
|
||||
private boolean proceedKeyEvent(KeyEvent event, KeyStroke stroke) {
|
||||
if (myInputMap.get(stroke) != null) {
|
||||
final Action action = myActionMap.get(myInputMap.get(stroke));
|
||||
if (action != null && action.isEnabled()) {
|
||||
action.actionPerformed(new ActionEvent(getContent(), event.getID(), "", event.getWhen(), event.getModifiers()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void process(KeyEvent aEvent) {
|
||||
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(getContent().getLocationOnScreen(), getContent().getSize());
|
||||
}
|
||||
|
||||
protected WizardPopup createPopup(WizardPopup parent, PopupStep step, Object parentValue) {
|
||||
if (step instanceof ListPopupStep) {
|
||||
return new ListPopupImpl(parent, (ListPopupStep)step, parentValue);
|
||||
}
|
||||
else if (step instanceof TreePopupStep) {
|
||||
return new TreePopupImpl(parent, (TreePopupStep)step, parentValue);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(step.getClass().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public final void actionPerformed(ActionEvent e) {
|
||||
myAutoSelectionTimer.stop();
|
||||
if (getStep().isAutoSelectionEnabled()) {
|
||||
onAutoSelectionTimer();
|
||||
}
|
||||
}
|
||||
|
||||
protected final void restartTimer() {
|
||||
if (!myAutoSelectionTimer.isRunning()) {
|
||||
myAutoSelectionTimer.start();
|
||||
}
|
||||
else {
|
||||
myAutoSelectionTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
protected final void stopTimer() {
|
||||
myAutoSelectionTimer.stop();
|
||||
}
|
||||
|
||||
protected void onAutoSelectionTimer() {
|
||||
|
||||
}
|
||||
|
||||
public boolean shouldBeShowing(Object value) {
|
||||
if (!myStep.isSpeedSearchEnabled()) return true;
|
||||
SpeedSearchFilter<Object> filter = myStep.getSpeedSearchFilter();
|
||||
if (!filter.canBeHidden(value)) return true;
|
||||
String text = filter.getIndexedString(value);
|
||||
return mySpeedSearch.shouldBeShowing(text);
|
||||
}
|
||||
|
||||
public SpeedSearch getSpeedSearch() {
|
||||
return mySpeedSearch;
|
||||
}
|
||||
|
||||
|
||||
protected void onSelectByMnemonic(Object value) {
|
||||
|
||||
}
|
||||
|
||||
protected abstract void onChildSelectedFor(Object value);
|
||||
|
||||
protected final void notifyParentOnChildSelection() {
|
||||
if (myParent == null || myParentValue == null) return;
|
||||
myParent.onChildSelectedFor(myParentValue);
|
||||
}
|
||||
|
||||
|
||||
private class MyComponentAdapter extends ComponentAdapter {
|
||||
public void componentMoved(final ComponentEvent e) {
|
||||
processParentWindowMoved();
|
||||
}
|
||||
}
|
||||
|
||||
public final void setFinalRunnable(Runnable runnable) {
|
||||
if (getParent() == null) {
|
||||
super.setFinalRunnable(runnable);
|
||||
} else {
|
||||
getParent().setFinalRunnable(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOk(boolean ok) {
|
||||
if (getParent() == null) {
|
||||
super.setOk(ok);
|
||||
} else {
|
||||
getParent().setOk(ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.popup;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.*;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.PopupBorder;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import com.intellij.ui.popup.tree.TreePopupImpl;
|
||||
import com.intellij.ui.popup.util.MnemonicsSearch;
|
||||
import com.intellij.ui.speedSearch.ElementFilter;
|
||||
import com.intellij.ui.speedSearch.SpeedSearch;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Collections;
|
||||
|
||||
public abstract class WizardPopup extends AbstractPopup implements ActionListener, ElementFilter {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.popup.WizardPopup");
|
||||
|
||||
private static final int AUTO_POPUP_DELAY = 750;
|
||||
private static final Dimension MAX_SIZE = new Dimension(Integer.MAX_VALUE, 600);
|
||||
|
||||
protected static final int STEP_X_PADDING = 2;
|
||||
|
||||
private final WizardPopup myParent;
|
||||
|
||||
protected final PopupStep<Object> myStep;
|
||||
protected WizardPopup myChild;
|
||||
|
||||
private final Timer myAutoSelectionTimer = UIUtil.createNamedTimer("Wizard autoselection",AUTO_POPUP_DELAY, this);
|
||||
|
||||
private MnemonicsSearch myMnemonicsSearch;
|
||||
private Object myParentValue;
|
||||
|
||||
private Point myLastOwnerPoint;
|
||||
private Window myOwnerWindow;
|
||||
private MyComponentAdapter myOwnerListener;
|
||||
|
||||
private final ActionMap myActionMap = new ActionMap();
|
||||
private final InputMap myInputMap = new InputMap();
|
||||
|
||||
public WizardPopup(PopupStep<Object> aStep) {
|
||||
this(null, aStep);
|
||||
}
|
||||
|
||||
public WizardPopup(JBPopup aParent, PopupStep<Object> aStep) {
|
||||
myParent = (WizardPopup) aParent;
|
||||
myStep = aStep;
|
||||
|
||||
mySpeedSearch.setEnabled(myStep.isSpeedSearchEnabled());
|
||||
|
||||
final JComponent content = createContent();
|
||||
|
||||
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(content);
|
||||
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.getHorizontalScrollBar().setBorder(null);
|
||||
|
||||
scrollPane.getActionMap().get("unitScrollLeft").setEnabled(false);
|
||||
scrollPane.getActionMap().get("unitScrollRight").setEnabled(false);
|
||||
|
||||
scrollPane.setBorder(null);
|
||||
|
||||
final Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
|
||||
init(project, scrollPane, getPreferredFocusableComponent(), true, true, true, true, null,
|
||||
false, aStep.getTitle(), null, true, null, false, null, null, null, false, null, true, false, true, null, 0f,
|
||||
null, true, false, new Component[0], null, SwingUtilities.LEFT, true, Collections.<Pair<ActionListener, KeyStroke>>emptyList(), null, null, false, true,
|
||||
true, null);
|
||||
|
||||
registerAction("disposeAll", KeyEvent.VK_ESCAPE, InputEvent.SHIFT_MASK, new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (mySpeedSearch.isHoldingFilter()) {
|
||||
mySpeedSearch.reset();
|
||||
}
|
||||
else {
|
||||
disposeAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AbstractAction goBackAction = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
goBack();
|
||||
}
|
||||
};
|
||||
|
||||
registerAction("goBack3", KeyEvent.VK_ESCAPE, 0, goBackAction);
|
||||
|
||||
myMnemonicsSearch = new MnemonicsSearch(this) {
|
||||
protected void select(Object value) {
|
||||
onSelectByMnemonic(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void disposeAll() {
|
||||
WizardPopup root = PopupDispatcher.getActiveRoot();
|
||||
disposeAllParents(null);
|
||||
root.getStep().canceled();
|
||||
}
|
||||
|
||||
public void goBack() {
|
||||
if (mySpeedSearch.isHoldingFilter()) {
|
||||
mySpeedSearch.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (myParent != null) {
|
||||
myParent.disposeChildren();
|
||||
}
|
||||
else {
|
||||
disposeAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract JComponent createContent();
|
||||
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
||||
myAutoSelectionTimer.stop();
|
||||
|
||||
PopupDispatcher.unsetShowing(this);
|
||||
PopupDispatcher.clearRootIfNeeded(this);
|
||||
|
||||
|
||||
if (myOwnerWindow != null && myOwnerListener != null) {
|
||||
myOwnerWindow.removeComponentListener(myOwnerListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void disposeChildren() {
|
||||
if (myChild != null) {
|
||||
myChild.disposeChildren();
|
||||
Disposer.dispose(myChild);
|
||||
myChild = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void show(final Component owner, final int aScreenX, final int aScreenY, final boolean considerForcedXY) {
|
||||
LOG.assertTrue (!isDisposed());
|
||||
|
||||
Rectangle targetBounds = new Rectangle(new Point(aScreenX, aScreenY), getContent().getPreferredSize());
|
||||
ScreenUtil.moveRectangleToFitTheScreen(targetBounds);
|
||||
|
||||
if (getParent() != null) {
|
||||
final Rectangle parentBounds = getParent().getBounds();
|
||||
parentBounds.x += STEP_X_PADDING;
|
||||
parentBounds.width -= STEP_X_PADDING * 2;
|
||||
if (parentBounds.intersects(targetBounds)) {
|
||||
targetBounds.x = getParent().getBounds().x - targetBounds.width - STEP_X_PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
if (getParent() == null) {
|
||||
PopupDispatcher.setActiveRoot(this);
|
||||
}
|
||||
else {
|
||||
PopupDispatcher.setShowing(this);
|
||||
}
|
||||
|
||||
LOG.assertTrue (!isDisposed(), "Disposed popup, parent="+getParent());
|
||||
super.show(owner, targetBounds.x, targetBounds.y, true);
|
||||
}
|
||||
|
||||
protected void afterShow() {
|
||||
super.afterShow();
|
||||
registerAutoMove();
|
||||
|
||||
if (!myFocusTrackback.isMustBeShown()) {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerAutoMove() {
|
||||
if (myOwner != null) {
|
||||
myOwnerWindow = SwingUtilities.getWindowAncestor(myOwner);
|
||||
if (myOwnerWindow != null) {
|
||||
myLastOwnerPoint = myOwnerWindow.getLocationOnScreen();
|
||||
myOwnerListener = new MyComponentAdapter();
|
||||
myOwnerWindow.addComponentListener(myOwnerListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processParentWindowMoved() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
final Point newOwnerPoint = myOwnerWindow.getLocationOnScreen();
|
||||
|
||||
int deltaX = myLastOwnerPoint.x - newOwnerPoint.x;
|
||||
int deltaY = myLastOwnerPoint.y - newOwnerPoint.y;
|
||||
|
||||
myLastOwnerPoint = newOwnerPoint;
|
||||
|
||||
final Window wnd = SwingUtilities.getWindowAncestor(getContent());
|
||||
final Point current = wnd.getLocationOnScreen();
|
||||
|
||||
setLocation(new Point(current.x - deltaX, current.y - deltaY));
|
||||
}
|
||||
|
||||
protected abstract JComponent getPreferredFocusableComponent();
|
||||
|
||||
public void cancel(InputEvent e) {
|
||||
super.cancel(e);
|
||||
disposeChildren();
|
||||
Disposer.dispose(this);
|
||||
getStep().canceled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelKeyEnabled() {
|
||||
return super.isCancelKeyEnabled() && !mySpeedSearch.isHoldingFilter();
|
||||
}
|
||||
|
||||
protected void disposeAllParents(InputEvent e) {
|
||||
myDisposeEvent = e;
|
||||
dispose();
|
||||
if (myParent != null) {
|
||||
myParent.disposeAllParents(null);
|
||||
}
|
||||
}
|
||||
|
||||
public final void registerAction(@NonNls String aActionName, int aKeyCode, @JdkConstants.InputEventMask int aModifier, Action aAction) {
|
||||
myInputMap.put(KeyStroke.getKeyStroke(aKeyCode, aModifier), aActionName);
|
||||
myActionMap.put(aActionName, aAction);
|
||||
}
|
||||
|
||||
protected String getActionForKeyStroke(final KeyStroke keyStroke) {
|
||||
return (String) myInputMap.get(keyStroke);
|
||||
}
|
||||
|
||||
public final void registerAction(@NonNls String aActionName, KeyStroke keyStroke, Action aAction) {
|
||||
myInputMap.put(keyStroke, aActionName);
|
||||
myActionMap.put(aActionName, aAction);
|
||||
}
|
||||
|
||||
protected abstract InputMap getInputMap();
|
||||
|
||||
protected abstract ActionMap getActionMap();
|
||||
|
||||
protected final void setParentValue(Object parentValue) {
|
||||
myParentValue = parentValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected MyContentPanel createContentPanel(final boolean resizable, final PopupBorder border, final boolean isToDrawMacCorner) {
|
||||
return new MyContainer(resizable, border, isToDrawMacCorner);
|
||||
}
|
||||
|
||||
private static class MyContainer extends MyContentPanel {
|
||||
|
||||
private MyContainer(final boolean resizable, final PopupBorder border, final boolean drawMacCorner) {
|
||||
super(resizable, border, drawMacCorner);
|
||||
setOpaque(true);
|
||||
setFocusCycleRoot(true);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
Point p = null;
|
||||
if (focusOwner != null && focusOwner.isShowing()) {
|
||||
p = focusOwner.getLocationOnScreen();
|
||||
}
|
||||
|
||||
return computeNotBiggerDimension(super.getPreferredSize().getSize(), p);
|
||||
}
|
||||
|
||||
private static Dimension computeNotBiggerDimension(Dimension ofContent, final Point locationOnScreen) {
|
||||
int resultHeight = ofContent.height > MAX_SIZE.height + 50 ? MAX_SIZE.height : ofContent.height;
|
||||
if (locationOnScreen != null) {
|
||||
final Rectangle r = ScreenUtil.getScreenRectangle(locationOnScreen);
|
||||
resultHeight = ofContent.height > r.height - (r.height / 4) ? r.height - (r.height / 4) : ofContent.height;
|
||||
}
|
||||
|
||||
int resultWidth = ofContent.width > MAX_SIZE.width ? MAX_SIZE.width : ofContent.width;
|
||||
|
||||
if (ofContent.height > MAX_SIZE.height) {
|
||||
resultWidth += ScrollPaneFactory.createScrollPane().getVerticalScrollBar().getPreferredSize().getWidth();
|
||||
}
|
||||
|
||||
return new Dimension(resultWidth, resultHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public WizardPopup getParent() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
public PopupStep getStep() {
|
||||
return myStep;
|
||||
}
|
||||
|
||||
public final void dispatch(KeyEvent event) {
|
||||
if (event.getID() != KeyEvent.KEY_PRESSED && event.getID() != KeyEvent.KEY_RELEASED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getID() == KeyEvent.KEY_PRESSED) {
|
||||
final KeyStroke stroke = KeyStroke.getKeyStroke(event.getKeyCode(), event.getModifiers(), false);
|
||||
if (proceedKeyEvent(event, stroke)) return;
|
||||
}
|
||||
|
||||
if (event.getID() == KeyEvent.KEY_RELEASED) {
|
||||
final KeyStroke stroke = KeyStroke.getKeyStroke(event.getKeyCode(), event.getModifiers(), true);
|
||||
proceedKeyEvent(event, stroke);
|
||||
return;
|
||||
}
|
||||
|
||||
myMnemonicsSearch.process(event);
|
||||
mySpeedSearch.process(event);
|
||||
|
||||
if (event.isConsumed()) return;
|
||||
process(event);
|
||||
}
|
||||
|
||||
private boolean proceedKeyEvent(KeyEvent event, KeyStroke stroke) {
|
||||
if (myInputMap.get(stroke) != null) {
|
||||
final Action action = myActionMap.get(myInputMap.get(stroke));
|
||||
if (action != null && action.isEnabled()) {
|
||||
action.actionPerformed(new ActionEvent(getContent(), event.getID(), "", event.getWhen(), event.getModifiers()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void process(KeyEvent aEvent) {
|
||||
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(getContent().getLocationOnScreen(), getContent().getSize());
|
||||
}
|
||||
|
||||
protected WizardPopup createPopup(WizardPopup parent, PopupStep step, Object parentValue) {
|
||||
if (step instanceof ListPopupStep) {
|
||||
return new ListPopupImpl(parent, (ListPopupStep)step, parentValue);
|
||||
}
|
||||
else if (step instanceof TreePopupStep) {
|
||||
return new TreePopupImpl(parent, (TreePopupStep)step, parentValue);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(step.getClass().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public final void actionPerformed(ActionEvent e) {
|
||||
myAutoSelectionTimer.stop();
|
||||
if (getStep().isAutoSelectionEnabled()) {
|
||||
onAutoSelectionTimer();
|
||||
}
|
||||
}
|
||||
|
||||
protected final void restartTimer() {
|
||||
if (!myAutoSelectionTimer.isRunning()) {
|
||||
myAutoSelectionTimer.start();
|
||||
}
|
||||
else {
|
||||
myAutoSelectionTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
protected final void stopTimer() {
|
||||
myAutoSelectionTimer.stop();
|
||||
}
|
||||
|
||||
protected void onAutoSelectionTimer() {
|
||||
|
||||
}
|
||||
|
||||
public boolean shouldBeShowing(Object value) {
|
||||
if (!myStep.isSpeedSearchEnabled()) return true;
|
||||
SpeedSearchFilter<Object> filter = myStep.getSpeedSearchFilter();
|
||||
if (!filter.canBeHidden(value)) return true;
|
||||
String text = filter.getIndexedString(value);
|
||||
return mySpeedSearch.shouldBeShowing(text);
|
||||
}
|
||||
|
||||
public SpeedSearch getSpeedSearch() {
|
||||
return mySpeedSearch;
|
||||
}
|
||||
|
||||
|
||||
protected void onSelectByMnemonic(Object value) {
|
||||
|
||||
}
|
||||
|
||||
protected abstract void onChildSelectedFor(Object value);
|
||||
|
||||
protected final void notifyParentOnChildSelection() {
|
||||
if (myParent == null || myParentValue == null) return;
|
||||
myParent.onChildSelectedFor(myParentValue);
|
||||
}
|
||||
|
||||
|
||||
private class MyComponentAdapter extends ComponentAdapter {
|
||||
public void componentMoved(final ComponentEvent e) {
|
||||
processParentWindowMoved();
|
||||
}
|
||||
}
|
||||
|
||||
public final void setFinalRunnable(Runnable runnable) {
|
||||
if (getParent() == null) {
|
||||
super.setFinalRunnable(runnable);
|
||||
} else {
|
||||
getParent().setFinalRunnable(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOk(boolean ok) {
|
||||
if (getParent() == null) {
|
||||
super.setOk(ok);
|
||||
} else {
|
||||
getParent().setOk(ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user