GP-5097 - Updated the Importer to allow users to double-click a language to pick it

This commit is contained in:
dragonmacher 2024-11-12 16:11:40 -05:00
parent d09c75e4ac
commit b7dec5e363
4 changed files with 133 additions and 90 deletions

View File

@ -19,8 +19,8 @@ import javax.swing.BorderFactory;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.plugin.importer.LcsSelectionListener; import ghidra.plugin.importer.*;
import ghidra.plugin.importer.NewLanguagePanel; import ghidra.plugin.importer.LcsSelectionEvent.Type;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.util.DefaultLanguageService; import ghidra.program.util.DefaultLanguageService;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
@ -30,33 +30,14 @@ public class SetLanguageDialog extends DialogComponentProvider {
private NewLanguagePanel selectLangPanel; private NewLanguagePanel selectLangPanel;
private PluginTool tool; private PluginTool tool;
private LanguageCompilerSpecPair currentLCSPair; private LanguageCompilerSpecPair currentLcsPair;
private LanguageID dialogLanguageID; private LanguageID dialogLanguageID;
private CompilerSpecID dialogCompilerSpecID; private CompilerSpecID dialogCompilerSpecID;
LcsSelectionListener listener = e -> { private LcsSelectionListener listener = e -> {
LanguageID langID = null; languageSelected(e.getLcs());
CompilerSpecID compilerSpecID = null; maybePressOk(e);
if (e != null && e.selection != null) {
langID = e.selection.languageID;
compilerSpecID = e.selection.compilerSpecID;
}
if ((currentLCSPair != null) && (langID != null) &&
(langID.equals(currentLCSPair.getLanguageID()))) {
if (compilerSpecID != null &&
compilerSpecID.equals(currentLCSPair.getCompilerSpecID())) {
setStatusText("Please select a different Language or Compiler Spec.");
setOkEnabled(false);
}
else {
setStatusText(null);
setOkEnabled(true);
}
return;
}
setStatusText(null);
setOkEnabled(langID != null);
}; };
/** /**
@ -89,7 +70,7 @@ public class SetLanguageDialog extends DialogComponentProvider {
*/ */
public SetLanguageDialog(PluginTool tool, LanguageCompilerSpecPair lcsPair, String title) { public SetLanguageDialog(PluginTool tool, LanguageCompilerSpecPair lcsPair, String title) {
super(title, true, true, true, false); super(title, true, true, true, false);
currentLCSPair = lcsPair; currentLcsPair = lcsPair;
this.tool = tool; this.tool = tool;
selectLangPanel = new NewLanguagePanel(); selectLangPanel = new NewLanguagePanel();
@ -110,7 +91,40 @@ public class SetLanguageDialog extends DialogComponentProvider {
setHelpLocation(new HelpLocation("LanguageProviderPlugin", "set language")); setHelpLocation(new HelpLocation("LanguageProviderPlugin", "set language"));
selectLangPanel.setShowRecommendedCheckbox(false); selectLangPanel.setShowRecommendedCheckbox(false);
listener.valueChanged(null); // kick to establish initial button enablement languageSelected(null); // kick to establish initial button enablement
}
private void languageSelected(LanguageCompilerSpecPair lcs) {
LanguageID langId = null;
CompilerSpecID compilerSpecID = null;
if (lcs != null) {
langId = lcs.languageID;
compilerSpecID = lcs.compilerSpecID;
}
if ((currentLcsPair != null) && (langId != null) &&
(langId.equals(currentLcsPair.getLanguageID()))) {
if (compilerSpecID != null &&
compilerSpecID.equals(currentLcsPair.getCompilerSpecID())) {
setStatusText("Please select a different Language or Compiler Spec.");
setOkEnabled(false);
}
else {
setStatusText(null);
setOkEnabled(true);
}
return;
}
setStatusText(null);
setOkEnabled(langId != null);
}
private void maybePressOk(LcsSelectionEvent e) {
if (e.getType() == Type.PICKED && isOKEnabled()) {
// the user picked (i.e., double-clicked) a language and it is valid, so use it
okCallback();
}
} }
private static LanguageCompilerSpecPair getLanguageCompilerSpecPair(String languageIdStr, private static LanguageCompilerSpecPair getLanguageCompilerSpecPair(String languageIdStr,

View File

@ -19,14 +19,14 @@ import java.awt.Component;
import java.util.*; import java.util.*;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.SwingUtilities;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import ghidra.app.util.opinion.LoadSpec; import ghidra.app.util.opinion.LoadSpec;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.plugin.importer.LcsSelectionEvent.Type;
import ghidra.program.model.lang.LanguageCompilerSpecPair; import ghidra.program.model.lang.LanguageCompilerSpecPair;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Swing;
public class ImporterLanguageDialog extends DialogComponentProvider { public class ImporterLanguageDialog extends DialogComponentProvider {
@ -46,25 +46,11 @@ public class ImporterLanguageDialog extends DialogComponentProvider {
} }
public void show(Component parent) { public void show(Component parent) {
if (SwingUtilities.isEventDispatchThread()) { Swing.runIfSwingOrRunLater(() -> {
build(); build();
tool.showDialog(this, parent); tool.showDialog(this, parent);
}
else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
build();
tool.showDialog(ImporterLanguageDialog.this, parent);
}
}); });
} }
catch (Exception e) {
Msg.error(this, e);
}
}
}
private void build() { private void build() {
languagePanel = new NewLanguagePanel(); languagePanel = new NewLanguagePanel();
@ -72,10 +58,11 @@ public class ImporterLanguageDialog extends DialogComponentProvider {
languagePanel.setShowAllLcsPairs(false); languagePanel.setShowAllLcsPairs(false);
languagePanel.setBorder( languagePanel.setBorder(
BorderFactory.createTitledBorder(" Select Language and Compiler Specification ")); BorderFactory.createTitledBorder(" Select Language and Compiler Specification "));
languagePanel.addSelectionListener(new LcsSelectionListener() { languagePanel.addSelectionListener(e -> {
@Override
public void valueChanged(LcsSelectionEvent e) {
validateFormInput(); validateFormInput();
if (e.getType() == Type.PICKED && isOKEnabled()) {
okCallback();
} }
}); });

View File

@ -18,14 +18,33 @@ package ghidra.plugin.importer;
import ghidra.program.model.lang.LanguageCompilerSpecPair; import ghidra.program.model.lang.LanguageCompilerSpecPair;
public class LcsSelectionEvent { public class LcsSelectionEvent {
public final LanguageCompilerSpecPair selection;
public LcsSelectionEvent(LanguageCompilerSpecPair selection) { public enum Type {
this.selection = selection; /** A language was selected in the UI */
SELECTED,
/** A language was picked (e.g., double-clicked) in the UI */
PICKED
}
private final LanguageCompilerSpecPair lcs;
private final Type type;
public LcsSelectionEvent(LanguageCompilerSpecPair selection, Type type) {
this.lcs = selection;
this.type = type;
}
public LanguageCompilerSpecPair getLcs() {
return lcs;
}
public Type getType() {
return type;
} }
@Override @Override
public String toString() { public String toString() {
return "LSE{" + selection + "}"; return "LSE{" + lcs + "}";
} }
} }

View File

@ -23,10 +23,12 @@ import java.util.List;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
import docking.actions.KeyBindingUtils;
import docking.widgets.checkbox.GCheckBox; import docking.widgets.checkbox.GCheckBox;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import generic.theme.Gui; import generic.theme.Gui;
import ghidra.plugin.importer.LcsSelectionEvent.Type;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.util.DefaultLanguageService; import ghidra.program.util.DefaultLanguageService;
import ghidra.util.table.*; import ghidra.util.table.*;
@ -41,12 +43,13 @@ public class NewLanguagePanel extends JPanel {
private JCheckBox recommendedCheckbox; private JCheckBox recommendedCheckbox;
private JLabel formatLabel; private JLabel formatLabel;
private void setDescriptionLabelText(String text) { private boolean isOnShowAll = true;
if (text == null || "".equals(text)) {
text = " "; private List<LanguageCompilerSpecPair> allLcsPairsList;
} private List<LanguageCompilerSpecPair> recommendedLcsPairsList;
descriptionLabel.setText(text); private LanguageCompilerSpecPair recommendedLcsPair;
}
private final Set<LcsSelectionListener> listeners = new HashSet<>();
public NewLanguagePanel() { public NewLanguagePanel() {
constructEverything(); constructEverything();
@ -94,7 +97,6 @@ public class NewLanguagePanel extends JPanel {
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
// this makes us a bit smaller in height, as the preferred height can be excessive // this makes us a bit smaller in height, as the preferred height can be excessive
Dimension preferredSize = super.getPreferredSize(); Dimension preferredSize = super.getPreferredSize();
if (preferredSize.width == 0) { if (preferredSize.width == 0) {
return preferredSize; // no size yet, don't change anything return preferredSize; // no size yet, don't change anything
@ -138,16 +140,37 @@ public class NewLanguagePanel extends JPanel {
if (e.getValueIsAdjusting()) { if (e.getValueIsAdjusting()) {
return; return;
} }
notifyListeners(); notifyLanguageSelected();
}); });
table.addMouseListener(new MouseAdapter() { table.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
if (e.getClickCount() == 2) { if (e.getClickCount() == 2) {
// do the next action thingie notfiyLanguagePicked();
} }
} }
}); });
// Update Enter to allow the user to pick the selected language
KeyStroke enterKs = KeyBindingUtils.parseKeyStroke("Enter");
Action action = new AbstractAction("Pick Language") {
@Override
public void actionPerformed(ActionEvent e) {
notfiyLanguagePicked();
}
};
// remove the table's enter key binding and then add our own
KeyBindingUtils.clearKeyBinding(table, enterKs);
KeyBindingUtils.registerAction(table, enterKs, action, JComponent.WHEN_FOCUSED);
}
private void setDescriptionLabelText(String text) {
if (text == null || "".equals(text)) {
text = " ";
}
descriptionLabel.setText(text);
} }
public void setFormatText(String text) { public void setFormatText(String text) {
@ -158,8 +181,6 @@ public class NewLanguagePanel extends JPanel {
recommendedCheckbox.setVisible(show); recommendedCheckbox.setVisible(show);
} }
private boolean isOnShowAll = true;
private boolean isAllLcsPairsTableShowing() { private boolean isAllLcsPairsTableShowing() {
return isOnShowAll; return isOnShowAll;
} }
@ -174,7 +195,7 @@ public class NewLanguagePanel extends JPanel {
private void setLanguages(List<LanguageCompilerSpecPair> lcsPairList) { private void setLanguages(List<LanguageCompilerSpecPair> lcsPairList) {
tableModel.setLanguages(lcsPairList); tableModel.setLanguages(lcsPairList);
notifyListeners(); notifyLanguageSelected();
} }
private void switchToAllList() { private void switchToAllList() {
@ -203,13 +224,20 @@ public class NewLanguagePanel extends JPanel {
} }
} }
private List<LanguageCompilerSpecPair> allLcsPairsList; private void notifyLanguageSelected() {
private List<LanguageCompilerSpecPair> recommendedLcsPairsList; LanguageCompilerSpecPair lcs = getSelectedLcsPair();
LcsSelectionEvent e = new LcsSelectionEvent(lcs, Type.SELECTED);
doNotify(e);
}
private LanguageCompilerSpecPair recommendedLcsPair; private void notfiyLanguagePicked() {
LanguageCompilerSpecPair lcs = getSelectedLcsPair();
LcsSelectionEvent e = new LcsSelectionEvent(lcs, Type.PICKED);
doNotify(e);
}
private void notifyListeners() { private void doNotify(LcsSelectionEvent event) {
LanguageCompilerSpecPair selectedLcsPair = getSelectedLcsPair(); LanguageCompilerSpecPair selectedLcsPair = event.getLcs();
if (selectedLcsPair == null) { if (selectedLcsPair == null) {
descriptionLabel.setText(DEFAULT_DESCRIPTION_TEXT); descriptionLabel.setText(DEFAULT_DESCRIPTION_TEXT);
} }
@ -221,12 +249,9 @@ public class NewLanguagePanel extends JPanel {
descriptionLabel.setText("<LanguageNotFound>"); descriptionLabel.setText("<LanguageNotFound>");
} }
} }
// notifyListenersOfValidityChanged();
if (!listeners.isEmpty()) {
LcsSelectionEvent e = new LcsSelectionEvent(selectedLcsPair);
for (LcsSelectionListener listener : listeners) { for (LcsSelectionListener listener : listeners) {
listener.valueChanged(e); listener.valueChanged(event);
}
} }
} }
@ -314,8 +339,6 @@ public class NewLanguagePanel extends JPanel {
return true; return true;
} }
private final Set<LcsSelectionListener> listeners = new HashSet<>();
public void addSelectionListener(LcsSelectionListener listener) { public void addSelectionListener(LcsSelectionListener listener) {
listeners.add(listener); listeners.add(listener);
} }