636 lines
18 KiB
Java
636 lines
18 KiB
Java
package jadx.gui.ui.tab;
|
|
|
|
import java.awt.Component;
|
|
import java.awt.KeyEventDispatcher;
|
|
import java.awt.KeyboardFocusManager;
|
|
import java.awt.event.FocusEvent;
|
|
import java.awt.event.FocusListener;
|
|
import java.awt.event.KeyEvent;
|
|
import java.awt.event.MouseAdapter;
|
|
import java.awt.event.MouseEvent;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import javax.swing.JTabbedPane;
|
|
import javax.swing.SwingUtilities;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import jadx.core.utils.exceptions.JadxRuntimeException;
|
|
import jadx.gui.jobs.SilentTask;
|
|
import jadx.gui.treemodel.JClass;
|
|
import jadx.gui.treemodel.JNode;
|
|
import jadx.gui.ui.MainWindow;
|
|
import jadx.gui.ui.codearea.AbstractCodeArea;
|
|
import jadx.gui.ui.codearea.AbstractCodeContentPanel;
|
|
import jadx.gui.ui.codearea.ClassCodeContentPanel;
|
|
import jadx.gui.ui.codearea.EditorViewState;
|
|
import jadx.gui.ui.codearea.SmaliArea;
|
|
import jadx.gui.ui.panel.ContentPanel;
|
|
import jadx.gui.ui.panel.FontPanel;
|
|
import jadx.gui.ui.panel.HtmlPanel;
|
|
import jadx.gui.ui.panel.IViewStateSupport;
|
|
import jadx.gui.ui.panel.ImagePanel;
|
|
import jadx.gui.ui.tab.dnd.TabDndController;
|
|
import jadx.gui.utils.JumpPosition;
|
|
import jadx.gui.utils.UiUtils;
|
|
|
|
public class TabbedPane extends JTabbedPane implements ITabStatesListener {
|
|
private static final long serialVersionUID = -8833600618794570904L;
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(TabbedPane.class);
|
|
|
|
private final transient MainWindow mainWindow;
|
|
private final transient TabsController controller;
|
|
private final transient Map<JNode, ContentPanel> tabsMap = new HashMap<>();
|
|
|
|
private transient ContentPanel curTab;
|
|
private transient ContentPanel lastTab;
|
|
|
|
private transient TabDndController dnd;
|
|
|
|
public TabbedPane(MainWindow window, TabsController controller) {
|
|
this.mainWindow = window;
|
|
this.controller = controller;
|
|
|
|
controller.addListener(this);
|
|
setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
|
|
|
|
MouseAdapter clickAdapter = new MouseAdapter() {
|
|
@Override
|
|
public void mousePressed(MouseEvent e) {
|
|
int tabIndex = indexAtLocation(e.getX(), e.getY());
|
|
if (tabIndex == -1 || tabIndex > getTabCount()) {
|
|
return;
|
|
}
|
|
TabComponent tab = (TabComponent) getTabComponentAt(tabIndex);
|
|
tab.dispatchEvent(e);
|
|
}
|
|
};
|
|
addMouseListener(clickAdapter);
|
|
|
|
addMouseWheelListener(event -> {
|
|
if (dnd != null && dnd.isDragging()) {
|
|
return;
|
|
}
|
|
int direction = event.getWheelRotation();
|
|
if (getTabCount() == 0 || direction == 0) {
|
|
return;
|
|
}
|
|
direction = (direction < 0) ? -1 : 1; // normalize direction
|
|
int index = getSelectedIndex();
|
|
int maxIndex = getTabCount() - 1;
|
|
index += direction;
|
|
index = Math.max(0, Math.min(maxIndex, index));
|
|
try {
|
|
setSelectedIndex(index);
|
|
} catch (IndexOutOfBoundsException e) {
|
|
// ignore error
|
|
}
|
|
});
|
|
interceptTabKey();
|
|
interceptCloseKey();
|
|
enableSwitchingTabs();
|
|
}
|
|
|
|
private void interceptTabKey() {
|
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
|
|
private static final int ctrlDown = KeyEvent.CTRL_DOWN_MASK;
|
|
private long ctrlInterval = 0;
|
|
|
|
@Override
|
|
public boolean dispatchKeyEvent(KeyEvent e) {
|
|
long cur = System.currentTimeMillis();
|
|
if (!FocusManager.isActive()) {
|
|
return false; // don't do nothing when tab is not on focus.
|
|
}
|
|
int code = e.getKeyCode();
|
|
boolean consume = code == KeyEvent.VK_TAB; // consume Tab key event anyway
|
|
boolean isReleased = e.getID() == KeyEvent.KEY_RELEASED;
|
|
if (isReleased) {
|
|
if (code == KeyEvent.VK_CONTROL) {
|
|
ctrlInterval = cur;
|
|
} else if (code == KeyEvent.VK_TAB) {
|
|
boolean doSwitch = false;
|
|
if ((e.getModifiersEx() & ctrlDown) != 0) {
|
|
doSwitch = lastTab != null && getTabCount() > 1;
|
|
} else {
|
|
// the gap of the release of ctrl and tab is very close, nearly the same time,
|
|
// but ctrl released first.
|
|
ctrlInterval = cur - ctrlInterval;
|
|
if (ctrlInterval <= 90) {
|
|
doSwitch = lastTab != null && getTabCount() > 1;
|
|
}
|
|
}
|
|
if (doSwitch) {
|
|
selectTab(lastTab);
|
|
}
|
|
}
|
|
} else if (consume && (e.getModifiersEx() & ctrlDown) == 0) {
|
|
// switch between source and smali
|
|
if (curTab instanceof ClassCodeContentPanel) {
|
|
((ClassCodeContentPanel) curTab).switchPanel();
|
|
}
|
|
}
|
|
return consume;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void interceptCloseKey() {
|
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
|
|
private static final int closeKey = KeyEvent.VK_W;
|
|
private boolean canClose = true;
|
|
|
|
@Override
|
|
public boolean dispatchKeyEvent(KeyEvent e) {
|
|
if (!FocusManager.isActive()) {
|
|
return false; // do nothing when tab is not on focus.
|
|
}
|
|
if (e.getKeyCode() != closeKey) {
|
|
return false; // only intercept the events of the close key
|
|
}
|
|
if (e.getID() == KeyEvent.KEY_RELEASED) {
|
|
canClose = true; // after the close key is lifted we allow to use it again
|
|
return false;
|
|
}
|
|
if (e.isControlDown() && canClose) {
|
|
// close the current tab
|
|
closeCodePanel(curTab);
|
|
canClose = false; // make sure we dont close more tabs until the close key is lifted
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void enableSwitchingTabs() {
|
|
addChangeListener(e -> {
|
|
ContentPanel tab = getSelectedContentPanel();
|
|
if (tab == null) { // all closed
|
|
curTab = null;
|
|
lastTab = null;
|
|
return;
|
|
}
|
|
FocusManager.focusOnCodePanel(tab);
|
|
if (tab == curTab) { // a tab was closed by not the current one.
|
|
if (lastTab != null && indexOfComponent(lastTab) == -1) { // lastTab was closed
|
|
setLastTabAdjacentToCurTab();
|
|
}
|
|
return;
|
|
}
|
|
if (tab == lastTab) {
|
|
if (indexOfComponent(curTab) == -1) { // curTab was closed and lastTab is the current one.
|
|
curTab = lastTab;
|
|
setLastTabAdjacentToCurTab();
|
|
return;
|
|
}
|
|
// it's switching between lastTab and curTab.
|
|
}
|
|
lastTab = curTab;
|
|
curTab = tab;
|
|
});
|
|
}
|
|
|
|
private void setLastTabAdjacentToCurTab() {
|
|
if (getTabCount() < 2) {
|
|
lastTab = null;
|
|
return;
|
|
}
|
|
int idx = indexOfComponent(curTab);
|
|
if (idx == 0) {
|
|
lastTab = (ContentPanel) getComponentAt(idx + 1);
|
|
} else {
|
|
lastTab = (ContentPanel) getComponentAt(idx - 1);
|
|
}
|
|
}
|
|
|
|
public MainWindow getMainWindow() {
|
|
return mainWindow;
|
|
}
|
|
|
|
public TabsController getTabsController() {
|
|
return controller;
|
|
}
|
|
|
|
private @Nullable ContentPanel showCode(JumpPosition jumpPos) {
|
|
JNode jumpNode = jumpPos.getNode();
|
|
ContentPanel contentPanel = getTabByNode(jumpNode);
|
|
if (contentPanel == null) {
|
|
return null;
|
|
}
|
|
selectTab(contentPanel);
|
|
int pos = jumpPos.getPos();
|
|
if (pos < 0) {
|
|
LOG.warn("Invalid jump: {}", jumpPos, new JadxRuntimeException());
|
|
pos = 0;
|
|
}
|
|
contentPanel.scrollToPos(pos);
|
|
return contentPanel;
|
|
}
|
|
|
|
public void selectTab(ContentPanel contentPanel) {
|
|
controller.selectTab(contentPanel.getNode());
|
|
}
|
|
|
|
private void smaliJump(JClass cls, int pos, boolean debugMode) {
|
|
ContentPanel panel = getTabByNode(cls);
|
|
if (panel == null) {
|
|
panel = showCode(new JumpPosition(cls, 1));
|
|
if (panel == null) {
|
|
throw new JadxRuntimeException("Failed to open panel for JClass: " + cls);
|
|
}
|
|
} else {
|
|
selectTab(panel);
|
|
}
|
|
ClassCodeContentPanel codePane = (ClassCodeContentPanel) panel;
|
|
codePane.showSmaliPane();
|
|
SmaliArea smaliArea = (SmaliArea) codePane.getSmaliCodeArea();
|
|
if (debugMode) {
|
|
smaliArea.scrollToDebugPos(pos);
|
|
}
|
|
smaliArea.scrollToPos(pos);
|
|
smaliArea.requestFocus();
|
|
}
|
|
|
|
public @Nullable JumpPosition getCurrentPosition() {
|
|
ContentPanel selectedCodePanel = getSelectedContentPanel();
|
|
if (selectedCodePanel instanceof AbstractCodeContentPanel) {
|
|
AbstractCodeArea codeArea = ((AbstractCodeContentPanel) selectedCodePanel).getCodeArea();
|
|
if (codeArea != null) {
|
|
return codeArea.getCurrentPosition();
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void addContentPanel(ContentPanel contentPanel) {
|
|
tabsMap.put(contentPanel.getNode(), contentPanel);
|
|
int tabCount = getTabCount();
|
|
add(contentPanel, tabCount);
|
|
setTabComponentAt(tabCount, makeTabComponent(contentPanel));
|
|
}
|
|
|
|
public void closeCodePanel(ContentPanel contentPanel) {
|
|
closeCodePanel(contentPanel, false);
|
|
}
|
|
|
|
public void closeCodePanel(ContentPanel contentPanel, boolean considerPins) {
|
|
controller.closeTab(contentPanel.getNode(), considerPins);
|
|
}
|
|
|
|
public List<ContentPanel> getTabs() {
|
|
List<ContentPanel> list = new ArrayList<>(getTabCount());
|
|
for (int i = 0; i < getTabCount(); i++) {
|
|
list.add((ContentPanel) getComponentAt(i));
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public @Nullable ContentPanel getTabByNode(JNode node) {
|
|
return tabsMap.get(node);
|
|
}
|
|
|
|
public @Nullable TabComponent getTabComponentByNode(JNode node) {
|
|
ContentPanel contentPanel = getTabByNode(node);
|
|
if (contentPanel == null) {
|
|
return null;
|
|
}
|
|
int index = indexOfComponent(contentPanel);
|
|
if (index == -1) {
|
|
return null;
|
|
}
|
|
Component component = getTabComponentAt(index);
|
|
if (!(component instanceof TabComponent)) {
|
|
return null;
|
|
}
|
|
|
|
return (TabComponent) component;
|
|
}
|
|
|
|
public void refresh(JNode node) {
|
|
ContentPanel panel = getTabByNode(node);
|
|
if (panel != null) {
|
|
setTabComponentAt(indexOfComponent(panel), makeTabComponent(panel));
|
|
fireStateChanged();
|
|
}
|
|
}
|
|
|
|
public void reloadInactiveTabs() {
|
|
UiUtils.uiThreadGuard();
|
|
int tabCount = getTabCount();
|
|
if (tabCount == 1) {
|
|
return;
|
|
}
|
|
int current = getSelectedIndex();
|
|
for (int i = 0; i < tabCount; i++) {
|
|
if (i == current) {
|
|
continue;
|
|
}
|
|
ContentPanel oldPanel = (ContentPanel) getComponentAt(i);
|
|
TabBlueprint tab = controller.getTabByNode(oldPanel.getNode());
|
|
if (tab == null) {
|
|
continue;
|
|
}
|
|
EditorViewState viewState = controller.getEditorViewState(tab);
|
|
JNode node = oldPanel.getNode();
|
|
ContentPanel panel = node.getContentPanel(this);
|
|
FocusManager.listen(panel);
|
|
tabsMap.put(node, panel);
|
|
setComponentAt(i, panel);
|
|
setTabComponentAt(i, makeTabComponent(panel));
|
|
controller.restoreEditorViewState(viewState);
|
|
}
|
|
fireStateChanged();
|
|
}
|
|
|
|
@Nullable
|
|
public ContentPanel getSelectedContentPanel() {
|
|
return (ContentPanel) getSelectedComponent();
|
|
}
|
|
|
|
private Component makeTabComponent(final ContentPanel contentPanel) {
|
|
return new TabComponent(this, contentPanel);
|
|
}
|
|
|
|
public void closeAllTabs() {
|
|
closeAllTabs(false);
|
|
}
|
|
|
|
public void closeAllTabs(boolean considerPins) {
|
|
for (ContentPanel panel : getTabs()) {
|
|
closeCodePanel(panel, considerPins);
|
|
}
|
|
}
|
|
|
|
public void loadSettings() {
|
|
for (int i = 0; i < getTabCount(); i++) {
|
|
((ContentPanel) getComponentAt(i)).loadSettings();
|
|
((TabComponent) getTabComponentAt(i)).loadSettings();
|
|
}
|
|
}
|
|
|
|
public void reset() {
|
|
closeAllTabs();
|
|
tabsMap.clear();
|
|
curTab = null;
|
|
lastTab = null;
|
|
FocusManager.reset();
|
|
}
|
|
|
|
@Nullable
|
|
public Component getFocusedComp() {
|
|
return FocusManager.getFocusedComp();
|
|
}
|
|
|
|
public TabDndController getDnd() {
|
|
return dnd;
|
|
}
|
|
|
|
public void setDnd(TabDndController dnd) {
|
|
this.dnd = dnd;
|
|
}
|
|
|
|
@Override
|
|
public void onTabOpen(TabBlueprint blueprint) {
|
|
if (blueprint.isHidden()) {
|
|
return;
|
|
}
|
|
JNode node = blueprint.getNode();
|
|
ContentPanel newPanel = node.getContentPanel(this);
|
|
if (newPanel != null) {
|
|
if (node != newPanel.getNode()) {
|
|
throw new JadxRuntimeException("Incorrect node found in content panel");
|
|
}
|
|
FocusManager.listen(newPanel);
|
|
addContentPanel(newPanel);
|
|
blueprint.setCreated(true);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onTabSelect(TabBlueprint blueprint) {
|
|
ContentPanel contentPanel = getTabByNode(blueprint.getNode());
|
|
if (contentPanel != null) {
|
|
setSelectedComponent(contentPanel);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onTabCodeJump(TabBlueprint blueprint, @Nullable JumpPosition prevPos, JumpPosition position) {
|
|
// queue task to wait completion of loading tasks
|
|
mainWindow.getBackgroundExecutor().execute(new SilentTask(() -> showCode(position)));
|
|
}
|
|
|
|
@Override
|
|
public void onTabSmaliJump(TabBlueprint blueprint, int pos, boolean debugMode) {
|
|
JNode node = blueprint.getNode();
|
|
if (node instanceof JClass) {
|
|
smaliJump((JClass) node, pos, debugMode);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onTabClose(TabBlueprint blueprint) {
|
|
ContentPanel contentPanelToClose = getTabByNode(blueprint.getNode());
|
|
if (contentPanelToClose == null) {
|
|
return;
|
|
}
|
|
|
|
ContentPanel currentContentPanel = getSelectedContentPanel();
|
|
if (currentContentPanel == contentPanelToClose) {
|
|
if (lastTab != null && lastTab.getNode() != null) {
|
|
selectTab(lastTab);
|
|
} else if (getTabCount() > 1) {
|
|
int removalIdx = indexOfComponent(contentPanelToClose);
|
|
if (removalIdx > 0) { // select left tab
|
|
setSelectedIndex(removalIdx - 1);
|
|
} else if (removalIdx == 0) { // select right tab
|
|
setSelectedIndex(removalIdx + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
tabsMap.remove(contentPanelToClose.getNode());
|
|
remove(contentPanelToClose);
|
|
contentPanelToClose.dispose();
|
|
}
|
|
|
|
@Override
|
|
public void onTabPositionFirst(TabBlueprint blueprint) {
|
|
ContentPanel contentPanel = getTabByNode(blueprint.getNode());
|
|
if (contentPanel == null) {
|
|
return;
|
|
}
|
|
setTabPosition(contentPanel, 0);
|
|
}
|
|
|
|
private void setTabPosition(ContentPanel contentPanel, int position) {
|
|
TabComponent tabComponent = getTabComponentByNode(contentPanel.getNode());
|
|
if (tabComponent == null) {
|
|
return;
|
|
}
|
|
boolean restoreSelection = contentPanel == getSelectedContentPanel();
|
|
remove(contentPanel);
|
|
add(contentPanel, position);
|
|
setTabComponentAt(position, tabComponent);
|
|
if (restoreSelection) {
|
|
setSelectedIndex(position);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onTabPinChange(TabBlueprint blueprint) {
|
|
TabComponent tabComponent = getTabComponentByNode(blueprint.getNode());
|
|
if (tabComponent == null) {
|
|
return;
|
|
}
|
|
tabComponent.update();
|
|
}
|
|
|
|
@Override
|
|
public void onTabBookmarkChange(TabBlueprint blueprint) {
|
|
TabComponent tabComponent = getTabComponentByNode(blueprint.getNode());
|
|
if (tabComponent == null) {
|
|
return;
|
|
}
|
|
tabComponent.update();
|
|
}
|
|
|
|
@Override
|
|
public void onTabVisibilityChange(TabBlueprint blueprint) {
|
|
if (!blueprint.isHidden() && !tabsMap.containsKey(blueprint.getNode())) {
|
|
onTabOpen(blueprint);
|
|
}
|
|
if (blueprint.isHidden() && tabsMap.containsKey(blueprint.getNode())) {
|
|
onTabClose(blueprint);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onTabPreviewChange(TabBlueprint blueprint) {
|
|
TabComponent tabComponent = getTabComponentByNode(blueprint.getNode());
|
|
if (tabComponent == null) {
|
|
return;
|
|
}
|
|
tabComponent.update();
|
|
}
|
|
|
|
@Override
|
|
public void onTabRestore(TabBlueprint blueprint, EditorViewState viewState) {
|
|
ContentPanel contentPanel = getTabByNode(blueprint.getNode());
|
|
if (contentPanel instanceof IViewStateSupport) {
|
|
((IViewStateSupport) contentPanel).restoreEditorViewState(viewState);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onTabsReorder(List<TabBlueprint> blueprints) {
|
|
List<TabBlueprint> newBlueprints = new ArrayList<>(blueprints.size());
|
|
for (ContentPanel contentPanel : getTabs()) {
|
|
TabBlueprint blueprint = controller.getTabByNode(contentPanel.getNode());
|
|
if (blueprint != null) {
|
|
newBlueprints.add(blueprint);
|
|
}
|
|
}
|
|
// Add back hidden tabs
|
|
Set<TabBlueprint> set = new LinkedHashSet<>(blueprints);
|
|
newBlueprints.forEach(set::remove);
|
|
newBlueprints.addAll(set);
|
|
|
|
blueprints.clear();
|
|
blueprints.addAll(newBlueprints);
|
|
}
|
|
|
|
@Override
|
|
public void onTabSave(TabBlueprint blueprint, EditorViewState viewState) {
|
|
ContentPanel contentPanel = getTabByNode(blueprint.getNode());
|
|
if (contentPanel instanceof IViewStateSupport) {
|
|
((IViewStateSupport) contentPanel).saveEditorViewState(viewState);
|
|
}
|
|
}
|
|
|
|
private static class FocusManager implements FocusListener {
|
|
private static final FocusManager INSTANCE = new FocusManager();
|
|
private static @Nullable Component focusedComp;
|
|
|
|
static boolean isActive() {
|
|
return focusedComp != null;
|
|
}
|
|
|
|
static void reset() {
|
|
focusedComp = null;
|
|
}
|
|
|
|
static Component getFocusedComp() {
|
|
return focusedComp;
|
|
}
|
|
|
|
@Override
|
|
public void focusGained(FocusEvent e) {
|
|
focusedComp = (Component) e.getSource();
|
|
}
|
|
|
|
@Override
|
|
public void focusLost(FocusEvent e) {
|
|
focusedComp = null;
|
|
}
|
|
|
|
static void listen(ContentPanel pane) {
|
|
if (pane instanceof ClassCodeContentPanel) {
|
|
((ClassCodeContentPanel) pane).getCodeArea().addFocusListener(INSTANCE);
|
|
((ClassCodeContentPanel) pane).getSmaliCodeArea().addFocusListener(INSTANCE);
|
|
return;
|
|
}
|
|
if (pane instanceof AbstractCodeContentPanel) {
|
|
((AbstractCodeContentPanel) pane).getChildrenComponent().addFocusListener(INSTANCE);
|
|
return;
|
|
}
|
|
if (pane instanceof HtmlPanel) {
|
|
((HtmlPanel) pane).getHtmlArea().addFocusListener(INSTANCE);
|
|
return;
|
|
}
|
|
if (pane instanceof ImagePanel) {
|
|
pane.addFocusListener(INSTANCE);
|
|
return;
|
|
}
|
|
if (pane instanceof FontPanel) {
|
|
pane.addFocusListener(INSTANCE);
|
|
return;
|
|
}
|
|
// throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane);
|
|
}
|
|
|
|
static void focusOnCodePanel(ContentPanel pane) {
|
|
if (pane instanceof ClassCodeContentPanel) {
|
|
SwingUtilities.invokeLater(() -> ((ClassCodeContentPanel) pane).getCurrentCodeArea().requestFocus());
|
|
return;
|
|
}
|
|
if (pane instanceof AbstractCodeContentPanel) {
|
|
SwingUtilities.invokeLater(() -> ((AbstractCodeContentPanel) pane).getChildrenComponent().requestFocus());
|
|
return;
|
|
}
|
|
if (pane instanceof HtmlPanel) {
|
|
SwingUtilities.invokeLater(() -> ((HtmlPanel) pane).getHtmlArea().requestFocusInWindow());
|
|
return;
|
|
}
|
|
if (pane instanceof ImagePanel) {
|
|
SwingUtilities.invokeLater(((ImagePanel) pane)::requestFocusInWindow);
|
|
return;
|
|
}
|
|
if (pane instanceof FontPanel) {
|
|
SwingUtilities.invokeLater(((FontPanel) pane)::requestFocusInWindow);
|
|
return;
|
|
}
|
|
// throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane);
|
|
}
|
|
}
|
|
}
|