From 4189f73db83371dd19881fec6c157bcb75dfd8ed Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Thu, 2 Nov 2023 11:11:12 -0400 Subject: [PATCH] GP-3874: Fix radix with Copy in Registers panel. --- .../register/DebuggerRegistersProvider.java | 61 ++++---- .../DefaultEnumeratedColumnTableModel.java | 42 ++++++ .../table/HexBigIntegerTableCellEditor.java | 1 + .../table/HexBigIntegerTableCellRenderer.java | 49 ------- .../table/HexDefaultGColumnRenderer.java | 35 +++++ .../table/AbstractDynamicTableColumn.java | 4 +- .../widgets/table/GTableCellRenderer.java | 43 ++++-- .../widgets/textfield/IntegerTextField.java | 130 +++++++++++------- 8 files changed, 225 insertions(+), 140 deletions(-) delete mode 100644 Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellRenderer.java create mode 100644 Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexDefaultGColumnRenderer.java diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java index f8b3f6289e..735507a117 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java @@ -54,7 +54,7 @@ import ghidra.base.widgets.table.DataTypeTableCellEditor; import ghidra.dbg.error.DebuggerModelAccessException; import ghidra.dbg.target.TargetRegisterBank; import ghidra.dbg.target.TargetThread; -import ghidra.docking.settings.Settings; +import ghidra.docking.settings.*; import ghidra.framework.model.DomainObject; import ghidra.framework.model.DomainObjectChangeRecord; import ghidra.framework.options.AutoOptions; @@ -82,6 +82,7 @@ import ghidra.util.data.DataTypeParser.AllowedDataTypes; import ghidra.util.exception.CancelledException; import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTableFilterPanel; +import ghidra.util.table.column.GColumnRenderer; import ghidra.util.task.TaskMonitor; public class DebuggerRegistersProvider extends ComponentProviderAdapter @@ -145,33 +146,53 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter protected enum RegisterTableColumns implements EnumeratedTableColumn { - FAV("Fav", Boolean.class, RegisterRow::isFavorite, RegisterRow::setFavorite, // + FAV("Fav", 1, Boolean.class, RegisterRow::isFavorite, RegisterRow::setFavorite, // r -> true, SortDirection.DESCENDING), - NUMBER("#", Integer.class, RegisterRow::getNumber), - NAME("Name", String.class, RegisterRow::getName), - VALUE("Value", BigInteger.class, RegisterRow::getValue, RegisterRow::setValue, // - RegisterRow::isValueEditable, SortDirection.ASCENDING), - TYPE("Type", DataType.class, RegisterRow::getDataType, RegisterRow::setDataType, // + NUMBER("#", 1, Integer.class, RegisterRow::getNumber), + NAME("Name", 40, String.class, RegisterRow::getName), + VALUE("Value", 100, BigInteger.class, RegisterRow::getValue, RegisterRow::setValue, // + RegisterRow::isValueEditable, SortDirection.ASCENDING) { + private static final RegisterValueCellRenderer RENDERER = + new RegisterValueCellRenderer(); + private static final SettingsDefinition[] DEFS = new SettingsDefinition[] { + FormatSettingsDefinition.DEF_HEX, + }; + + @Override + public GColumnRenderer getRenderer() { + return RENDERER; + } + + @Override + public SettingsDefinition[] getSettingsDefinitions() { + return DEFS; + } + }, + TYPE("Type", 40, DataType.class, RegisterRow::getDataType, RegisterRow::setDataType, // r -> true, SortDirection.ASCENDING), - REPR("Repr", String.class, RegisterRow::getRepresentation, RegisterRow::setRepresentation, // + REPR("Repr", 100, String.class, RegisterRow::getRepresentation, RegisterRow::setRepresentation, // RegisterRow::isRepresentationEditable, SortDirection.ASCENDING); private final String header; + private final int width; private final Function getter; private final BiConsumer setter; private final Predicate editable; private final Class cls; private final SortDirection direction; - RegisterTableColumns(String header, Class cls, Function getter) { - this(header, cls, getter, null, null, SortDirection.ASCENDING); + RegisterTableColumns(String header, int width, Class cls, + Function getter) { + this(header, width, cls, getter, null, null, SortDirection.ASCENDING); } @SuppressWarnings("unchecked") - RegisterTableColumns(String header, Class cls, Function getter, + RegisterTableColumns(String header, int width, Class cls, + Function getter, BiConsumer setter, Predicate editable, SortDirection direction) { this.header = header; + this.width = width; this.cls = cls; this.getter = getter; this.setter = (BiConsumer) setter; @@ -208,6 +229,11 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter public SortDirection defaultSortDirection() { return direction; } + + @Override + public int getPreferredWidth() { + return width; + } } protected static class RegistersTableModel @@ -401,7 +427,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter } } - class RegisterValueCellRenderer extends HexBigIntegerTableCellRenderer { + static class RegisterValueCellRenderer extends HexDefaultGColumnRenderer { @Override public final Component getTableCellRendererComponent(GTableCellRenderingData data) { super.getTableCellRendererComponent(data); @@ -590,21 +616,10 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter }); TableColumnModel columnModel = regsTable.getColumnModel(); - TableColumn favCol = columnModel.getColumn(RegisterTableColumns.FAV.ordinal()); - favCol.setPreferredWidth(1); - TableColumn numCol = columnModel.getColumn(RegisterTableColumns.NUMBER.ordinal()); - numCol.setPreferredWidth(1); - TableColumn nameCol = columnModel.getColumn(RegisterTableColumns.NAME.ordinal()); - nameCol.setPreferredWidth(40); TableColumn valCol = columnModel.getColumn(RegisterTableColumns.VALUE.ordinal()); - valCol.setCellRenderer(new RegisterValueCellRenderer()); valCol.setCellEditor(new HexBigIntegerTableCellEditor()); - valCol.setPreferredWidth(100); TableColumn typeCol = columnModel.getColumn(RegisterTableColumns.TYPE.ordinal()); typeCol.setCellEditor(new RegisterDataTypeEditor()); - typeCol.setPreferredWidth(50); - TableColumn reprCol = columnModel.getColumn(RegisterTableColumns.REPR.ordinal()); - reprCol.setPreferredWidth(100); } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java index 07ee4b8432..61ec02f703 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnTableModel.java @@ -21,8 +21,10 @@ import java.util.function.Predicate; import docking.widgets.table.ColumnSortState.SortDirection; import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn; import ghidra.docking.settings.Settings; +import ghidra.docking.settings.SettingsDefinition; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.ServiceProvider; +import ghidra.util.table.column.GColumnRenderer; /** * A table model whose columns are described using an {@link Enum}. @@ -106,6 +108,26 @@ public class DefaultEnumeratedColumnTableModel & EnumeratedTab default public SortDirection defaultSortDirection() { return SortDirection.ASCENDING; } + + default public int getPreferredWidth() { + return -1; + } + + /** + * Because of limitations with Java generics and Enumerations, type checking cannot be + * guaranteed here. The user must ensure that any returned by {@link #getValueOf(Object)} + * can be accepted by the renderer returned here. The framework will perform an unchecked + * cast of the renderer. + * + * @return the renderer + */ + default public GColumnRenderer getRenderer() { + return null; + } + + default public SettingsDefinition[] getSettingsDefinitions() { + return null; + } } private final List modelData = new ArrayList<>(); @@ -167,6 +189,26 @@ public class DefaultEnumeratedColumnTableModel & EnumeratedTab ServiceProvider serviceProvider) { col.setValueOf(row, value); } + + @Override + @SuppressWarnings("unchecked") + public GColumnRenderer getColumnRenderer() { + return (GColumnRenderer) col.getRenderer(); + } + + @Override + public int getColumnPreferredWidth() { + return col.getPreferredWidth(); + } + + @Override + public SettingsDefinition[] getSettingsDefinitions() { + SettingsDefinition[] defs = col.getSettingsDefinitions(); + if (defs != null) { + return defs; + } + return super.getSettingsDefinitions(); + } } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellEditor.java b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellEditor.java index 07c7e411ae..e8b5ce3b1f 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellEditor.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellEditor.java @@ -52,6 +52,7 @@ public class HexBigIntegerTableCellEditor extends AbstractCellEditor implements input.setHexMode(); input.setAllowsHexPrefix(false); input.setShowNumberMode(true); + input.setHorizontalAlignment(JTextField.RIGHT); if (value != null) { input.setValue((BigInteger) value); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellRenderer.java b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellRenderer.java deleted file mode 100644 index c5433c36cb..0000000000 --- a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexBigIntegerTableCellRenderer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking.widgets.table; - -import java.awt.Component; -import java.math.BigInteger; - -import javax.swing.JTable; -import javax.swing.table.TableModel; - -import ghidra.docking.settings.Settings; -import ghidra.util.table.column.AbstractGColumnRenderer; - -public class HexBigIntegerTableCellRenderer extends AbstractGColumnRenderer { - @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(fixedWidthFont); - } - - protected String formatBigInteger(BigInteger value) { - return value == null ? "??" : value.toString(16); - } - - @Override - public Component getTableCellRendererComponent(GTableCellRenderingData data) { - super.getTableCellRendererComponent(data); - setText(formatBigInteger((BigInteger) data.getValue())); - return this; - } - - // TODO: Seems the filter model does not heed this.... - @Override - public String getFilterString(BigInteger t, Settings settings) { - return formatBigInteger(t); - } -} diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexDefaultGColumnRenderer.java b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexDefaultGColumnRenderer.java new file mode 100644 index 0000000000..45a5bfdd00 --- /dev/null +++ b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/HexDefaultGColumnRenderer.java @@ -0,0 +1,35 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.widgets.table; + +import ghidra.docking.settings.FormatSettingsDefinition; +import ghidra.docking.settings.Settings; +import ghidra.util.table.column.AbstractGColumnRenderer; + +public class HexDefaultGColumnRenderer extends AbstractGColumnRenderer { + private final static FormatSettingsDefinition INTEGER_RADIX_SETTING = + FormatSettingsDefinition.DEF_HEX; + + @Override + protected int getRadix(Settings settings) { + return INTEGER_RADIX_SETTING.getRadix(settings); + } + + @Override + public String getFilterString(Number t, Settings settings) { + return formatNumber(t, settings); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractDynamicTableColumn.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractDynamicTableColumn.java index 963261e502..b0b9683370 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractDynamicTableColumn.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractDynamicTableColumn.java @@ -50,10 +50,10 @@ public abstract class AbstractDynamicTableColumntoString() method - * when rendering the cells of the table. + * A default table cell renderer that relies on the toString() method when rendering + * the cells of the table. */ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCellRenderer { @@ -84,6 +84,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe /** * Constructs a new GTableCellRenderer using the specified font. + * * @param f the font to use when rendering text in the table cells */ public GTableCellRenderer(Font f) { @@ -93,6 +94,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe /** * Return the cell renderer text + * * @param value Cell object value * @return A string interpretation of value; generated by calling value.toString() */ @@ -101,8 +103,8 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe } /** - * Satisfies the Java {@link javax.swing.table.TableCellRenderer} interface; retrieves - * column data via a GTableCellRenderingData object, and defers painting to + * Satisfies the Java {@link javax.swing.table.TableCellRenderer} interface; retrieves column + * data via a GTableCellRenderingData object, and defers painting to * {@link #getTableCellRendererComponent(GTableCellRenderingData)}. *

* This is marked final to redirect subclasses to the enhanced method, @@ -111,8 +113,9 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe * Throws an AssertException if the table this renderer is used with is not a * {@link docking.widgets.table.GTable} instance. * - * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int) - * @see #getTableCellRendererComponent(GTableCellRenderingData) + * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, + * java.lang.Object, boolean, boolean, int, int) + * @see #getTableCellRendererComponent(GTableCellRenderingData) */ @Override public final Component getTableCellRendererComponent(JTable table, Object value, @@ -144,8 +147,9 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe /** * Provide basic cell rendering -- setting foreground and background colors, font, text, - * alignment, drop color, and border. Additional data that may be of use to the renderer - * is passed through the {@link docking.widgets.table.GTableCellRenderingData} object. + * alignment, drop color, and border. Additional data that may be of use to the renderer is + * passed through the {@link docking.widgets.table.GTableCellRenderingData} object. + * * @param data Context data used in the rendering of a data cell. * @return The component used for drawing the table cell. */ @@ -199,8 +203,21 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe setFont(defaultFont); } + protected int getRadix(Settings settings) { + return INTEGER_RADIX_SETTING.getRadix(settings); + } + + protected SignednessFormatMode getSignMode(Settings settings) { + return INTEGER_SIGNEDNESS_MODE_SETTING.getFormatMode(settings); + } + + protected int getPrecision(Settings settings) { + return FLOATING_POINT_PRECISION_SETTING.getPrecision(settings); + } + /** * Format a Number per the Settings parameters. + * * @param value the number to format * @param settings settings controlling the display of the Number parameter * @return a formatted representation of the Number value @@ -208,8 +225,8 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe protected String formatNumber(Number value, Settings settings) { if (NumericUtilities.isIntegerType(value)) { - int radix = INTEGER_RADIX_SETTING.getRadix(settings); - SignednessFormatMode signMode = INTEGER_SIGNEDNESS_MODE_SETTING.getFormatMode(settings); + int radix = getRadix(settings); + SignednessFormatMode signMode = getSignMode(settings); long number = value.longValue(); return NumericUtilities.formatNumber(number, radix, signMode); } @@ -219,18 +236,18 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe if (number.isNaN() || number.isInfinite()) { return Character.toString('\u221e'); // infinity symbol } - int precision = FLOATING_POINT_PRECISION_SETTING.getPrecision(settings); + int precision = getPrecision(settings); return getFormatter(precision).format(number); } if (value instanceof BigInteger) { - int radix = INTEGER_RADIX_SETTING.getRadix(settings); + int radix = getRadix(settings); return ((BigInteger) value).toString(radix); } if (value instanceof BigDecimal) { - int precision = FLOATING_POINT_PRECISION_SETTING.getPrecision(settings); + int precision = getPrecision(settings); DecimalFormat formatter = getFormatter(precision); formatter.format(value); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java index 26711c5433..0260b62b19 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java @@ -34,28 +34,30 @@ import ghidra.util.SystemUtilities; /** * TextField for entering integer numbers, either in decimal or hex. * - *

This field does continuous checking, so - * you can't enter a bad value. + *

+ * This field does continuous checking, so you can't enter a bad value. * - *

Internally, values are maintained using BigIntegers so this field can - * contain numbers as large as desired. There are convenience methods for getting the value as - * either an int or long. If using these convenience methods, you should also set the max allowed - * value so that users can't enter a value larger than can be represented by the {@link #getIntValue()} - * or {@link #getLongValue()} methods as appropriate. + *

+ * Internally, values are maintained using BigIntegers so this field can contain numbers as large as + * desired. There are convenience methods for getting the value as either an int or long. If using + * these convenience methods, you should also set the max allowed value so that users can't enter a + * value larger than can be represented by the {@link #getIntValue()} or {@link #getLongValue()} + * methods as appropriate. * - *

There are several configuration options as follows: + *

+ * There are several configuration options as follows: *

    - *
  • Allows negative numbers - either support all integer numbers or just non-negative - * numbers. See {@link #setAllowNegativeValues(boolean)}
  • - *
  • Allows hex prefix - If this mode is on, then hex mode is turned on and off automatically - * depending whether or not the text starts with 0x. Otherwise, the hex/decimal mode is set externally - * (either programmatically or pressing <CTRL> M) and the user is restricted to the numbers/letters - * appropriate for that mode. See {@link #setAllowsHexPrefix(boolean)}
  • - *
  • Have a max value - a max value can be set (must be positive) such that the user can not type a - * number whose absolute value is greater than the max. Otherwise, the value is unlimited if max is - * null/unspecified. See {@link #setMaxValue(BigInteger)}
  • - *
  • Show the number mode as hint text - If on either "Hex" or "Dec" is displayed lightly in the - * bottom right portion of the text field. See {@link #setShowNumberMode(boolean)}
  • + *
  • Allows negative numbers - either support all integer numbers or just non-negative numbers. + * See {@link #setAllowNegativeValues(boolean)}
  • + *
  • Allows hex prefix - If this mode is on, then hex mode is turned on and off automatically + * depending whether or not the text starts with 0x. Otherwise, the hex/decimal mode is set + * externally (either programmatically or pressing <CTRL> M) and the user is restricted to the + * numbers/letters appropriate for that mode. See {@link #setAllowsHexPrefix(boolean)}
  • + *
  • Have a max value - a max value can be set (must be positive) such that the user can not type + * a number whose absolute value is greater than the max. Otherwise, the value is unlimited if max + * is null/unspecified. See {@link #setMaxValue(BigInteger)}
  • + *
  • Show the number mode as hint text - If on either "Hex" or "Dec" is displayed lightly in the + * bottom right portion of the text field. See {@link #setShowNumberMode(boolean)}
  • *
* */ @@ -91,9 +93,9 @@ public class IntegerTextField { * Creates a new IntegerTextField with the specified number of columns and an initial value * * @param columns the number of columns to display in the JTextField. - * @param initialValue the initial value. This constructor takes an initialValue as a long. If - * you need a value that is bigger (or smaller) than can be specified as a long, then use - * the constructor that takes a BigInteger as an initial value. + * @param initialValue the initial value. This constructor takes an initialValue as a long. If + * you need a value that is bigger (or smaller) than can be specified as a long, then + * use the constructor that takes a BigInteger as an initial value. */ public IntegerTextField(int columns, long initialValue) { this(columns, BigInteger.valueOf(initialValue)); @@ -158,11 +160,13 @@ public class IntegerTextField { /** * Returns the current value as an int. * - *

If the field has no current value, 0 will be returned. If - * the value is bigger (or smaller) than an int, it will be cast to an int. + *

+ * If the field has no current value, 0 will be returned. If the value is bigger (or smaller) + * than an int, it will be cast to an int. * - *

If using this method, it is highly recommended that you set the max value to {@link Integer#MAX_VALUE} - * or lower. + *

+ * If using this method, it is highly recommended that you set the max value to + * {@link Integer#MAX_VALUE} or lower. * * @return the current value as an int. Or 0 if there is no value * @throws ArithmeticException if the value in this field will not fit into an int @@ -178,11 +182,13 @@ public class IntegerTextField { /** * Returns the current value as a long. * - *

If the field has no current value, 0 will be returned. If - * the value is bigger (or smaller) than an long, it will be cast to a long. + *

+ * If the field has no current value, 0 will be returned. If the value is bigger (or smaller) + * than an long, it will be cast to a long. * - *

If using this method, it is highly recommended that you set the max value to {@link Long#MAX_VALUE} - * or lower. + *

+ * If using this method, it is highly recommended that you set the max value to + * {@link Long#MAX_VALUE} or lower. * * @return the current value as a long. Or 0 if there is no value * @throws ArithmeticException if the value in this field will not fit into a long @@ -214,13 +220,13 @@ public class IntegerTextField { } /** - * Sets the field to the given text. The text must be a properly formated string that is - * a value that is valid for this field. If the field is set to not allow "0x" prefixes, then - * the input string cannot start with 0x and furthermore, if the field is in decimal mode, then - * input string cannot take in hex digits a-f. On the other hand, if "0x" prefixes are allowed, - * then the input string can be either a decimal number or a hex number depending on if the - * input string starts with "0x". In this case, the field's hex mode will be set to match - * the input text. If the text is not valid, the field will not change. + * Sets the field to the given text. The text must be a properly formated string that is a value + * that is valid for this field. If the field is set to not allow "0x" prefixes, then the input + * string cannot start with 0x and furthermore, if the field is in decimal mode, then input + * string cannot take in hex digits a-f. On the other hand, if "0x" prefixes are allowed, then + * the input string can be either a decimal number or a hex number depending on if the input + * string starts with "0x". In this case, the field's hex mode will be set to match the input + * text. If the text is not valid, the field will not change. * * @param text the value as text to set on this field * @return true if the set was successful @@ -232,7 +238,7 @@ public class IntegerTextField { } /** - * Sets the value of the field to the given value. A null value will clear the field. + * Sets the value of the field to the given value. A null value will clear the field. * * @param newValue the new value or null. */ @@ -258,8 +264,9 @@ public class IntegerTextField { /** * Sets the radix mode to Hex. * - *

If the field is currently in decimal mode, the current text will be - * change from displaying the current value from decimal to hex. + *

+ * If the field is currently in decimal mode, the current text will be change from displaying + * the current value from decimal to hex. */ public void setHexMode() { BigInteger currentValue = getValue(); @@ -270,8 +277,9 @@ public class IntegerTextField { /** * Sets the mode to Decimal. * - *

If the field is currently in hex mode, the current text will be - * change from displaying the current value from hex to decimal. + *

+ * If the field is currently in hex mode, the current text will be change from displaying the + * current value from hex to decimal. */ public void setDecimalMode() { BigInteger currentValue = getValue(); @@ -282,12 +290,12 @@ public class IntegerTextField { /** * Sets whether on not the field supports the 0x prefix. * - *

If 0x is supported, hex numbers - * will be displayed with the 0x prefix. Also, when typing, you must type 0x first to enter - * a hex number, otherwise it will only allow digits 0-9. If the 0x prefix option is turned - * off, then hex numbers are displayed without the 0x prefix and you can't change the decimal/hex - * mode by typing 0x. The field will either be in decimal or hex mode and the typed text - * will be interpreted appropriately for the mode. + *

+ * If 0x is supported, hex numbers will be displayed with the 0x prefix. Also, when typing, you + * must type 0x first to enter a hex number, otherwise it will only allow digits 0-9. If the 0x + * prefix option is turned off, then hex numbers are displayed without the 0x prefix and you + * can't change the decimal/hex mode by typing 0x. The field will either be in decimal or hex + * mode and the typed text will be interpreted appropriately for the mode. * * @param allowsHexPrefix true to use the 0x convention for hex. */ @@ -332,9 +340,10 @@ public class IntegerTextField { } /** - * Returns the current maximum allowed value. Null indicates that there is no maximum value. - * If negative values are permitted (see {@link #setAllowNegativeValues(boolean)}) this value - * will establish the upper and lower limit of the absolute value. + * Returns the current maximum allowed value. Null indicates that there is no maximum value. If + * negative values are permitted (see {@link #setAllowNegativeValues(boolean)}) this value will + * establish the upper and lower limit of the absolute value. + * * @return the current maximum value allowed. */ public BigInteger getMaxValue() { @@ -342,7 +351,7 @@ public class IntegerTextField { } /** - * Sets the maximum allowed value. The maximum must be a positive number. Null indicates that + * Sets the maximum allowed value. The maximum must be a positive number. Null indicates that * there is no maximum value. *

* If negative values are permitted (see {@link #setAllowNegativeValues(boolean)}) this value @@ -425,6 +434,15 @@ public class IntegerTextField { textField.selectAll(); } + /** + * Sets the horizontal alignment of the JTextField + * + * @param alignment the alignment as in {@link JTextField#setHorizontalAlignment(int)} + */ + public void setHorizontalAlignment(int alignment) { + textField.setHorizontalAlignment(alignment); + } + private String computeTextForValue(BigInteger value) { if (value == null) { return ""; @@ -688,7 +706,13 @@ public class IntegerTextField { Dimension size = getSize(); Insets insets = getInsets(); - int x = size.width - insets.right - hintWidth; + int x; + if (getHorizontalAlignment() == RIGHT) { + x = insets.left; + } + else { + x = size.width - insets.right - hintWidth; + } int y = size.height - insets.bottom - 1; String mode = isHexMode ? "Hex" : "Dec"; GraphicsUtils.drawString(this, g, mode, x, y);