GP-1943 - Structure Editor - added the 'Offset' column

This commit is contained in:
dragonmacher 2022-04-21 11:40:38 -04:00
parent 47f76c78d6
commit acf8a9e1bf
6 changed files with 187 additions and 145 deletions

View File

@ -74,6 +74,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
*
* @param dataType the new composite data type.
*/
@Override
public void load(Composite dataType) {
if (dataType == null) { // TODO: Why is this needed? Use case?
return;
@ -104,7 +105,8 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
// Listen so we can update editor if name changes for this structure.
originalCompositeId = DataTypeManager.NULL_DATATYPE_ID;
if (originalDTM.contains(dataType)) {
originalCompositeId = originalDTM.getID(dataType); // Get the id if editing an existing data type.
// Get the id if editing an existing data type.
originalCompositeId = originalDTM.getID(dataType);
}
originalDTM.addDataTypeManagerListener(this);
@ -117,7 +119,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
editorStateChanged(CompositeEditorModelListener.COMPOSITE_LOADED);
}
/**
* Create view composite with the appropriate datatype manager and
* changes listener(s) if required.
@ -393,7 +395,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
if (newDt == null) {
return; // Was nothing and is nothing.
}
if (DataTypeComponent.usesZeroLengthComponent(newDt)) {
newLength = 0;
}
@ -401,7 +403,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
checkIsAllowableDataType(newDt);
newDt = resolveDataType(newDt, viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
if (newLength < 0) {
// prefer previous size first
int suggestedLength = (previousLength <= 0) ? lastNumBytes : previousLength;
@ -410,7 +412,8 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
if (sizedDataType == null) {
return;
}
newDt = resolveDataType(sizedDataType.getDataType(), viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
newDt = resolveDataType(sizedDataType.getDataType(), viewDTM,
DataTypeConflictHandler.DEFAULT_HANDLER);
newLength = sizedDataType.getLength();
if (newLength <= 0) {
throw new UsrException("Can't currently add this data type.");
@ -430,9 +433,10 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
}
/**
* Resolves the data type against the indicated data type manager using the specified conflictHandler.
* Transactions should have already been initiated prior to calling this method.
* If not then override this method to perform the transaction code around the resolve.
* Resolves the data type against the indicated data type manager using the specified
* conflictHandler. Transactions should have already been initiated prior to calling this
* method. If not then override this method to perform the transaction code around the
* resolve.
*
* @param dt the data type to be resolved
* @param resolveDtm the data type manager to resolve the data type against

View File

@ -23,6 +23,7 @@ import java.awt.event.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.EventObject;
import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
@ -42,8 +43,7 @@ import docking.widgets.fieldpanel.support.FieldRange;
import docking.widgets.fieldpanel.support.FieldSelection;
import docking.widgets.label.GDLabel;
import docking.widgets.label.GLabel;
import docking.widgets.table.GTable;
import docking.widgets.table.GTableCellRenderer;
import docking.widgets.table.*;
import docking.widgets.textfield.GValidatedTextField;
import ghidra.app.services.DataTypeManagerService;
import ghidra.app.util.datatype.DataTypeSelectionEditor;
@ -555,6 +555,16 @@ public abstract class CompositeEditorPanel extends JPanel
private void createTable() {
table = new CompositeTable(model);
TableColumnModel columnModel = table.getColumnModel();
if (columnModel instanceof GTableColumnModel) {
GTableColumnModel gColumnModel = (GTableColumnModel) columnModel;
List<TableColumn> hiddenColumns = model.getHiddenColumns();
for (TableColumn column : hiddenColumns) {
gColumnModel.addHiddenColumn(column);
}
}
table.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
table.addMouseListener(new CompositeTableMouseListener());

View File

@ -16,11 +16,11 @@
package ghidra.app.plugin.core.compositeeditor;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.function.Consumer;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import docking.widgets.fieldpanel.support.FieldRange;
import docking.widgets.fieldpanel.support.FieldSelection;
@ -34,9 +34,10 @@ import utility.function.Callback;
abstract class CompositeViewerModel extends AbstractTableModel
implements DataTypeManagerChangeListener {
/** Flag indicating that the model is updating the selection and
* should ignore any attempts to set the selection until it is no
* longer updating. */
/**
* Flag indicating that the model is updating the selection and should ignore any attempts to
* set the selection until it is no longer updating.
*/
protected boolean updatingSelection = false;
protected Composite originalComposite;
@ -68,7 +69,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
/** Offset of each component field. */
protected int[] columnOffsets = new int[headers.length];
/** Width of each component field. */
protected int[] columnWidths = { 75, 75, 100, 100, 100, 150 }; // Initial default column widths.
protected int[] columnWidths = { 75, 75, 100, 100, 100, 150 }; // Initial default column widths
/** Total component area width. */
protected int width = 0;
/** Width of left margin in pixels for the component area. */
@ -88,10 +89,10 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns <code>String.class</code> regardless of <code>columnIndex</code>.
* Returns <code>String.class</code> regardless of <code>columnIndex</code>.
*
* @param columnIndex the column being queried
* @return the String.class
* @param columnIndex the column being queried
* @return the String.class
*/
@Override
public Class<?> getColumnClass(int columnIndex) {
@ -125,6 +126,11 @@ abstract class CompositeViewerModel extends AbstractTableModel
return COMMENT;
}
// subclasses may supply columns
protected List<TableColumn> getHiddenColumns() {
return Collections.emptyList();
}
/**
* Terminates listening for category change events within the model.
*/
@ -135,19 +141,18 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns whether or not the editor has a structure loaded.
* If no structure is loaded then only unload() or dispose() methods
* should be called.
* @return true if an editable structure is currently loaded in the model.
* Returns whether or not the editor has a structure loaded. If no structure is loaded then
* only unload() or dispose() methods should be called.
*
* @return true if an editable structure is currently loaded in the model.
*/
public boolean isLoaded() {
return (viewComposite != null);
}
/**
* Updates the model to now view the indicated data structure.
* This method should cleanup from a previous load if neccessary
* and must initilize the following model state:
* Updates the model to now view the indicated data structure. This method should cleanup from
* a previous load if necessary and must initialize the following model state:
* <ul>
* <li>originalComposite</li>
* <li>originalDataTypePath</li>
@ -188,8 +193,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Resolves the indicated data type against the working copy in the
* viewer's data type manager.
* Resolves the indicated data type against the working copy in the viewer's data type manager.
* @param dataType the data type
* @return the working copy of the data type.
*/
@ -328,8 +332,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Return the size of the structure being viewed in bytes as a hex or decimal string
* depending on the model's current display setting for numbers
* Return the size of the structure being viewed in bytes as a hex or decimal string depending
* on the model's current display setting for numbers
* @return the length
*/
public String getLengthAsString() {
@ -354,10 +358,10 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Return a header name for the indicated column.
* Return a header name for the indicated column.
*
* @param columnIndex the index number indicating the component field (column)
* to get the header for.
* @param columnIndex the index number indicating the component field (column) to get the
* header for.
*/
@Override
public String getColumnName(int columnIndex) {
@ -365,25 +369,36 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Return a header name for the indicated field (column)
* Return a header name for the indicated field (column)
*
* @param columnIndex the index number indicating the component field (column)
* to get the header for
* @param columnIndex the index number indicating the component field (column) to get the
* header for
* @return the name
*/
public String getFieldName(int columnIndex) {
if (columnIndex < 0 || columnIndex > getColumnCount()) {
if (columnIndex < 0) {
return "UNKNOWN";
}
return headers[columnIndex];
if (columnIndex < headers.length) {
return headers[columnIndex];
}
List<TableColumn> hiddenColumns = getHiddenColumns();
for (TableColumn c : hiddenColumns) {
int modelIndex = c.getModelIndex();
if (modelIndex == columnIndex) {
return Objects.toString(c.getHeaderValue());
}
}
return "UNKNOWN";
}
/**
* Returns whether or not a particular component row and field in this
* structure is an editable type of cell. However the cell still
* may not be editable currently. To check if the cell can actually be
* edited call isCellEditable().
* Returns whether or not a particular component row and field in this structure is an editable
* type of cell. However the cell still may not be editable currently. To check if the cell can
* actually be edited call isCellEditable().
*
* @param rowIndex the row index of the component
* @param columnIndex the index for the field of the component
@ -394,12 +409,10 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns whether or not a particular component row and field in this
* structure is editable
* Returns whether or not a particular component row and field in this structure is editable
*
* @param rowIndex index for the row (component within this structure).
* @param columnIndex index for the column (field of the component within
* this structure).
* @param columnIndex index for the column (field of the component within this structure).
*/
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
@ -407,7 +420,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Gets the display offset of the component field at the specified column index
* Gets the display offset of the component field at the specified column index.
*
* @param columnIndex the field index within the component.
* @return the offset in pixels of the component field.
@ -460,10 +473,10 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Gets the display width of the component field at the specified column index
* Gets the display width of the component field at the specified column index.
*
* @param columnIndex the field index within the component.
* @return the width of the component field.
* @param columnIndex the field index within the component
* @return the width of the component field
*/
public int getFieldWidth(int columnIndex) {
return ((columnIndex < 0 || columnIndex >= getColumnCount()) ? 0
@ -471,10 +484,9 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns the number of component rows in the viewer. There may be a
* blank row at the end for selecting. Therefore this number can be
* different than the actual number of components currently in the
* structure being viewed.
* Returns the number of component rows in the viewer. There may be a blank row at the end for
* selecting. Therefore this number can be different than the actual number of components
* currently in the structure being viewed.
*
* @return the number of rows in the model
*/
@ -492,11 +504,11 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Return the nth component for the structure being viewed. Since the number of rows
* can exceed the number of components defined within the composite
* ({@link Composite#getNumComponents()}) this method will return null for a blank
* row.
* @param rowIndex the index of the component to return. First component is index of 0.
* Return the nth component for the structure being viewed. Since the number of rows can exceed
* the number of components defined within the composite ({@link Composite#getNumComponents()})
* this method will return null for a blank row.
*
* @param rowIndex the index of the component to return. First component is index of 0
* @return the component
*/
public DataTypeComponent getComponent(int rowIndex) {
@ -507,10 +519,10 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns the number of columns (display fields) for each component in
* this structure or union.
* Returns the number of columns (display fields) for each component in this structure or
* union.
*
* @return the number of display fields for each component.
* @return the number of display fields for each component
*/
@Override
public int getColumnCount() {
@ -520,7 +532,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
/**
* Returns the number of display fields for this structure or union.
*
* @return the number of display fields for each component.
* @return the number of display fields for each component
*/
public int getNumFields() {
return getColumnCount();
@ -573,7 +585,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns the current dataType name (Structure or Union) as a string
* Returns the current dataType name (Structure or Union) as a string.
* @return the name
*/
protected String getTypeName() {
@ -581,7 +593,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns the current status string
* Returns the current status string.
* @return the status
*/
public String getStatus() {
@ -597,10 +609,9 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Sets the current status string and performs notification to all
* CompositeModelStatusListeners.
* Sets the current status string and performs notification to all listeners.
* @param status the status message
* @param beep true indicates an audible beep should sound when the message is displayed.
* @param beep true indicates an audible beep should sound when the message is displayed
*/
public void setStatus(String status, boolean beep) {
if (status == null) {
@ -623,9 +634,9 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Fixes up the original name and category because a program restoration may
* have changed the original composite.
* @param composite the restored copy of our original composite.
* Fixes up the original name and category because a program restoration may have changed the
* original composite.
* @param composite the restored copy of our original composite
*/
protected void fixupOriginalPath(Composite composite) {
String newName = composite.getName();
@ -659,8 +670,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Called whenever the composite's non-component information changes.
* For example, the name, or description change.
* Called whenever the composite's non-component information changes. For example, the name,
* or description change.
*/
protected void compositeInfoChanged() {
notify(modelListeners, CompositeViewerModelListener::compositeInfoChanged);
@ -674,8 +685,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Determines the full path name for the composite data type based on
* the original composite and original category.
* Determines the full path name for the composite data type based on the original composite
* and original category.
* @return the full path name
*/
public final DataTypePath getOriginalDataTypePath() {
@ -837,10 +848,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
fireTableDataChanged();
componentDataChanged();
}
catch (InvalidNameException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (DuplicateNameException e) {
catch (InvalidNameException | DuplicateNameException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
}
@ -947,22 +955,23 @@ abstract class CompositeViewerModel extends AbstractTableModel
@Override
public void favoritesChanged(DataTypeManager dtm, DataTypePath path, boolean isFavorite) {
// Don't care.
}
}
//=================================================================================================
// Helper methods for CategoryChangeListener methods.
//=================================================================================================
/*******************************************************************
* Helper methods for CategoryChangeListener methods.
********************************************************************/
/**
* Determines whether the indicated composite data type has any
* sub-components that are within the indicated category or one
* of its sub-categories.
* Determines whether the indicated composite data type has any sub-components that are within
* the indicated category or one of its sub-categories.
* @param parentDt the composite data type
* @param catPath the category's path.
* @return true if a sub-component is in the indicated category.
* @param catPath the category's path
* @return true if a sub-component is in the indicated category
*/
boolean hasSubDtInCategory(Composite parentDt, String catPath) {
DataTypeComponent components[] = parentDt.getDefinedComponents();
// FUTURE Add a structure to keep track of which composites were searched so they aren't searched multiple times.
// FUTURE Add a structure to keep track of which composites were searched so they aren't
// searched multiple times.
for (DataTypeComponent component : components) {
DataType subDt = component.getDataType();
String subCatPath = subDt.getCategoryPath().getPath();
@ -979,11 +988,11 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Determines whether the indicated composite data type has any
* sub-components that are the indicated data type.
* Determines whether the indicated composite data type has any sub-components that are the
* indicated data type.
* @param parentDt the composite data type
* @param dtPath the data type to be detected.
* @return true if the composite data type has the data type as a sub-component.
* @param dtPath the data type to be detected
* @return true if the composite data type has the data type as a sub-component
*/
protected boolean hasSubDt(Composite parentDt, DataTypePath dtPath) {
DataTypeComponent components[] = parentDt.getDefinedComponents();
@ -1032,6 +1041,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
* Returns the number of rows currently selected.
*
* <p>Note: In unlocked mode this can include the additional blank line.
*
* @return the selected row count
*/
public int getNumSelectedRows() {
@ -1048,6 +1058,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
* Returns the number of component rows currently selected.
*
* <p>Note: This only includes rows that are actually components.
*
* @return the selected row count
*/
public int getNumSelectedComponentRows() {
@ -1065,7 +1076,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns true if the component list selection is contiguous
* Returns true if the component list selection is contiguous.
* @return true if contiguous
*/
public boolean isContiguousSelection() {
@ -1073,7 +1084,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns true if the component list selection is a single component
* Returns true if the component list selection is a single component.
* @return true if the component list selection is a single component
*/
public boolean isSingleComponentRowSelection() {
@ -1086,7 +1097,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns true if the selection is a single row
* Returns true if the selection is a single row.
* @return true if the selection is a single row
*/
public boolean isSingleRowSelection() {
@ -1098,7 +1109,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns true if the list selection is contiguous and only contains component rows
* Returns true if the list selection is contiguous and only contains component rows.
* @return true if the list selection is contiguous and only contains component rows
*/
public boolean isContiguousComponentSelection() {
@ -1107,7 +1118,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Get an array of the indices for all the selected rows
* Get an array of the indices for all the selected rows.
* @return the selected rows
*/
public int[] getSelectedRows() {
@ -1123,7 +1134,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Get an array of the row indices for all the selected components
* Get an array of the row indices for all the selected components.
* @return the selected rows
*/
public int[] getSelectedComponentRows() {
@ -1140,8 +1151,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Returns the selection range containing the specified row index
* if there is one that contains it. Otherwise, returns null.
* Returns the selection range containing the specified row index if there is one that contains
* it. Otherwise, returns null.
*
* @param rowIndex the row index
* @return the range or null
@ -1164,7 +1175,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Gets the minimum row index that is selected or -1 if no index is selected
* Gets the minimum row index that is selected or -1 if no index is selected.
* @return the index
*/
public int getMinIndexSelected() {
@ -1176,7 +1187,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Saves the current selection in the structure components viewing area
* Saves the current selection in the structure components viewing area.
*
* @param rows the indices for the selected rows.
*/
@ -1202,8 +1213,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Sets the model's current selection to the indicated selection.
* If the selection is empty, it gets adjusted to the empty last line when in unlocked mode.
* Sets the model's current selection to the indicated selection. If the selection is empty,
* it gets adjusted to the empty last line when in unlocked mode.
* @param selection the new selection
*/
public void setSelection(FieldSelection selection) {
@ -1269,7 +1280,7 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Convenience method to run the given task on the swing thread now if swing or later if not
* Convenience method to run the given task on the swing thread now if swing or later if not.
* @param r the runnable
*/
protected void swing(Runnable r) {
@ -1277,8 +1288,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* A notify method to take the listens to notify, along with the method that should be
* called on each listener
* A notify method to take the listens to notify, along with the method that should be called
* on each listener.
*
* @param <T> the type of the listener
* @param listeners the listeners
@ -1293,8 +1304,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
}
/**
* Sets whether or not the editor displays numeric values in hexadecimal.
* @param showHex true means show in hexadecimal. false means show in decimal.
* Sets whether or not the editor displays numeric values in hexadecimal.
* @param showHex true means show in hexadecimal. false means show in decimal
*/
public void displayNumbersInHex(boolean showHex) {
if (this.showHexNumbers != showHex) {

View File

@ -16,14 +16,16 @@
package ghidra.app.plugin.core.compositeeditor;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.*;
import javax.swing.table.TableColumn;
import docking.widgets.OptionDialog;
import docking.widgets.dialogs.InputDialog;
import docking.widgets.dialogs.InputDialogListener;
import docking.widgets.fieldpanel.support.FieldRange;
import docking.widgets.fieldpanel.support.FieldSelection;
import docking.widgets.table.GTableHeaderRenderer;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.InsufficientBytesException;
import ghidra.util.Msg;
@ -39,6 +41,9 @@ class StructureEditorModel extends CompEditorModel {
private static final int DATATYPE = 3;
private static final int FIELDNAME = 4;
private static final int COMMENT = 5;
private static final int ORDINAL = 6;
private List<TableColumn> hiddenColumns;
StructureEditorModel(StructureEditorProvider provider, boolean showHexNumbers) {
super(provider);
@ -47,6 +52,18 @@ class StructureEditorModel extends CompEditorModel {
columnOffsets = new int[headers.length];
adjustOffsets();
this.showHexNumbers = showHexNumbers;
List<TableColumn> additionalColumns = new ArrayList<>();
TableColumn ordinalColumn = new TableColumn(ORDINAL, 75);
ordinalColumn.setHeaderRenderer(new GTableHeaderRenderer());
ordinalColumn.setHeaderValue("Ordinal");
additionalColumns.add(ordinalColumn);
hiddenColumns = Collections.unmodifiableList(additionalColumns);
}
@Override
protected List<TableColumn> getHiddenColumns() {
return hiddenColumns;
}
@Override
@ -110,11 +127,7 @@ class StructureEditorModel extends CompEditorModel {
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if ((viewComposite == null) || (rowIndex < 0) || (columnIndex < 0) ||
(columnIndex >= getColumnCount())) {
if (columnIndex == getDataTypeColumn()) {
return null;
}
if ((viewComposite == null) || (rowIndex < 0) || (columnIndex < 0)) {
return "";
}
@ -155,6 +168,10 @@ class StructureEditorModel extends CompEditorModel {
else if (columnIndex == getCommentColumn()) {
value = dtc.getComment();
}
else if (columnIndex == ORDINAL) {
int ordinal = dtc.getOrdinal();
value = showHexNumbers ? getHexString(ordinal, true) : Integer.toString(ordinal);
}
return (value == null) ? "" : value;
}
@ -671,7 +688,6 @@ class StructureEditorModel extends CompEditorModel {
1 == currentRange.getEnd().getIndex().intValue());
if (isOneComponent) {
// TODO
if (!isShowingUndefinedBytes() || isAtEnd(currentIndex) ||
onlyUndefinedsUntilEnd(currentIndex + 1)) {
return true; // allow replace of component when aligning.

View File

@ -116,7 +116,6 @@ public class GTable extends JTable {
* Constructs a new GTable
*/
public GTable() {
super();
init();
}
@ -721,9 +720,6 @@ public class GTable extends JTable {
}
}
/**
* @see javax.swing.JComponent#getToolTipText(java.awt.event.MouseEvent)
*/
@Override
public String getToolTipText(MouseEvent e) {
String str = super.getToolTipText(e);
@ -873,10 +869,10 @@ public class GTable extends JTable {
}
/**
* Performs custom work to locate renderers for special table model types. This method
* allows clients to bypass the {@link #getCellRenderer(int, int)}, which is sometimes
* overridden by subclasses to return a hard-coded renderer. In that case, some clients
* still want a way to perform normal cell renderer lookup.
* Performs custom work to locate renderers for special table model types. This method allows
* clients to bypass the {@link #getCellRenderer(int, int)}, which is sometimes overridden by
* subclasses to return a hard-coded renderer. In that case, some clients still want a way to
* perform normal cell renderer lookup.
*
* @param row the row
* @param col the column
@ -895,11 +891,9 @@ public class GTable extends JTable {
}
/**
* If you just begin typing into an editable cell in
* a JTable, then the cell editor will be displayed. However,
* the editor component will not have a focus. This
* method has been overridden to request
* focus on the editor component.
* If you just begin typing into an editable cell in a JTable, then the cell editor will be
* displayed. However, the editor component will not have a focus. This method has been
* overridden to request focus on the editor component.
*
* @see javax.swing.JTable#editCellAt(int, int)
*/
@ -1057,18 +1051,16 @@ public class GTable extends JTable {
}
/**
* Maintain a {@link docking.widgets.table.GTableCellRenderingData} object
* associated with each column that maintains some state and references to
* useful data. These objects are created as needed, stored by the table for
* convenient re-use and to prevent per-cell creation, and cleared when columns
* are removed from the table.
* Maintain a {@link docking.widgets.table.GTableCellRenderingData} object associated with each
* column that maintains some state and references to useful data. These objects are created as
* needed, stored by the table for convenient re-use and to prevent per-cell creation, and
* cleared when columns are removed from the table.
* <p>
* Row and cell state is cleared before returning to the caller to ensure
* consistent state; when the client is done rendering a cell, row and cell
* state should also be cleared to minimize references.
* Row and cell state is cleared before returning to the caller to ensure consistent state;
* when the client is done rendering a cell, row and cell state should also be cleared to
* minimize references.
*
* @param viewColumn
* The columns' view index
* @param viewColumn the columns' view index
* @return Data specific to the column. Row state is cleared before returning.
*/
GTableCellRenderingData getRenderingData(int viewColumn) {

View File

@ -151,10 +151,7 @@ public class GTableColumnModel
@Override
public void addColumn(TableColumn aColumn) {
if (aColumn == null) {
throw new IllegalArgumentException("Object is null");
}
Objects.requireNonNull(aColumn);
removeColumnWithModelIndex(aColumn.getModelIndex()); // dedup
completeList.add(aColumn);
@ -169,6 +166,18 @@ public class GTableColumnModel
columnModelState.restoreState();
}
/**
* Adds a table column to this model that is not visible default. This column may be made
* visible later by the user or by the system restoring a previously used visible column state.
* @param aColumn the column
*/
public void addHiddenColumn(TableColumn aColumn) {
Objects.requireNonNull(aColumn);
removeColumnWithModelIndex(aColumn.getModelIndex()); // dedup
completeList.add(aColumn);
aColumn.addPropertyChangeListener(this);
}
/** Finds the table's column with the given model index */
private TableColumn getColumnFromModelIndex(int modelIndex) {
for (TableColumn tableColumn : completeList) {