mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-167805 Keyboard navigation in debug tool window
GitOrigin-RevId: 1b07992e854cfa45714154c4cf8cca109d7c36d7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6f5dde8f50
commit
1437c1dcd3
@@ -323,7 +323,7 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
final ThreadsPanel panel = new ThreadsPanel(myJavaSession.getProject(), getDebuggerStateManager());
|
||||
final Content threadsContent = ui.createContent(
|
||||
DebuggerContentInfo.THREADS_CONTENT, panel, XDebuggerBundle.message("debugger.session.tab.threads.title"),
|
||||
null, null);
|
||||
null, panel.getDefaultFocusedComponent());
|
||||
threadsContent.setCloseable(false);
|
||||
ui.addContent(threadsContent, 0, PlaceInGrid.left, true);
|
||||
ui.addListener(new ContentManagerAdapter() {
|
||||
@@ -355,7 +355,7 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
|
||||
final Content memoryViewContent =
|
||||
ui.createContent(MemoryViewManager.MEMORY_VIEW_CONTENT, classesFilteredView, "Memory",
|
||||
null, null);
|
||||
null, classesFilteredView.getDefaultFocusedComponent());
|
||||
|
||||
memoryViewContent.setCloseable(false);
|
||||
memoryViewContent.setShouldDisposeContent(true);
|
||||
@@ -387,7 +387,7 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
|
||||
DebugProcessImpl process = myJavaSession.getProcess();
|
||||
OverheadView monitor = new OverheadView(process);
|
||||
Content overheadContent = ui.createContent("OverheadMonitor", monitor, "Overhead", null, null);
|
||||
Content overheadContent = ui.createContent("OverheadMonitor", monitor, "Overhead", null, monitor.getDefaultFocusedComponent());
|
||||
|
||||
monitor.setBouncer(() -> ui.setBouncing(overheadContent, true));
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.util.Alarm;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
@@ -125,6 +126,10 @@ public class ThreadsPanel extends DebuggerTreePanel{
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public JComponent getDefaultFocusedComponent() {
|
||||
return getThreadsTree();
|
||||
}
|
||||
|
||||
private static void updateNodeLabels(DebuggerTreeNodeImpl from) {
|
||||
Enumeration children = from.children();
|
||||
try {
|
||||
|
||||
@@ -121,6 +121,11 @@ public class OverheadView extends BorderLayoutPanel implements Disposable, DataP
|
||||
.map(XBreakpoint::getNavigatable).nonNull();
|
||||
}
|
||||
|
||||
|
||||
public JComponent getDefaultFocusedComponent() {
|
||||
return myTable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getData(@NotNull String dataId) {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
package com.intellij.execution.ui.layout.impl;
|
||||
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.RunContentManager;
|
||||
import com.intellij.execution.ui.RunnerLayoutUi;
|
||||
import com.intellij.execution.ui.layout.*;
|
||||
import com.intellij.execution.ui.layout.actions.CloseViewAction;
|
||||
@@ -10,11 +12,17 @@ import com.intellij.execution.ui.layout.actions.RestoreViewAction;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.actions.CloseAction;
|
||||
import com.intellij.ide.actions.ShowContentAction;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.AbstractPainter;
|
||||
import com.intellij.openapi.ui.ShadowAction;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.ActiveRunnable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
@@ -25,6 +33,7 @@ import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.IdeGlassPaneUtil;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.impl.ToolWindowsPane;
|
||||
import com.intellij.openapi.wm.impl.content.SelectContentStep;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
@@ -41,6 +50,7 @@ import com.intellij.ui.tabs.JBTabs;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.TabsListener;
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -67,6 +77,8 @@ import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.intellij.ui.tabs.JBTabsEx.NAVIGATION_ACTIONS_KEY;
|
||||
|
||||
public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Facade, ViewContextEx, PropertyChangeListener,
|
||||
QuickActionProvider, DockContainer.Dialog {
|
||||
public static final DataKey<RunnerContentUi> KEY = DataKey.create("DebuggerContentUI");
|
||||
@@ -77,6 +89,8 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
@NonNls private static final String VIEW_POPUP = "Runner.View.Popup";
|
||||
@NonNls static final String VIEW_TOOLBAR = "Runner.View.Toolbar";
|
||||
|
||||
private ShowDebugContentAction myShowDebugContentAction = null;
|
||||
|
||||
private ContentManager myManager;
|
||||
private final RunnerLayout myLayoutSettings;
|
||||
|
||||
@@ -320,6 +334,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
|
||||
DefaultActionGroup group = new DefaultActionGroup(VIEW_POPUP, original.isPopup());
|
||||
|
||||
if (myShowDebugContentAction == null) {
|
||||
myShowDebugContentAction = new ShowDebugContentAction(this, myTabs.getComponent(), this);
|
||||
}
|
||||
group.add(myShowDebugContentAction);
|
||||
|
||||
final AnActionEvent event = new AnActionEvent(null, DataManager.getInstance().getDataContext(), place, new Presentation(),
|
||||
ActionManager.getInstance(), 0);
|
||||
final AnAction[] originalActions = original.getChildren(event);
|
||||
@@ -585,6 +604,45 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
return myCurrentOverImg;
|
||||
}
|
||||
|
||||
public void toggleContentPopup(JBTabs tabs) {
|
||||
if (myOriginal != null) {
|
||||
myOriginal.toggleContentPopup(tabs);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Content> contents = getPopupContents();
|
||||
final Content selectedContent = myManager.getSelectedContent();
|
||||
final SelectContentStep step = new SelectContentStep(contents);
|
||||
if (selectedContent != null) {
|
||||
step.setDefaultOptionIndex(myManager.getIndexOfContent(selectedContent));
|
||||
}
|
||||
|
||||
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(step);
|
||||
popup.showUnderneathOf(tabs.getTabLabel(tabs.getSelectedInfo()));
|
||||
|
||||
if (selectedContent instanceof TabbedContent) {
|
||||
new Alarm(Alarm.ThreadToUse.SWING_THREAD, popup).addRequest(() -> popup.handleSelect(false), 50);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Content> getPopupContents() {
|
||||
if (myOriginal != null) return myOriginal.getPopupContents();
|
||||
|
||||
List<Content> contents = new ArrayList<>(Arrays.asList(myManager.getContents()));
|
||||
myChildren.stream()
|
||||
.flatMap(child -> Arrays.stream(child.myManager.getContents()))
|
||||
.forEachOrdered(contents::add);
|
||||
|
||||
RunContentManager contentManager = RunContentManager.getInstance(myProject);
|
||||
RunContentDescriptor selectedDescriptor = contentManager.getSelectedContent();
|
||||
|
||||
contentManager.getAllDescriptors().stream()
|
||||
.filter(descriptor -> descriptor != selectedDescriptor)
|
||||
.map(descriptor -> descriptor.getAttachedContent())
|
||||
.forEachOrdered(contents::add);
|
||||
return contents;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PlaceInGrid calcPlaceInGrid(Point point, Dimension size) {
|
||||
// 1/3 (left) | (center/bottom) | 1/3 (right)
|
||||
@@ -1889,6 +1947,34 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
}
|
||||
|
||||
public class ShowDebugContentAction extends AnAction implements DumbAware {
|
||||
public static final String ACTION_ID = "ShowDebugContent";
|
||||
|
||||
private RunnerContentUi myContentUi;
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public ShowDebugContentAction() {
|
||||
}
|
||||
|
||||
public ShowDebugContentAction(RunnerContentUi runner, JComponent component, @NotNull Disposable parentDisposable) {
|
||||
myContentUi = runner;
|
||||
AnAction original = ActionManager.getInstance().getAction(ShowContentAction.ACTION_ID);
|
||||
new ShadowAction(this, original, component, parentDisposable);
|
||||
ActionUtil.copyFrom(this, ShowContentAction.ACTION_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
e.getPresentation().setEnabledAndVisible(myContentUi != null && myContentUi.getPopupContents().size() > 1);
|
||||
e.getPresentation().setText("Show List of Tabs");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
myContentUi.toggleContentPopup(e.getData(NAVIGATION_ACTIONS_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
private void fireContentOpened(@NotNull Content content) {
|
||||
for (Listener each : myDockingListeners) {
|
||||
each.contentAdded(content);
|
||||
|
||||
@@ -79,14 +79,17 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
|
||||
@SuppressWarnings("Duplicates")
|
||||
public Component getComponentAfter(Container aContainer, Component aComponent) {
|
||||
Component comp;
|
||||
if (aComponent == myFirstComponent) {
|
||||
comp = findChildToFocus(myInnerComponent);
|
||||
if (SwingUtilities.isDescendingFrom(aComponent, myFirstComponent)) {
|
||||
Component next = nextVisible(myFirstComponent);
|
||||
comp = (next != null) ? findChildToFocus(next) : aComponent;
|
||||
}
|
||||
else if (aComponent == myInnerComponent) {
|
||||
comp = findChildToFocus(myLastComponent);
|
||||
else if (SwingUtilities.isDescendingFrom(aComponent, myInnerComponent)) {
|
||||
Component next = nextVisible(myInnerComponent);
|
||||
comp = (next != null) ? findChildToFocus(next) : aComponent;
|
||||
}
|
||||
else {
|
||||
comp = findChildToFocus(myFirstComponent);
|
||||
Component next = nextVisible(myLastComponent);
|
||||
comp = (next != null) ? findChildToFocus(next) : aComponent;
|
||||
}
|
||||
if (comp == aComponent) {
|
||||
// if focus is stuck on the component let it go further
|
||||
@@ -99,14 +102,17 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
|
||||
@SuppressWarnings("Duplicates")
|
||||
public Component getComponentBefore(Container aContainer, Component aComponent) {
|
||||
Component comp;
|
||||
if (aComponent == myInnerComponent) {
|
||||
comp = findChildToFocus(myFirstComponent);
|
||||
if (SwingUtilities.isDescendingFrom(aComponent, myInnerComponent)) {
|
||||
Component prev = prevVisible(myInnerComponent);
|
||||
comp = (prev != null) ? findChildToFocus(prev) : aComponent;
|
||||
}
|
||||
else if (aComponent == myLastComponent) {
|
||||
comp = findChildToFocus(myInnerComponent);
|
||||
else if (SwingUtilities.isDescendingFrom(aComponent, myLastComponent)) {
|
||||
Component prev = prevVisible(myLastComponent);
|
||||
comp = (prev != null) ? findChildToFocus(prev) : aComponent;
|
||||
}
|
||||
else {
|
||||
comp = findChildToFocus(myFirstComponent);
|
||||
Component prev = prevVisible(myFirstComponent);
|
||||
comp = (prev != null) ? findChildToFocus(prev) : aComponent;
|
||||
}
|
||||
if (comp == aComponent) {
|
||||
// if focus is stuck on the component let it go further
|
||||
@@ -115,14 +121,33 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
|
||||
return comp;
|
||||
}
|
||||
|
||||
private Component nextVisible(Component comp) {
|
||||
if (comp == myFirstComponent) return innerVisible() ? myInnerComponent : lastVisible() ? myLastComponent : null;
|
||||
if (comp == myInnerComponent) return lastVisible() ? myLastComponent : firstVisible() ? myFirstComponent : null;
|
||||
if (comp == myLastComponent) return firstVisible() ? myFirstComponent : innerVisible() ? myInnerComponent : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Component prevVisible(Component comp) {
|
||||
if (comp == myFirstComponent) return lastVisible() ? myLastComponent : innerVisible() ? myInnerComponent : null;
|
||||
if (comp == myInnerComponent) return firstVisible() ? myFirstComponent : lastVisible() ? myLastComponent : null;
|
||||
if (comp == myLastComponent) return innerVisible() ? myInnerComponent : firstVisible() ? myFirstComponent : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getFirstComponent(Container aContainer) {
|
||||
return findChildToFocus(myFirstComponent);
|
||||
if (firstVisible()) return findChildToFocus(myFirstComponent);
|
||||
Component next = nextVisible(myFirstComponent);
|
||||
return next != null ? findChildToFocus(next) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getLastComponent(Container aContainer) {
|
||||
return findChildToFocus(myLastComponent);
|
||||
if (lastVisible()) return findChildToFocus(myLastComponent);
|
||||
Component prev = prevVisible(myLastComponent);
|
||||
return prev != null ? findChildToFocus(prev) : null;
|
||||
}
|
||||
|
||||
private boolean myReentrantLock = false;
|
||||
@@ -131,7 +156,9 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
|
||||
if (myReentrantLock) return null;
|
||||
try {
|
||||
myReentrantLock = true;
|
||||
return findChildToFocus(myInnerComponent);
|
||||
if (innerVisible()) return findChildToFocus(myInnerComponent);
|
||||
Component next = nextVisible(myLastComponent);
|
||||
return next != null ? findChildToFocus(next) : null;
|
||||
} finally {
|
||||
myReentrantLock = false;
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
|
||||
mySelectionHistory.remove(content);
|
||||
mySelectionHistory.add(0, content);
|
||||
if (isSelected(content) && requestFocus) {
|
||||
return requestFocus(content, forcedFocus);
|
||||
return getFocusManager().requestFocus(getComponent(), true).doWhenProcessed(() -> requestFocus(content, forcedFocus));
|
||||
}
|
||||
|
||||
if (!checkSelectionChangeShouldBeProcessed(content, implicit)) {
|
||||
|
||||
+4
@@ -170,6 +170,10 @@ public abstract class ClassesFilteredViewBase extends BorderLayoutPanel implemen
|
||||
addToCenter(scroll);
|
||||
}
|
||||
|
||||
public JComponent getDefaultFocusedComponent() {
|
||||
return myFilterTextField;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ClassesTable createClassesTable(MemoryViewManagerState memoryViewManagerState) {
|
||||
return new ClassesTable(myProject,this, memoryViewManagerState.isShowWithDiffOnly,
|
||||
|
||||
Reference in New Issue
Block a user