NavBar fixes IDEA-70474, IDEA-66157, IDEA-66559 (Alt+Home and then quickly Alt+Insert result in navigation bar collapse and the Generate action working as if it were invoked in the editor)

This commit is contained in:
Konstantin Bulenkov
2011-06-06 19:36:38 +04:00
parent 5f3617f1bc
commit c6b09c100c
3 changed files with 56 additions and 153 deletions
@@ -33,12 +33,9 @@ import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.actions.ModuleDeleteProvider;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -53,16 +50,17 @@ import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.popup.AbstractPopup;
import com.intellij.ui.popup.PopupOwner;
import com.intellij.ui.popup.list.ListPopupImpl;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
@@ -82,10 +80,7 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
private final IdeView myIdeView;
private final CopyPasteDelegator myCopyPasteDelegator;
private LightweightHint myHint = null;
private NavBarPopup myNodeHint = null;
private ListPopupImpl myNodePopup = null;
private NavBarPopup myNodePopup = null;
private JComponent myHintContainer;
private Component myContextComponent;
@@ -94,7 +89,6 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
private NavBarItem myContextObject;
private boolean myDisposed = false;
private RelativePoint myLocationCache;
private boolean initialized = false;
public NavBarPanel(final Project project) {
super(new FlowLayout(FlowLayout.LEFT, 5, 0));
@@ -123,8 +117,7 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
}
public boolean isNodePopupActive() {
return (myNodePopup != null && myNodePopup.isVisible() && myNodePopup.isFocused())
|| (myNodeHint != null && myNodeHint.isVisible());
return myNodePopup != null && myNodePopup.isVisible();
}
public LightweightHint getHint() {
@@ -207,7 +200,7 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
boolean isSelectedInPopup(Object object) {
if (isNodePopupActive()) {
return myNodeHint.getSelectedValue() == object;
return myNodePopup.getSelectedValue() == object;
}
return false;
}
@@ -416,7 +409,7 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
}
final Object object = myModel.getElement(index);
final java.util.List<Object> objects = myModel.getChildren(object);
final List<Object> objects = myModel.getChildren(object);
if (!objects.isEmpty()) {
final Object[] siblings = new Object[objects.size()];
@@ -426,74 +419,16 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
icons[i] = NavBarPresentation.getIcon(siblings[i], false);
}
final NavBarItem item = getItem(index);
final BaseListPopupStep<Object> step;
if (Registry.is("navbar.newpopup")) {
myNodePopup = null;
myNodeHint = new NavBarPopup(this, siblings, index < myModel.size() - 1 ? objects.indexOf(myModel.getElement(index + 1)) : 0);
if (item != null && item.isShowing()) {
myNodeHint.show(item);
}
} else {
myNodeHint = null;
step = new BaseListPopupStep<Object>("", siblings, icons) {
public boolean isSpeedSearchEnabled() {
return true;
}
@NotNull
public String getTextFor(final Object value) {
return NavBarPresentation.getPresentableText(value, null);
}
public PopupStep onChosen(final Object selectedValue, final boolean finalChoice) {
return doFinalStep(new Runnable() {
public void run() {
navigateInsideBar(selectedValue);
}
});
}
};
step.setDefaultOptionIndex(index < myModel.size() - 1 ? objects.indexOf(myModel.getElement(index + 1)) : 0);
myNodePopup = new ListPopupImpl(step) {
protected ListCellRenderer getListElementRenderer() {
return new NavBarListCellRenderer(myProject, NavBarPanel.this);
}
@Override
public void cancel(InputEvent e) {
super.cancel(e);
}
};
myNodePopup.registerAction("left", KeyEvent.VK_LEFT, 0, new AbstractAction() {
public void actionPerformed(ActionEvent e) {
myNodePopup.goBack();
shiftFocus(-1);
restorePopup();
}
});
myNodePopup.registerAction("right", KeyEvent.VK_RIGHT, 0, new AbstractAction() {
public void actionPerformed(ActionEvent e) {
myNodePopup.goBack();
shiftFocus(1);
restorePopup();
}
});
if (!isValid()) {
validate();
}
if (item != null && item.isShowing() && step.getValues().size() > 0) {
myNodePopup.showUnderneathOf(item);
}
myNodePopup = new NavBarPopup(this, siblings, index < myModel.size() - 1 ? objects.indexOf(myModel.getElement(index + 1)) : 0);
if (item != null && item.isShowing()) {
myNodePopup.show(item);
}
}
}
boolean isNodePopupShowing() {
return (myNodePopup != null && myNodePopup.isVisible())
|| (myNodeHint != null && myNodeHint.isVisible());
return myNodePopup != null && myNodePopup.isVisible();
}
void navigateInsideBar(final Object object) {
@@ -538,12 +473,8 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
}
void cancelPopup() {
if (myNodeHint != null) {
myNodeHint.hide();
myNodeHint = null;
}
if (myNodePopup != null) {
myNodePopup.cancel();
myNodePopup.hide();
myNodePopup = null;
}
}
@@ -628,8 +559,8 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
@SuppressWarnings({"unchecked"})
<T> T getSelectedElement(Class<T> klass) {
Object value = null;
if (myNodeHint != null) {
value = myNodeHint.getSelectedValue();
if (myNodePopup != null) {
value = myNodePopup.getSelectedValue();
}
if (value == null) value = myModel.getSelectedValue();
if (value == null) {
@@ -687,80 +618,52 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis
// ------ popup NavBar ----------
public void showHint(@Nullable final Editor editor, final DataContext dataContext) {
myUpdateQueue.queueModelUpdate(dataContext);
myUpdateQueue.queueAfterAll(new Runnable() {
@Override
public void run() {
if (myModel.isEmpty()) return;
final JPanel panel = new JPanel(new BorderLayout());
panel.add(NavBarPanel.this);
panel.setOpaque(true);
panel.setBackground(UIUtil.isUnderGTKLookAndFeel() ? Color.WHITE : UIUtil.getListBackground());
myModel.updateModel(dataContext);
if (myModel.isEmpty()) return;
final JPanel panel = new JPanel(new BorderLayout());
panel.add(this);
panel.setOpaque(true);
panel.setBackground(UIUtil.isUnderGTKLookAndFeel() ? Color.WHITE : UIUtil.getListBackground());
myHint = new LightweightHint(panel) {
public void hide() {
super.hide();
cancelPopup();
Disposer.dispose(NavBarPanel.this);
myHint = new LightweightHint(panel) {
public void hide() {
super.hide();
cancelPopup();
Disposer.dispose(NavBarPanel.this);
}
};
myHint.setForceShowAsPopup(true);
myHint.setFocusRequestor(this);
final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
myUpdateQueue.rebuildUi();
if (editor == null) {
myContextComponent = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
getHintContainerShowPoint().doWhenDone(new AsyncResult.Handler<RelativePoint>() {
@Override
public void run(RelativePoint relativePoint) {
final Component owner = focusManager.getFocusOwner();
final Component cmp = relativePoint.getComponent();
if (cmp instanceof JComponent && cmp.isShowing()) {
myHint.show((JComponent)cmp, relativePoint.getPoint().x, relativePoint.getPoint().y,
owner instanceof JComponent ? (JComponent)owner : null,
new HintHint(relativePoint.getComponent(), relativePoint.getPoint()));
}
};
myHint.setForceShowAsPopup(true);
myHint.setFocusRequestor(NavBarPanel.this);
final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
if (editor == null) {
myContextComponent = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
getHintContainerShowPoint().doWhenDone(new AsyncResult.Handler<RelativePoint>() {
@Override
public void run(RelativePoint relativePoint) {
final Component owner = focusManager.getFocusOwner();
final Component cmp = relativePoint.getComponent();
if (cmp instanceof JComponent && cmp.isShowing()) {
myHint.show((JComponent)cmp, relativePoint.getPoint().x, relativePoint.getPoint().y,
owner instanceof JComponent ? (JComponent)owner : null,
new HintHint(relativePoint.getComponent(), relativePoint.getPoint()));
}
}
});
} else {
myHintContainer = editor.getContentComponent();
getHintContainerShowPoint().doWhenDone(new AsyncResult.Handler<RelativePoint>() {
@Override
public void run(RelativePoint rp) {
Point p = rp.getPointOn(myHintContainer).getPoint();
final HintHint hintInfo = new HintHint(editor, p);
HintManagerImpl.getInstanceImpl().showEditorHint(myHint, editor, p, HintManager.HIDE_BY_ESCAPE, 0, true, hintInfo);
}
});
}
selectTail();
}
}, NavBarUpdateQueue.ID.SHOW_HINT);
}
public void activatePopupOnLastElement() {
activatePopupOnLastElement(null);
}
public void activatePopupOnLastElement(@Nullable DataContext context) {
if (context != null) {
myUpdateQueue.queueModelUpdate(context);
});
}
myUpdateQueue.queueRebuildUi();
myUpdateQueue.queueSelect(new Runnable() {
@Override
public void run() {
if (!myList.isEmpty()) {
myModel.setSelectedIndex(Math.max(myList.size() - 2, 0));
IdeFocusManager.getInstance(myProject).requestFocus(NavBarPanel.this, true);
restorePopup();
initialized = true;
else {
myHintContainer = editor.getContentComponent();
getHintContainerShowPoint().doWhenDone(new AsyncResult.Handler<RelativePoint>() {
@Override
public void run(RelativePoint rp) {
Point p = rp.getPointOn(myHintContainer).getPoint();
final HintHint hintInfo = new HintHint(editor, p);
HintManagerImpl.getInstanceImpl().showEditorHint(myHint, editor, p, HintManager.HIDE_BY_ESCAPE, 0, true, hintInfo);
}
}
});
});
}
myUpdateQueue.flush();
selectTail();
}
AsyncResult<RelativePoint> getHintContainerShowPoint() {
@@ -85,7 +85,7 @@ public class NavBarPresentation {
}
@NotNull
protected static String getPresentableText(final Object object, Window window) {
protected static String getPresentableText(final Object object, @Nullable Window window) {
if (!NavBarModel.isValid(object)) return IdeBundle.message("node.structureview.invalid");
for (NavBarModelExtension modelExtension : Extensions.getExtensions(NavBarModelExtension.EP_NAME)) {
String text = modelExtension.getPresentableText(object);
@@ -181,7 +181,7 @@ public class NavBarUpdateQueue extends MergingUpdateQueue {
queueRevalidate(null);
}
private void rebuildUi() {
public void rebuildUi() {
if (!myPanel.isRebuildUiNeeded()) return;
myPanel.getItems().clear();