mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 05:32:14 +00:00
Merge remote-tracking branch 'origin/patch' into
GP-0-dragonmacher-merge-conflict-resolution
This commit is contained in:
commit
0e23fe8c23
@ -27,7 +27,7 @@ import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
public class Annotation {
|
||||
/**
|
||||
* A pattern to match text between two quote characters and to capture that text. This
|
||||
* A pattern to match text between two quote characters and to capture that text. This
|
||||
* pattern does not match quote characters that are escaped with a '\' character.
|
||||
*/
|
||||
private static final Pattern QUOTATION_PATTERN =
|
||||
@ -47,7 +47,7 @@ public class Annotation {
|
||||
return ANNOTATED_STRING_MAP;
|
||||
}
|
||||
|
||||
// locates AnnotatedStringHandler implementations to handle annotations
|
||||
// locates AnnotatedStringHandler implementations to handle annotations
|
||||
private static Map<String, AnnotatedStringHandler> createAnnotatedStringHandlerMap() {
|
||||
Map<String, AnnotatedStringHandler> map = new HashMap<>();
|
||||
|
||||
@ -70,8 +70,9 @@ public class Annotation {
|
||||
* <b>Note</b>: This constructor assumes that the string starts with "{<pre>@</pre>" and ends with '}'
|
||||
*
|
||||
* @param annotationText The complete annotation text.
|
||||
* @param prototypeString An AttributedString that provides the attributes for the display
|
||||
* @param prototypeString An AttributedString that provides the attributes for the display
|
||||
* text this Annotation can create
|
||||
* @param program the program
|
||||
*/
|
||||
public Annotation(String annotationText, AttributedString prototypeString, Program program) {
|
||||
|
||||
@ -126,7 +127,7 @@ public class Annotation {
|
||||
* Called when a mouse click occurs on a FieldElement containing this Annotation.
|
||||
*
|
||||
* @param sourceNavigatable The source navigatable associated with the mouse click.
|
||||
* @param serviceProvider The service provider to be used when creating
|
||||
* @param serviceProvider The service provider to be used when creating
|
||||
* {@link AnnotatedStringHandler} instances.
|
||||
* @return true if the handler desires to handle the mouse click.
|
||||
*/
|
||||
@ -143,13 +144,13 @@ public class Annotation {
|
||||
buffer.delete(0, 2); // remove '{' and '@'
|
||||
buffer.deleteCharAt(buffer.length() - 1);
|
||||
|
||||
// first split out the tokens on '"' so that annotations can have groupings with
|
||||
// first split out the tokens on '"' so that annotations can have groupings with
|
||||
// whitespace
|
||||
int unqouotedOffset = 0;
|
||||
List<String> tokens = new ArrayList<>();
|
||||
Matcher matcher = QUOTATION_PATTERN.matcher(buffer.toString());
|
||||
while (matcher.find()) {
|
||||
// put all text in the buffer,
|
||||
// put all text in the buffer,
|
||||
int quoteStart = matcher.start();
|
||||
String contentBeforeQuote = buffer.substring(unqouotedOffset, quoteStart);
|
||||
grabTokens(tokens, contentBeforeQuote);
|
||||
|
@ -23,9 +23,9 @@ import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
/**
|
||||
* A subclass of {@link FieldElement} that allows for mouse handling callbacks via the
|
||||
* A subclass of {@link FieldElement} that allows for mouse handling callbacks via the
|
||||
* {@link #handleMouseClicked(Navigatable, ServiceProvider)} method. This class
|
||||
* is based upon {@link Annotation} objects, which are elements that perform actions when the
|
||||
* is based upon {@link Annotation} objects, which are elements that perform actions when the
|
||||
* use clicks an instance of this class in the display.
|
||||
*/
|
||||
final public class AnnotatedTextFieldElement extends AbstractTextFieldElement {
|
||||
@ -56,13 +56,23 @@ final public class AnnotatedTextFieldElement extends AbstractTextFieldElement {
|
||||
* Returns the original annotation text in the data model, which will differ from the display
|
||||
* text.
|
||||
* @return the original annotation text in the data model.
|
||||
* @see #getDisplayString()
|
||||
*/
|
||||
public String getRawText() {
|
||||
return annotation.getAnnotationText();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is designed to be called when a mouse click has occurred for a given
|
||||
* Returns the display string of annotation
|
||||
* @return the display string
|
||||
* @see #getRawText()
|
||||
*/
|
||||
public String getDisplayString() {
|
||||
return annotation.getDisplayString().getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is designed to be called when a mouse click has occurred for a given
|
||||
* {@link ProgramLocation}.
|
||||
*
|
||||
* @param sourceNavigatable The source Navigatable
|
||||
|
@ -35,7 +35,7 @@ import util.CollectionUtils;
|
||||
/**
|
||||
* Class to handle highlights for a decompiled function.
|
||||
*
|
||||
* <p>This class does not painting directly. Rather, this class tracks the currently highlighted
|
||||
* <p>This class does not paint directly. Rather, this class tracks the currently highlighted
|
||||
* tokens and then sets the highlight color on the token when it is highlighted and clears the
|
||||
* highlight color when the highlight is removed.
|
||||
*
|
||||
@ -206,7 +206,7 @@ public abstract class ClangHighlightController {
|
||||
* Return the current highlighted token (if exists and unique)
|
||||
* @return token or null
|
||||
*/
|
||||
private ClangToken getHighlightedToken() {
|
||||
public ClangToken getHighlightedToken() {
|
||||
if (primaryHighlightTokens.size() == 1) {
|
||||
HighlightToken hlToken = CollectionUtils.any(primaryHighlightTokens);
|
||||
return hlToken.getToken();
|
||||
|
@ -259,10 +259,6 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
highlightController.addPrimaryHighlights(root, ops, hlColor);
|
||||
}
|
||||
|
||||
public String getHighlightedText() {
|
||||
return highlightController.getPrimaryHighlightedText();
|
||||
}
|
||||
|
||||
public void setHighlightController(ClangHighlightController highlightController) {
|
||||
if (this.highlightController != null) {
|
||||
this.highlightController.removeListener(this);
|
||||
@ -698,6 +694,11 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
highlightersById.clear();
|
||||
}
|
||||
|
||||
public FontMetrics getFontMetrics() {
|
||||
Font font = options.getDefaultFont();
|
||||
return super.getFontMetrics(font);
|
||||
}
|
||||
|
||||
private FontMetrics getFontMetrics(DecompileOptions decompileOptions) {
|
||||
Font font = decompileOptions.getDefaultFont();
|
||||
return getFontMetrics(font);
|
||||
@ -756,7 +757,7 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
tryGoToVarnode((ClangVariableToken) token, newWindow);
|
||||
}
|
||||
else if (token instanceof ClangCommentToken) {
|
||||
tryGoToComment(location, event, textField, token, newWindow);
|
||||
tryGoToComment(location, event, textField, newWindow);
|
||||
}
|
||||
else if (token instanceof ClangSyntaxToken) {
|
||||
tryGoToSyntaxToken((ClangSyntaxToken) token);
|
||||
@ -764,10 +765,9 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
}
|
||||
|
||||
private void tryGoToComment(FieldLocation location, MouseEvent event, ClangTextField textField,
|
||||
ClangToken token, boolean newWindow) {
|
||||
boolean newWindow) {
|
||||
|
||||
// special cases
|
||||
// -comments: these no longer use tokens for each item, but are one composite field
|
||||
// comments may use annotations; tell the annotation it was clicked
|
||||
FieldElement clickedElement = textField.getClickedObject(location);
|
||||
if (clickedElement instanceof AnnotatedTextFieldElement) {
|
||||
AnnotatedTextFieldElement annotation = (AnnotatedTextFieldElement) clickedElement;
|
||||
@ -775,7 +775,7 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
return;
|
||||
}
|
||||
|
||||
String text = clickedElement.getText();
|
||||
String text = textField.getText();
|
||||
String word = StringUtilities.findWord(text, location.col);
|
||||
tryGoToScalar(word, newWindow);
|
||||
}
|
||||
@ -879,7 +879,7 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
Address addr = space.getAddress(NumericUtilities.parseHexLong(offsetStr), true);
|
||||
controller.goToAddress(addr, newWindow);
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
// give-up
|
||||
}
|
||||
return;
|
||||
@ -888,7 +888,7 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
long value = NumericUtilities.parseHexLong(text);
|
||||
controller.goToScalar(value, newWindow);
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (NumberFormatException e) {
|
||||
return; // give up
|
||||
}
|
||||
}
|
||||
@ -1017,6 +1017,49 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
return SPECIAL_COLOR_DEF;
|
||||
}
|
||||
|
||||
public String getHighlightedText() {
|
||||
ClangToken token = highlightController.getHighlightedToken();
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
if (token instanceof ClangCommentToken) {
|
||||
return null; // comments are not single words that get highlighted
|
||||
}
|
||||
return token.getText();
|
||||
}
|
||||
|
||||
public String getTextUnderCursor() {
|
||||
|
||||
FieldLocation location = fieldPanel.getCursorLocation();
|
||||
ClangTextField textField = (ClangTextField) fieldPanel.getCurrentField();
|
||||
if (textField == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClangToken token = textField.getToken(location);
|
||||
if (!(token instanceof ClangCommentToken)) {
|
||||
return token.getText(); // non-comment tokens are not multi-word; use the token's text
|
||||
}
|
||||
|
||||
FieldElement clickedElement = textField.getClickedObject(location);
|
||||
if (clickedElement instanceof AnnotatedTextFieldElement) {
|
||||
AnnotatedTextFieldElement annotation = (AnnotatedTextFieldElement) clickedElement;
|
||||
return annotation.getDisplayString();
|
||||
}
|
||||
|
||||
String text = textField.getText();
|
||||
return StringUtilities.findWord(text, location.col);
|
||||
}
|
||||
|
||||
public String getSelectedText() {
|
||||
FieldSelection selection = fieldPanel.getSelection();
|
||||
if (selection.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FieldSelectionHelper.getFieldSelectionText(selection, fieldPanel);
|
||||
}
|
||||
|
||||
public FieldLocation getCursorPosition() {
|
||||
return fieldPanel.getCursorLocation();
|
||||
}
|
||||
@ -1047,15 +1090,6 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getTextSelection() {
|
||||
FieldSelection selection = fieldPanel.getSelection();
|
||||
if (selection.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FieldSelectionHelper.getFieldSelectionText(selection, fieldPanel);
|
||||
}
|
||||
|
||||
public ClangToken getTokenAtCursor() {
|
||||
FieldLocation cursorPosition = fieldPanel.getCursorLocation();
|
||||
Field field = fieldPanel.getCurrentField();
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package ghidra.app.decompiler.component;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.widgets.EventTrigger;
|
||||
import docking.widgets.fieldpanel.field.Field;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
@ -40,6 +42,11 @@ public class LocationClangHighlightController extends ClangHighlightController {
|
||||
return;
|
||||
}
|
||||
|
||||
String text = tok.getText();
|
||||
if (StringUtils.isBlank(text)) {
|
||||
return; // do not highlight whitespace
|
||||
}
|
||||
|
||||
addPrimaryHighlight(tok, defaultHighlightColor);
|
||||
if (tok instanceof ClangSyntaxToken) {
|
||||
addPrimaryHighlightToTokensForParenthesis((ClangSyntaxToken) tok, defaultParenColor);
|
||||
|
@ -462,7 +462,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
||||
@Override
|
||||
public String getTextSelection() {
|
||||
DecompilerPanel decompilerPanel = controller.getDecompilerPanel();
|
||||
return decompilerPanel.getTextSelection();
|
||||
return decompilerPanel.getSelectedText();
|
||||
}
|
||||
|
||||
boolean isBusy() {
|
||||
|
@ -19,6 +19,8 @@ import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.action.KeyBindingData;
|
||||
import docking.action.MenuData;
|
||||
import docking.widgets.*;
|
||||
@ -126,8 +128,15 @@ public class FindAction extends AbstractDecompilerAction {
|
||||
protected void decompilerActionPerformed(DecompilerActionContext context) {
|
||||
DecompilerPanel decompilerPanel = context.getDecompilerPanel();
|
||||
FindDialog dialog = getFindDialog(decompilerPanel);
|
||||
String text = decompilerPanel.getHighlightedText();
|
||||
if (text != null) {
|
||||
String text = decompilerPanel.getSelectedText();
|
||||
if (text == null) {
|
||||
text = decompilerPanel.getHighlightedText();
|
||||
|
||||
// note: if we decide to grab the text under the cursor, then use
|
||||
// text = decompilerPanel.getTextUnderCursor();
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(text)) {
|
||||
dialog.setSearchText(text);
|
||||
}
|
||||
|
||||
|
@ -392,6 +392,8 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the default background color.
|
||||
* @return the default background color.
|
||||
* @see #getBackground()
|
||||
*/
|
||||
public Color getBackgroundColor() {
|
||||
return backgroundColorModel.getDefaultBackgroundColor();
|
||||
@ -431,6 +433,7 @@ public class FieldPanel extends JPanel
|
||||
/**
|
||||
*
|
||||
* Returns the foreground color.
|
||||
* @return the foreground color.
|
||||
*/
|
||||
public Color getForegroundColor() {
|
||||
return paintContext.getForeground();
|
||||
@ -438,6 +441,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the color used as the background for selected items.
|
||||
* @return the color used as the background for selected items.
|
||||
*/
|
||||
public Color getSelectionColor() {
|
||||
return paintContext.getSelectionColor();
|
||||
@ -445,18 +449,24 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the color color used as the background for highlighted items.
|
||||
* @return the color color used as the background for highlighted items.
|
||||
*/
|
||||
public Color getHighlightColor() {
|
||||
return paintContext.getHighlightColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current cursor color.
|
||||
* Returns the cursor color when this field panel is focused.
|
||||
* @return the cursor color when this field panel is focused.
|
||||
*/
|
||||
public Color getFocusedCursorColor() {
|
||||
return paintContext.getFocusedCursorColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cursor color when this field panel is not focused.
|
||||
* @return the cursor color when this field panel is not focused.
|
||||
*/
|
||||
public Color getNonFocusCursorColor() {
|
||||
return paintContext.getNotFocusedCursorColor();
|
||||
}
|
||||
@ -485,6 +495,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the point in pixels of where the cursor is located.
|
||||
* @return the point in pixels of where the cursor is located.
|
||||
*/
|
||||
public Point getCursorPoint() {
|
||||
Rectangle bounds = getCursorBounds();
|
||||
@ -529,7 +540,7 @@ public class FieldPanel extends JPanel
|
||||
selectionListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Adds a selection listener that will be notified while the selection is being created
|
||||
* @param listener the listener to be notified
|
||||
*/
|
||||
@ -537,7 +548,7 @@ public class FieldPanel extends JPanel
|
||||
liveSelectionListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Removes the selection listener from being notified when the selection is being created
|
||||
* @param listener the listener to be removed from being notified
|
||||
*/
|
||||
@ -680,6 +691,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the current selection.
|
||||
* @return the current selection.
|
||||
*/
|
||||
public FieldSelection getSelection() {
|
||||
return new FieldSelection(selection);
|
||||
@ -687,6 +699,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the current highlight (marked area).
|
||||
* @return the current highlight (marked area).
|
||||
*/
|
||||
public FieldSelection getHighlight() {
|
||||
return new FieldSelection(highlight);
|
||||
@ -730,7 +743,6 @@ public class FieldPanel extends JPanel
|
||||
return setCursorPosition(index, fieldNum, row, col, EventTrigger.API_CALL);
|
||||
}
|
||||
|
||||
// for subclasses to control the event trigger
|
||||
/**
|
||||
* Sets the cursorPosition to the given location with the given trigger.
|
||||
*
|
||||
@ -762,6 +774,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the state of the cursor. True if on, false if off.
|
||||
* @return the state of the cursor. True if on, false if off.
|
||||
*/
|
||||
public boolean isCursorOn() {
|
||||
return cursorHandler.isCursorOn();
|
||||
@ -858,6 +871,7 @@ public class FieldPanel extends JPanel
|
||||
* that layout. For example, if the layout is completely displayed, yPos will be 0. If part of
|
||||
* the layout is off the top off the screen, then yPos will have a negative value (indicating
|
||||
* that it begins above the displayable part of the screen.
|
||||
* @return the position
|
||||
*/
|
||||
public ViewerPosition getViewerPosition() {
|
||||
if (layouts.size() > 0) {
|
||||
@ -872,7 +886,8 @@ public class FieldPanel extends JPanel
|
||||
* <= 0, meaning the layout may be partially off the top of the screen.
|
||||
*
|
||||
* @param index the index of the layout to show at the top of the screen.
|
||||
* @param yPos the position to show the layout.
|
||||
* @param xPos the x position to set.
|
||||
* @param yPos the y position to set.
|
||||
*/
|
||||
public void setViewerPosition(BigInteger index, int xPos, int yPos) {
|
||||
if (index.compareTo(BigInteger.ZERO) >= 0 && index.compareTo(model.getNumIndexes()) < 0) {
|
||||
@ -909,7 +924,6 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
|
||||
@Override
|
||||
// BigLayoutModelListener
|
||||
public void dataChanged(BigInteger start, BigInteger end) {
|
||||
if (layouts.isEmpty()) {
|
||||
notifyScrollListenerDataChanged(start, end);
|
||||
@ -961,7 +975,6 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
|
||||
@Override
|
||||
// BigLayoutModelListener
|
||||
public void modelSizeChanged(IndexMapper indexMapper) {
|
||||
BigInteger anchorIndex =
|
||||
layouts.isEmpty() ? BigInteger.ZERO : indexMapper.map(layouts.get(0).getIndex());
|
||||
@ -1044,6 +1057,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
/**
|
||||
* Returns the offset of the cursor from the top of the screen
|
||||
* @return the offset of the cursor from the top of the screen
|
||||
*/
|
||||
public int getCursorOffset() {
|
||||
return getOffset(cursorPosition);
|
||||
@ -1238,7 +1252,9 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the layout containing the given point.
|
||||
* Finds the layout containing the given y position.
|
||||
* @param y the y position.
|
||||
* @return the layout.
|
||||
*/
|
||||
AnchoredLayout findLayoutAt(int y) {
|
||||
for (AnchoredLayout layout : layouts) {
|
||||
@ -1304,10 +1320,11 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
// ==================================================================================================
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
// ==================================================================================================
|
||||
public class FieldPanelMouseAdapter extends MouseAdapter {
|
||||
//==================================================================================================
|
||||
|
||||
private class FieldPanelMouseAdapter extends MouseAdapter {
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
@ -1329,12 +1346,12 @@ public class FieldPanel extends JPanel
|
||||
hoverHandler.hoverExited();
|
||||
}
|
||||
|
||||
public boolean isButton3(MouseEvent e) {
|
||||
private boolean isButton3(MouseEvent e) {
|
||||
return e.getButton() == MouseEvent.BUTTON3;
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldPanelMouseMotionAdapter extends MouseMotionAdapter {
|
||||
private class FieldPanelMouseMotionAdapter extends MouseMotionAdapter {
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
hoverHandler.stopHover();
|
||||
@ -1347,74 +1364,74 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
interface KeyAction {
|
||||
public interface KeyAction {
|
||||
public void handleKeyEvent(KeyEvent event);
|
||||
}
|
||||
|
||||
class UpKeyAction implements KeyAction {
|
||||
private class UpKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkUp(e);
|
||||
}
|
||||
}
|
||||
|
||||
class DownKeyAction implements KeyAction {
|
||||
private class DownKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkDown(e);
|
||||
}
|
||||
}
|
||||
|
||||
class LeftKeyAction implements KeyAction {
|
||||
private class LeftKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkLeft(e);
|
||||
}
|
||||
}
|
||||
|
||||
class RightKeyAction implements KeyAction {
|
||||
private class RightKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkRight(e);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeKeyAction implements KeyAction {
|
||||
private class HomeKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkHome(e);
|
||||
}
|
||||
}
|
||||
|
||||
class EndKeyAction implements KeyAction {
|
||||
private class EndKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkEnd(e);
|
||||
}
|
||||
}
|
||||
|
||||
class PageUpKeyAction implements KeyAction {
|
||||
private class PageUpKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkPageUp(e);
|
||||
}
|
||||
}
|
||||
|
||||
class PageDownKeyAction implements KeyAction {
|
||||
private class PageDownKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkPageDown(e);
|
||||
}
|
||||
}
|
||||
|
||||
class EnterKeyAction implements KeyAction {
|
||||
private class EnterKeyAction implements KeyAction {
|
||||
@Override
|
||||
public void handleKeyEvent(KeyEvent e) {
|
||||
keyHandler.vkEnter(e);
|
||||
}
|
||||
}
|
||||
|
||||
class FieldPanelKeyAdapter extends KeyAdapter {
|
||||
private class FieldPanelKeyAdapter extends KeyAdapter {
|
||||
private Map<KeyStroke, KeyAction> actionMap;
|
||||
|
||||
FieldPanelKeyAdapter() {
|
||||
@ -1460,8 +1477,7 @@ public class FieldPanel extends JPanel
|
||||
// Shift is handled special, so mask it off in the event before getting the action.
|
||||
// If the shift is being held, the selection is extended while moving the cursor.
|
||||
int keyCode = e.getKeyCode();
|
||||
int modifiers =
|
||||
e.getModifiers() & ~(InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK);
|
||||
int modifiers = e.getModifiersEx() & ~InputEvent.SHIFT_DOWN_MASK;
|
||||
KeyEvent maskedEvent = new KeyEvent(e.getComponent(), e.getID(), e.getWhen(), modifiers,
|
||||
keyCode, e.getKeyChar(), e.getKeyLocation());
|
||||
|
||||
@ -1490,7 +1506,7 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public class FieldPanelFocusListener implements FocusListener {
|
||||
private class FieldPanelFocusListener implements FocusListener {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
inFocus = true;
|
||||
@ -1511,7 +1527,7 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public class BigFieldPanelMouseWheelListener implements MouseWheelListener {
|
||||
private class BigFieldPanelMouseWheelListener implements MouseWheelListener {
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
double wheelRotation = e.getPreciseWheelRotation();
|
||||
@ -1555,7 +1571,7 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public class MouseHandler implements ActionListener {
|
||||
private class MouseHandler implements ActionListener {
|
||||
private Timer scrollTimer; // used to generate auto scroll
|
||||
private int mouseDownX;
|
||||
private int mouseDownY;
|
||||
@ -1563,11 +1579,11 @@ public class FieldPanel extends JPanel
|
||||
private int timerScrollAmount;
|
||||
private FieldLocation timerPoint;
|
||||
|
||||
public MouseHandler() {
|
||||
MouseHandler() {
|
||||
scrollTimer = new Timer(100, this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
void dispose() {
|
||||
scrollTimer.stop();
|
||||
}
|
||||
|
||||
@ -1588,7 +1604,7 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public void mousePressed(MouseEvent e) {
|
||||
void mousePressed(MouseEvent e) {
|
||||
requestFocus();
|
||||
didDrag = false;
|
||||
if (e.getButton() != MouseEvent.BUTTON1) {
|
||||
@ -1624,11 +1640,11 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public boolean didDrag() {
|
||||
boolean didDrag() {
|
||||
return didDrag;
|
||||
}
|
||||
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
void mouseDragged(MouseEvent e) {
|
||||
if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == 0) {
|
||||
return;
|
||||
}
|
||||
@ -1652,7 +1668,7 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
void mouseReleased(MouseEvent e) {
|
||||
scrollTimer.stop();
|
||||
if (e.getButton() != MouseEvent.BUTTON1) {
|
||||
return;
|
||||
@ -1661,7 +1677,7 @@ public class FieldPanel extends JPanel
|
||||
cursorHandler.setCursorPos(e.getX(), e.getY(), EventTrigger.GUI_ACTION);
|
||||
if (didDrag) {
|
||||
// Send an event after the drag is finished. Event are suppressed while dragging,
|
||||
// meaning that the above call to setCursorPos() will not have fired an event
|
||||
// meaning that the above call to setCursorPos() will not have fired an event
|
||||
// because the internal cursor position did not change during the mouse release.
|
||||
cursorHandler.notifyCursorChanged(EventTrigger.GUI_ACTION);
|
||||
}
|
||||
@ -1672,55 +1688,51 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically checks if the the "shift" modifier is on and the "control" modifier is not.
|
||||
* Note that "control" is operating system dependent. It is <control> on windows, and
|
||||
* <command> on mac.
|
||||
* Checks if the the "shift" modifier is on and the "control" modifier is not.
|
||||
*/
|
||||
private boolean isAddToContiguousSelectionActivator(MouseEvent e) {
|
||||
return (e.isShiftDown() && !DockingUtils.isControlModifier(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically checks if the the "control" modifier is on and the shift modifier is not. Note
|
||||
* that "control" is operating system dependent. It is <control> on windows, and <command>
|
||||
* on mac.
|
||||
* Checks if the the "control" modifier is on and the shift modifier is not.
|
||||
*/
|
||||
private boolean isAddRemoveDisjointSelectionActivator(MouseEvent e) {
|
||||
return DockingUtils.isControlModifier(e) && !e.isShiftDown();
|
||||
}
|
||||
}
|
||||
|
||||
class KeyHandler {
|
||||
private class KeyHandler {
|
||||
|
||||
public void shiftKeyPressed() {
|
||||
void shiftKeyPressed() {
|
||||
selectionHandler.beginSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void shiftKeyReleased() {
|
||||
void shiftKeyReleased() {
|
||||
selectionHandler.endSelectionSequence();
|
||||
}
|
||||
|
||||
public void vkUp(KeyEvent e) {
|
||||
void vkUp(KeyEvent e) {
|
||||
cursorHandler.doCursorUp(EventTrigger.GUI_ACTION);
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkDown(KeyEvent e) {
|
||||
void vkDown(KeyEvent e) {
|
||||
cursorHandler.doCursorDown(EventTrigger.GUI_ACTION);
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkLeft(KeyEvent e) {
|
||||
void vkLeft(KeyEvent e) {
|
||||
cursorHandler.doCursorLeft(EventTrigger.GUI_ACTION);
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkRight(KeyEvent e) {
|
||||
void vkRight(KeyEvent e) {
|
||||
cursorHandler.doCursorRight(EventTrigger.GUI_ACTION);
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkEnd(KeyEvent e) {
|
||||
void vkEnd(KeyEvent e) {
|
||||
if (DockingUtils.isControlModifier(e)) {
|
||||
doEndOfFile(EventTrigger.GUI_ACTION);
|
||||
}
|
||||
@ -1730,7 +1742,7 @@ public class FieldPanel extends JPanel
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkHome(KeyEvent e) {
|
||||
void vkHome(KeyEvent e) {
|
||||
if (DockingUtils.isControlModifier(e)) {
|
||||
doTopOfFile(EventTrigger.GUI_ACTION);
|
||||
}
|
||||
@ -1740,27 +1752,26 @@ public class FieldPanel extends JPanel
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkPageUp(KeyEvent e) {
|
||||
void vkPageUp(KeyEvent e) {
|
||||
doPageUp(EventTrigger.GUI_ACTION);
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkPageDown(KeyEvent e) {
|
||||
void vkPageDown(KeyEvent e) {
|
||||
doPageDown(EventTrigger.GUI_ACTION);
|
||||
selectionHandler.updateSelectionSequence(cursorPosition);
|
||||
}
|
||||
|
||||
public void vkEnter(KeyEvent e) {
|
||||
void vkEnter(KeyEvent e) {
|
||||
Point pt = getCursorPoint();
|
||||
if (pt != null) {
|
||||
notifyFieldMouseListeners(new MouseEvent(e.getComponent(), e.getID(), e.getWhen(),
|
||||
0, pt.x, pt.y, 2, false, MouseEvent.BUTTON1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SelectionHandler {
|
||||
private class SelectionHandler {
|
||||
private boolean selectionOn = true;
|
||||
private boolean selectionChanged;
|
||||
private boolean removeFromSelection;
|
||||
@ -1828,7 +1839,7 @@ public class FieldPanel extends JPanel
|
||||
selectionChanged = true;
|
||||
}
|
||||
|
||||
public void enableSelection(boolean b) {
|
||||
void enableSelection(boolean b) {
|
||||
selectionOn = b;
|
||||
if (!selectionOn) {
|
||||
selection.clear();
|
||||
@ -1836,7 +1847,7 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public class CursorHandler {
|
||||
private class CursorHandler {
|
||||
private int lastX = 0;
|
||||
private boolean cursorOn = true;
|
||||
private Field currentField;
|
||||
@ -1846,7 +1857,7 @@ public class FieldPanel extends JPanel
|
||||
cursorBlinker = new CursorBlinker(FieldPanel.this);
|
||||
}
|
||||
|
||||
public void setBlinkCursor(Boolean blinkCursor) {
|
||||
void setBlinkCursor(Boolean blinkCursor) {
|
||||
if (blinkCursor && cursorBlinker == null) {
|
||||
cursorBlinker = new CursorBlinker(FieldPanel.this);
|
||||
}
|
||||
@ -1856,28 +1867,28 @@ public class FieldPanel extends JPanel
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCursorOn() {
|
||||
boolean isCursorOn() {
|
||||
return cursorOn;
|
||||
}
|
||||
|
||||
public void setCursorOn(boolean cursorOn) {
|
||||
void setCursorOn(boolean cursorOn) {
|
||||
this.cursorOn = cursorOn;
|
||||
|
||||
}
|
||||
|
||||
public void focusLost() {
|
||||
void focusLost() {
|
||||
if (cursorBlinker != null) {
|
||||
cursorBlinker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void focusGained() {
|
||||
void focusGained() {
|
||||
if (cursorBlinker != null) {
|
||||
cursorBlinker.restart();
|
||||
}
|
||||
}
|
||||
|
||||
public Field getCurrentField() {
|
||||
Field getCurrentField() {
|
||||
if (currentField == null) {
|
||||
AnchoredLayout layout = findLayoutOnScreen(cursorPosition.getIndex());
|
||||
if (layout != null) {
|
||||
@ -2135,7 +2146,7 @@ public class FieldPanel extends JPanel
|
||||
|
||||
}
|
||||
|
||||
public void scrollToCursor() {
|
||||
void scrollToCursor() {
|
||||
doScrollTo(cursorPosition);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,8 +19,36 @@ import java.math.BigInteger;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import docking.widgets.fieldpanel.Layout;
|
||||
import docking.widgets.fieldpanel.field.Field;
|
||||
|
||||
/**
|
||||
* Class to represent locations within the FieldViewer.
|
||||
* Class to represent {@link Field} locations within the field viewer.
|
||||
* <p>
|
||||
* A field location represents a place within a Field. Fields live within a concept we call a
|
||||
* layout. A layout represents an 'item', for example an address, along with a grouping of
|
||||
* related information. Each layout will contain one or more Field objects. Further, each
|
||||
* layout's fields may have varying shapes, such as single or multiple rows within the layout.
|
||||
* Thusly, a layout could conceptually represent a single line of text or multiple groupings of
|
||||
* text and images, similar to how a newspaper or web page is laid out.
|
||||
* <p>
|
||||
* A layout lives in a larger collection of layouts, which are laid out vertically. The index of a
|
||||
* layout is its position within that larger list. This class contains the index of the layout
|
||||
* within which it lives.
|
||||
* <p>
|
||||
* A {@link FieldSelection} may be within a single layout or may cross multiple layouts. To
|
||||
* determine if a selection crosses multiple layouts, you can get the {@link FieldRange range} of
|
||||
* the selection. You can then use the range's start and end locations to determine if the
|
||||
* selection spans multiple layouts. If the start and end indexes of the range are the same, then
|
||||
* the selection is within a single layout; otherwise, the selection spans multiple layouts.
|
||||
* <p>
|
||||
* This location also contains row and column values. These values refer to the row and column of
|
||||
* text within a single Field. Lastly, this class contains a field number, which represents the
|
||||
* relative field number inside of the over layout, which may contain multiple fields.
|
||||
*
|
||||
* @see FieldSelection
|
||||
* @see FieldRange
|
||||
* @see Layout
|
||||
*/
|
||||
public class FieldLocation implements Comparable<FieldLocation> {
|
||||
public static final FieldLocation MAX =
|
||||
@ -29,7 +56,7 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
public int fieldNum; // the number of the field for this location
|
||||
public int row; // the row position within the field .
|
||||
public int row; // the row position within the field
|
||||
public int col; // the col position within the field
|
||||
|
||||
private BigInteger index;
|
||||
@ -94,12 +121,19 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
this(loc.index, loc.fieldNum, loc.row, loc.col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index for this location. The index corresponds to the layout that contains
|
||||
* the field represented by this location. See the javadoc header for more details.
|
||||
* @return the index for this location.
|
||||
*/
|
||||
public BigInteger getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field index for this location.
|
||||
* Returns the number of the field for this location. This is the number of the field within
|
||||
* a given layout. See the javadoc header for more details.
|
||||
* @return the number of the field for this location.
|
||||
*/
|
||||
public int getFieldNum() {
|
||||
return fieldNum;
|
||||
@ -107,6 +141,7 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
|
||||
/**
|
||||
* Returns the row within the Field for this location.
|
||||
* @return the row within the Field for this location.
|
||||
*/
|
||||
public int getRow() {
|
||||
return row;
|
||||
@ -114,15 +149,12 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
|
||||
/**
|
||||
* Returns the column within the Field for this location.
|
||||
* @return the column within the Field for this location.
|
||||
*/
|
||||
public int getCol() {
|
||||
return col;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
@ -141,6 +173,7 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(FieldLocation o) {
|
||||
int compareTo = index.compareTo(o.index);
|
||||
if (compareTo != 0) {
|
||||
@ -167,19 +200,11 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return index.intValue() + fieldNum * 100 + row * 10 + col;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return index.toString() + ", " + fieldNum + ", " + row + ", " + col;
|
||||
@ -200,7 +225,6 @@ public class FieldLocation implements Comparable<FieldLocation> {
|
||||
fieldNum = loc.fieldNum;
|
||||
row = loc.row;
|
||||
col = loc.col;
|
||||
|
||||
}
|
||||
|
||||
public void setIndex(BigInteger index) {
|
||||
|
@ -15,20 +15,24 @@
|
||||
*/
|
||||
package docking.widgets.fieldpanel.support;
|
||||
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import docking.widgets.fieldpanel.Layout;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* Class to a range consisting of a start position within a start row to an end position within an
|
||||
* end row (exclusive).
|
||||
* A range consists of a start position within a start row to an end position within an end row
|
||||
* (exclusive).
|
||||
* <p>
|
||||
* Conceptually, this class can be thought of as a range of rows (defined by
|
||||
* <code>startIndex</code> and <code>endindex</code>) with sub-positions within those rows (defined by
|
||||
* <code>startField</code> and <code>endField</code>). As an example, consider a text select that begins on
|
||||
* some word in a row and ends on another word in a different row.
|
||||
* Conceptually, this class can be thought of as a range of rows (defined by start and end
|
||||
* indexes) with sub-positions within those rows. As an example, consider a text selection that
|
||||
* begins on some word in a row and ends on another word in a different row.
|
||||
*
|
||||
* @see FieldSelection
|
||||
* @see FieldLocation
|
||||
* @see Layout
|
||||
*/
|
||||
public class FieldRange implements Comparable<FieldRange> {
|
||||
FieldLocation start;
|
||||
@ -71,9 +75,6 @@ public class FieldRange implements Comparable<FieldRange> {
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation for debugging purposes.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FieldRange: (" + start + " :: " + end + ")";
|
||||
@ -108,6 +109,7 @@ public class FieldRange implements Comparable<FieldRange> {
|
||||
return start.hashCode() << 16 + end.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(FieldRange o) {
|
||||
int result = start.compareTo(o.start);
|
||||
if (result == 0) {
|
||||
@ -190,7 +192,8 @@ public class FieldRange implements Comparable<FieldRange> {
|
||||
|
||||
public boolean containsEntirely(int index) {
|
||||
if (start.getIndex().intValue() > index ||
|
||||
((start.getIndex().intValue() == index) && (start.fieldNum != 0 || start.row != 0 || start.col != 0))) {
|
||||
((start.getIndex().intValue() == index) &&
|
||||
(start.fieldNum != 0 || start.row != 0 || start.col != 0))) {
|
||||
return false;
|
||||
}
|
||||
if (end.getIndex().intValue() <= index) {
|
||||
|
@ -15,17 +15,26 @@
|
||||
*/
|
||||
package docking.widgets.fieldpanel.support;
|
||||
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import docking.widgets.fieldpanel.Layout;
|
||||
import ghidra.framework.options.SaveState;
|
||||
|
||||
/**
|
||||
* Interface for reporting the FieldViewer selection. The selection consists of
|
||||
* a sequence of ranges of indexes.
|
||||
* This class represents a selection in a field viewer.
|
||||
* <p>
|
||||
* A {@link FieldSelection} may be within a single layout or may cross multiple layouts. To
|
||||
* determine if a selection crosses multiple layouts, you can get the {@link FieldRange range} of
|
||||
* the selection. You can then use the range's start and end locations to determine if the
|
||||
* selection spans multiple layouts. If the start and end indexes of the range are the same, then
|
||||
* the selection is within a single layout; otherwise, the selection spans multiple layouts.
|
||||
*
|
||||
* @see FieldRange
|
||||
* @see FieldLocation
|
||||
* @see Layout
|
||||
*/
|
||||
public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
@ -35,7 +44,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
* Construct a new empty FieldSelection.
|
||||
*/
|
||||
public FieldSelection() {
|
||||
ranges = new ArrayList<FieldRange>(4);
|
||||
ranges = new ArrayList<>(4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +52,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
* @param selection the FieldSelection to copy.
|
||||
*/
|
||||
public FieldSelection(FieldSelection selection) {
|
||||
ranges = new ArrayList<FieldRange>(selection.ranges.size());
|
||||
ranges = new ArrayList<>(selection.ranges.size());
|
||||
for (FieldRange range : selection.ranges) {
|
||||
ranges.add(new FieldRange(range));
|
||||
}
|
||||
@ -53,7 +62,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
* Removes all indexes from the list.
|
||||
*/
|
||||
public void clear() {
|
||||
ranges = new ArrayList<FieldRange>(4);
|
||||
ranges = new ArrayList<>(4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,6 +78,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
* Returns the range if the given Field at the given index is in the selection.
|
||||
* Otherwise returns null.
|
||||
* @param loc location to find the range for.
|
||||
* @return the range
|
||||
*/
|
||||
public FieldRange getRangeContaining(FieldLocation loc) {
|
||||
int insertIndex = Collections.binarySearch(ranges, new FieldRange(loc, FieldLocation.MAX));
|
||||
@ -95,9 +105,11 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
/**
|
||||
* Returns true if the all the fields in the layout with the given index are
|
||||
* included in this selection.
|
||||
* included in this selection.
|
||||
* @param index index of the layout to test.
|
||||
|
||||
* @return true if the all the fields in the layout with the given index are
|
||||
* included in this selection.
|
||||
|
||||
*/
|
||||
public boolean containsEntirely(BigInteger index) {
|
||||
FieldLocation start = new FieldLocation(index, 0, 0, 0);
|
||||
@ -229,12 +241,14 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insertIndex++;
|
||||
while (insertIndex < ranges.size()) {
|
||||
FieldRange range = ranges.get(insertIndex);
|
||||
if (!deleteRange.intersects(range)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FieldRange leftOver = range.subtract(deleteRange);
|
||||
if (range.isEmpty()) {
|
||||
ranges.remove(insertIndex);
|
||||
@ -264,6 +278,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
/**
|
||||
* Returns the current number of ranges in the list.
|
||||
* @return the current number of ranges in the list.
|
||||
*/
|
||||
public int getNumRanges() {
|
||||
return ranges.size();
|
||||
@ -272,6 +287,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
/**
|
||||
* Returns the i'th Field Range in the selection.
|
||||
* @param rangeNum the index of the range to retrieve.
|
||||
* @return the range
|
||||
*/
|
||||
public FieldRange getFieldRange(int rangeNum) {
|
||||
return ranges.get(rangeNum);
|
||||
@ -279,8 +295,9 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
/**
|
||||
* Compute the intersection of this field selection and another one.
|
||||
* The intersection of two field selections is all fields existing in
|
||||
* The intersection of two field selections is all fields existing in
|
||||
* both selections.
|
||||
*
|
||||
* <P>Note: This field selection becomes the intersection.
|
||||
*
|
||||
* @param selection field selection to intersect.
|
||||
@ -304,6 +321,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
/**
|
||||
* Computes the intersection of this field selection and the given field selection.
|
||||
* @param selection the selection to intersect with.
|
||||
* @return the selection
|
||||
*/
|
||||
public final FieldSelection findIntersection(FieldSelection selection) {
|
||||
if (selection == null || this.ranges.size() == 0 || selection.ranges.size() == 0) {
|
||||
@ -323,16 +341,14 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
/**
|
||||
* Delete all fields in the ranges in the given field selection from this one.
|
||||
* @param selection the field selection fields to remove from this
|
||||
* field selection.
|
||||
* @param selection the field selection fields to remove from this field selection.
|
||||
*/
|
||||
public final void delete(FieldSelection selection) {
|
||||
if (selection == null || this.ranges.size() == 0 || selection.ranges.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// process all ranges in the selection, delete each one's
|
||||
// associated fields from this set.
|
||||
// process all ranges in the selection, delete each associated fields from this set
|
||||
for (FieldRange range : selection.ranges) {
|
||||
removeRange(range.start, range.end);
|
||||
}
|
||||
@ -340,63 +356,50 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
/**
|
||||
* Insert all fields in the ranges in the given field selection from this one.
|
||||
* @param selection the field selection fields to add to this
|
||||
* field selection.
|
||||
* @param selection the field selection fields to add to this field selection.
|
||||
*/
|
||||
public final void insert(FieldSelection selection) {
|
||||
if (selection == null || selection.getNumRanges() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// process all ranges in the selection, add each one's
|
||||
// associated fields from this set.
|
||||
// process all ranges in the selection, add each associated fields from this set
|
||||
for (FieldRange range : selection.ranges) {
|
||||
addRange(range.start, range.end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the ranges for debugging.
|
||||
*/
|
||||
public void printRanges() {
|
||||
Msg.debug(this, "*********");
|
||||
for (FieldRange range : ranges) {
|
||||
Msg.debug(this, range);
|
||||
}
|
||||
Msg.debug(this, "**********");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (FieldRange range : ranges) {
|
||||
buf.append(range.toString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((ranges == null) ? 0 : ranges.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof FieldSelection)) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FieldSelection other = (FieldSelection) obj;
|
||||
if (ranges.size() != other.ranges.size()) {
|
||||
return false;
|
||||
}
|
||||
int n = ranges.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
FieldRange thisRange = ranges.get(i);
|
||||
FieldRange otherRange = other.ranges.get(i);
|
||||
if (!thisRange.equals(otherRange)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return Objects.equals(ranges, other.ranges);
|
||||
}
|
||||
|
||||
public void save(SaveState saveState) {
|
||||
@ -424,7 +427,7 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return ranges.size() == 0;
|
||||
return ranges.isEmpty();
|
||||
}
|
||||
|
||||
public FieldSelection intersect(int index) {
|
||||
@ -448,15 +451,17 @@ public class FieldSelection implements Iterable<FieldRange> {
|
||||
|
||||
int insertIndex = Collections.binarySearch(ranges, range);
|
||||
|
||||
// if exact match, return it;
|
||||
// if exact match, return it
|
||||
if (insertIndex >= 0) {
|
||||
intersection.addRange(range);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
insertIndex = -insertIndex - 2;
|
||||
if (insertIndex < 0) {
|
||||
insertIndex++;
|
||||
}
|
||||
|
||||
while (insertIndex < ranges.size()) {
|
||||
FieldRange searchRange = ranges.get(insertIndex);
|
||||
if (searchRange.start.compareTo(range.end) >= 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user