GP-1318 - fixed xref clicking bug

This commit is contained in:
dragonmacher 2021-09-24 09:00:22 -04:00
parent f00f7afa6b
commit f24e969c2a
5 changed files with 129 additions and 96 deletions

View File

@ -25,11 +25,13 @@ import javax.swing.table.TableModel;
import org.junit.*;
import docking.ActionContext;
import docking.action.DockingActionIf;
import docking.widgets.OptionDialog;
import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.dialogs.InputWithChoicesDialog;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
import ghidra.app.services.ProgramManager;
import ghidra.framework.Application;
import ghidra.framework.options.Options;
@ -307,8 +309,12 @@ public class AnalysisOptionsTest extends AbstractGhidraHeadedIntegrationTest {
}
private AnalysisOptionsDialog invokeAnalysisDialog() {
CodeBrowserPlugin cbp = env.getPlugin(CodeBrowserPlugin.class);
CodeViewerProvider provider = cbp.getProvider();
DockingActionIf action = getAction(tool, "Auto Analyze");
performAction(action, false);
ActionContext context = runSwing(() -> provider.getActionContext(null));
performAction(action, context, false);
// TODO temp debug to catch issue seen when running parallel tests
try {
@ -331,24 +337,14 @@ public class AnalysisOptionsTest extends AbstractGhidraHeadedIntegrationTest {
private void setAnalyzerEnabled(String name, boolean enabled) {
TableModel model = getAnalyzerTableModel();
int analyzerRow = getRowForAnalyzer(name, model);
runSwing(new Runnable() {
@Override
public void run() {
model.setValueAt(enabled, analyzerRow, 0);
}
});
runSwing(() -> model.setValueAt(enabled, analyzerRow, 0));
}
private boolean isAnalyzerEnabled(String name) {
TableModel model = getAnalyzerTableModel();
int analyzerRow = getRowForAnalyzer(name, model);
AtomicBoolean result = new AtomicBoolean();
runSwing(new Runnable() {
@Override
public void run() {
result.set((Boolean) model.getValueAt(analyzerRow, 0));
}
});
runSwing(() -> result.set((Boolean) model.getValueAt(analyzerRow, 0)));
return result.get();
}

View File

@ -116,7 +116,8 @@ public class CompositeVerticalLayoutTextField implements TextField {
private List<FieldRow> layoutRows(List<TextField> fields, int maxLines) {
List<FieldRow> newSubFields = new ArrayList<>();
int heightSoFar = -heightAbove;
int startY = -heightAbove;
int ySoFar = startY;
int currentRow = 0;
boolean tooManyLines = fields.size() > maxLines;
for (int i = 0; i < fields.size() && i < maxLines; i++) {
@ -124,15 +125,15 @@ public class CompositeVerticalLayoutTextField implements TextField {
if (tooManyLines && (i == maxLines - 1)) {
FieldElement element = field.getFieldElement(0, 0);
TextField newField = createClippedField(element);
newSubFields.add(new FieldRow(newField, currentRow, heightSoFar));
newSubFields.add(new FieldRow(newField, currentRow, ySoFar));
isClipped = true;
}
else {
newSubFields.add(new FieldRow(field, currentRow, heightSoFar));
newSubFields.add(new FieldRow(field, currentRow, ySoFar));
isClipped |= field.isClipped();
}
heightSoFar += field.getHeight();
ySoFar += field.getHeight();
currentRow += field.getNumRows();
}
@ -402,31 +403,42 @@ public class CompositeVerticalLayoutTextField implements TextField {
@Override
public int getY(int row) {
int y = -heightAbove;
int startY = -heightAbove;
int ySoFar = startY;
List<FieldRow> rows = getAllRows(row);
int lastHeight = 0;
for (FieldRow fieldRow : rows) {
y += fieldRow.field.getHeight();
ySoFar += lastHeight;
if (fieldRow.displayRowOffset >= row) {
return ySoFar;
}
lastHeight = fieldRow.field.getHeight();
}
return y;
return ySoFar;
}
@Override
public int getRow(int y) {
if (y < 0) {
// our start y value is our baseline - the heigh above the baseline
int startY = -heightAbove;
if (y < startY) {
return 0;
}
int heightSoFar = 0;
int ySoFar = startY;
for (FieldRow fieldRow : fieldRows) {
int fieldHeight = fieldRow.field.getHeight();
int bottom = fieldHeight + heightSoFar;
int bottom = fieldHeight + ySoFar;
if (bottom > y) {
int relativeY = y - heightSoFar;
int relativeY = y - ySoFar;
int relativeRow = fieldRow.field.getRow(relativeY);
int displayRow = fieldRow.fromRelativeRow(relativeRow);
return displayRow;
}
heightSoFar += fieldHeight;
ySoFar += fieldHeight;
}
return getNumRows() - 1;
}

View File

@ -208,20 +208,23 @@ public class VerticalLayoutTextField implements TextField {
@Override
public int getRow(int y) {
if (y < -heightAbove) {
// our start y value is our baseline - the heigh above the baseline
int startY = -heightAbove;
if (y < startY) {
return 0;
}
int heightSoFar = -heightAbove;
int ySoFar = startY;
int n = subFields.size();
for (int i = 0; i < n; i++) {
Field f = getField(i);
heightSoFar += f.getHeight();
if (heightSoFar > y) {
ySoFar += f.getHeight();
if (ySoFar > y) {
return i;
}
}
return n - 1;
}
@ -234,11 +237,14 @@ public class VerticalLayoutTextField implements TextField {
@Override
public int getY(int row) {
int y = -heightAbove;
for (int i = 0; i < row; i++) {
int startY = -heightAbove;
int y = startY;
int n = Math.min(row, subFields.size() - 1);
for (int i = 0; i < n; i++) {
Field f = getField(i);
y += f.getHeight();
}
return y;
}
@ -537,6 +543,9 @@ public class VerticalLayoutTextField implements TextField {
}
private TextField getField(int screenRow) {
if (screenRow >= subFields.size()) {
return null;
}
return subFields.get(screenRow).field;
}

View File

@ -93,6 +93,7 @@ public class RowLayout implements Layout {
/**
* Returns the height above the baseline.
* @return the height above the baseline.
*/
public int getHeightAbove() {
return heightAbove;
@ -100,6 +101,7 @@ public class RowLayout implements Layout {
/**
* Returns the height below the baseline.
* @return the height below the baseline.
*/
public int getHeightBelow() {
return heightBelow;
@ -107,6 +109,7 @@ public class RowLayout implements Layout {
/**
* Returns the row number of this layout with respect to its containing layout.
* @return the row number of this layout with respect to its containing layout.
*/
public int getRowID() {
return rowID;
@ -201,8 +204,12 @@ public class RowLayout implements Layout {
Field field = fields[index];
// y passed-in is 0-based; update y to be relative to our starting position, which is
// the tallest field in this group of fields, using that field's height above its font
// baseline.
int offsetY = y - heightAbove;
cursorLoc.fieldNum = index;
cursorLoc.row = field.getRow(y);
cursorLoc.row = field.getRow(offsetY);
cursorLoc.col = field.getCol(cursorLoc.row, x);
return field.getX(cursorLoc.row, cursorLoc.col);
}
@ -374,6 +381,9 @@ public class RowLayout implements Layout {
* Finds the most appropriate field to place the cursor for the given horizontal
* position. If the position is between fields, first try to the left and if that
* doesn't work, try to the right.
* @param x the x value
* @param y the y value
* @return the index
*/
int findAppropriateFieldIndex(int x, int y) {
y -= heightAbove;
@ -399,33 +409,6 @@ public class RowLayout implements Layout {
return -1;
}
/**
* Draws the selection background for individual fields.
*/
// private void drawSelection(Graphics g,int startField, int endField) {
// int start = fields[startField].getStartX();
// int end = fields[endField].getStartX()+fields[endField].getWidth();
// int width = end-start;
// g.fillRect(start,0,width,heightAbove+heightBelow);
// }
/**
* Draws the selection background for individual fields.
*/
// private void drawSelection(Graphics g, int startField, int endField,
// int first, int last) {
// int start = fields[startField].getStartX();
// int end = fields[endField].getStartX()+fields[endField].getWidth();
// if (first != -1 && first < start) {
// start = first;
// }
// if (last != -1 && last > end) {
// end = last;
// }
// int width = end-start;
// g.fillRect(start,0,width,heightAbove+heightBelow);
// }
@Override
public int getPrimaryOffset() {
return 0;

View File

@ -32,13 +32,13 @@ public class VerticalLayoutTextFieldTest extends AbstractGenericTest {
private static final String CLIPPED_STRING = "Supercalifragilisticexpialidocious";
private VerticalLayoutTextField textField;
private VerticalLayoutTextField field;
@SuppressWarnings("deprecation") // we mean to use getFontMetrics
@Before
public void setUp() throws Exception {
HighlightFactory factory = (field, text, cursorTextOffset) -> {
HighlightFactory factory = (f, text, cursorTextOffset) -> {
return new Highlight[] { new Highlight(4, 4, Color.YELLOW) };
};
@ -55,61 +55,94 @@ public class VerticalLayoutTextFieldTest extends AbstractGenericTest {
new TextFieldElement(new AttributedString(CLIPPED_STRING, Color.GREEN, fm), 2, 0));
elements.add(new TextFieldElement(new AttributedString("Wow!", Color.GRAY, fm), 3, 0));
textField = new VerticalLayoutTextField(elements, 100, 100, 5, factory);
field = new VerticalLayoutTextField(elements, 100, 100, 5, factory);
}
@Test
public void testScreenToDataLocation() {
assertEquals(new RowColLocation(0, 0), textField.screenToDataLocation(0, 0));
assertEquals(new RowColLocation(0, 2), textField.screenToDataLocation(0, 2));
assertEquals(new RowColLocation(0, 5), textField.screenToDataLocation(0, 5));
assertEquals(new RowColLocation(0, 5), textField.screenToDataLocation(0, 6));
assertEquals(new RowColLocation(0, 5), textField.screenToDataLocation(0, 75));
assertEquals(new RowColLocation(0, 0), field.screenToDataLocation(0, 0));
assertEquals(new RowColLocation(0, 2), field.screenToDataLocation(0, 2));
assertEquals(new RowColLocation(0, 5), field.screenToDataLocation(0, 5));
assertEquals(new RowColLocation(0, 5), field.screenToDataLocation(0, 6));
assertEquals(new RowColLocation(0, 5), field.screenToDataLocation(0, 75));
assertEquals(new RowColLocation(1, 0), textField.screenToDataLocation(1, 0));
assertEquals(new RowColLocation(1, 5), textField.screenToDataLocation(1, 6));
assertEquals(new RowColLocation(1, 5), textField.screenToDataLocation(1, 16));
assertEquals(new RowColLocation(1, 0), field.screenToDataLocation(1, 0));
assertEquals(new RowColLocation(1, 5), field.screenToDataLocation(1, 6));
assertEquals(new RowColLocation(1, 5), field.screenToDataLocation(1, 16));
assertEquals(new RowColLocation(2, 0), textField.screenToDataLocation(2, 0));
assertEquals(new RowColLocation(2, 4), textField.screenToDataLocation(2, 4));
assertEquals(new RowColLocation(2, 34), textField.screenToDataLocation(2, 75));
assertEquals(new RowColLocation(2, 0), field.screenToDataLocation(2, 0));
assertEquals(new RowColLocation(2, 4), field.screenToDataLocation(2, 4));
assertEquals(new RowColLocation(2, 34), field.screenToDataLocation(2, 75));
assertEquals(new RowColLocation(3, 0), textField.screenToDataLocation(3, 0));
assertEquals(new RowColLocation(3, 4), textField.screenToDataLocation(50, 75));
assertEquals(new RowColLocation(3, 0), field.screenToDataLocation(3, 0));
assertEquals(new RowColLocation(3, 4), field.screenToDataLocation(50, 75));
}
@Test
public void testDataToScreenLocation() {
assertEquals(new RowColLocation(0, 0), textField.dataToScreenLocation(0, 0));
assertEquals(new RowColLocation(0, 2), textField.dataToScreenLocation(0, 2));
assertEquals(new RowColLocation(0, 5), textField.dataToScreenLocation(0, 5));
assertEquals(new RowColLocation(0, 0), field.dataToScreenLocation(0, 0));
assertEquals(new RowColLocation(0, 2), field.dataToScreenLocation(0, 2));
assertEquals(new RowColLocation(0, 5), field.dataToScreenLocation(0, 5));
assertEquals(new RowColLocation(1, 0), textField.dataToScreenLocation(1, 0));
assertEquals(new RowColLocation(1, 4), textField.dataToScreenLocation(1, 4));
assertEquals(new RowColLocation(1, 5), textField.dataToScreenLocation(1, 5));
assertEquals(new RowColLocation(1, 0), field.dataToScreenLocation(1, 0));
assertEquals(new RowColLocation(1, 4), field.dataToScreenLocation(1, 4));
assertEquals(new RowColLocation(1, 5), field.dataToScreenLocation(1, 5));
assertEquals(new RowColLocation(2, 0), textField.dataToScreenLocation(2, 0));
assertEquals(new RowColLocation(2, 4), textField.dataToScreenLocation(2, 4));
assertEquals(new RowColLocation(2, 12), textField.dataToScreenLocation(2, 12));
assertEquals(new DefaultRowColLocation(2, 12), textField.dataToScreenLocation(2, 15));
assertEquals(new RowColLocation(2, 0), field.dataToScreenLocation(2, 0));
assertEquals(new RowColLocation(2, 4), field.dataToScreenLocation(2, 4));
assertEquals(new RowColLocation(2, 12), field.dataToScreenLocation(2, 12));
assertEquals(new DefaultRowColLocation(2, 12), field.dataToScreenLocation(2, 15));
assertEquals(new RowColLocation(3, 0), textField.dataToScreenLocation(3, 0));
assertEquals(new RowColLocation(3, 4), textField.dataToScreenLocation(3, 4));
assertEquals(new RowColLocation(3, 0), field.dataToScreenLocation(3, 0));
assertEquals(new RowColLocation(3, 4), field.dataToScreenLocation(3, 4));
}
@Test
public void testTextOffsetToScreenLocation() {
assertEquals(new RowColLocation(0, 0), textField.textOffsetToScreenLocation(0));
assertEquals(new RowColLocation(0, 5), textField.textOffsetToScreenLocation(5));
assertEquals(new RowColLocation(0, 0), field.textOffsetToScreenLocation(0));
assertEquals(new RowColLocation(0, 5), field.textOffsetToScreenLocation(5));
assertEquals(new RowColLocation(1, 0), textField.textOffsetToScreenLocation(6));
assertEquals(new RowColLocation(1, 4), textField.textOffsetToScreenLocation(10));
assertEquals(new RowColLocation(1, 5), textField.textOffsetToScreenLocation(11));
assertEquals(new RowColLocation(1, 0), field.textOffsetToScreenLocation(6));
assertEquals(new RowColLocation(1, 4), field.textOffsetToScreenLocation(10));
assertEquals(new RowColLocation(1, 5), field.textOffsetToScreenLocation(11));
assertEquals(new RowColLocation(2, 0), textField.textOffsetToScreenLocation(12));
assertEquals(new RowColLocation(2, 0), field.textOffsetToScreenLocation(12));
assertEquals(new RowColLocation(1, 4), textField.textOffsetToScreenLocation(10));
assertEquals(new RowColLocation(1, 4), field.textOffsetToScreenLocation(10));
assertEquals(new DefaultRowColLocation(3, 4), textField.textOffsetToScreenLocation(1000));
assertEquals(new DefaultRowColLocation(3, 4), field.textOffsetToScreenLocation(1000));
}
@Test
public void testGetY_And_GetRow() {
int y = field.getY(0);
int row = field.getRow(y);
assertEquals("Wrong row for y value: " + y, 0, row);
y = field.getY(1);
row = field.getRow(y);
assertEquals("Wrong row for y value: " + y, 1, row);
y = field.getY(2);
row = field.getRow(y);
assertEquals("Wrong row for y value: " + y, 2, row);
y = field.getY(3);
row = field.getRow(y);
assertEquals("Wrong row for y value: " + y, 3, row);
// try values past the end
int yForRowTooBig = field.getY(10);
assertEquals(y, yForRowTooBig);
int rowForYTooBig = field.getRow(1000);
assertEquals(3, rowForYTooBig);
// try values before the beginning
int yForRowTooSmall = field.getY(-1);
int expectedY = -field.getHeightAbove();
assertEquals(expectedY, yForRowTooSmall);
int rowForYTooSmall = field.getRow(-1000);
assertEquals(0, rowForYTooSmall);
}
}