iter = components.keySet().iterator();
-
- while (iter.hasNext()) {
-
- Component c = iter.next();
- TableColumn col = components.get(c);
- int width = c.getPreferredSize().width;
- int index = columnModel.getColumnIndex(col.getIdentifier());
-
- if (index == 0) {
- width += separatorWidth / 2;
- }
- else if (index == components.size() - 1) {
- width += separatorWidth / 2;
- }
- else {
- width += separatorWidth;
- }
- col.setMinWidth(width);
- col.setMaxWidth(width);
- col.setPreferredWidth(width);
- }
-
- }
-
-}
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerIndexedView.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerIndexedView.java
new file mode 100644
index 0000000000..e6617e38d9
--- /dev/null
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerIndexedView.java
@@ -0,0 +1,226 @@
+/* ###
+ * 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 ghidra.app.plugin.core.byteviewer;
+
+import java.awt.BorderLayout;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.*;
+
+import docking.widgets.fieldpanel.FieldPanel;
+import docking.widgets.fieldpanel.Layout;
+import docking.widgets.indexedscrollpane.*;
+import generic.theme.GColor;
+import generic.theme.Gui;
+import ghidra.app.plugin.core.format.DataFormatModel;
+
+/**
+ * Main ByteViewer component that is scrolled in a {@link IndexedScrollPane}. Similar to the view
+ * component in a {@link JScrollPane}. This component manages two or more {@link FieldPanel}
+ * components. It always contains the "index" field panel which displays the addresses of the
+ * values being displayed. Then it has one or more data FieldPanels; one for each format being
+ * displayed (e.g., hex, octal, binary).
+ *
+ * There is also header component that displays the name of each column and allows the user to
+ * reorder and resize the views. This class uses an {@link InteractivePanelManager} to handle
+ * the reordering and resizing of the views in coordination with the header component. It is the
+ * client's responsibility to get the header component and install it into the IndexedScrollPane.
+ */
+class ByteViewerIndexedView extends JPanel implements IndexedScrollable, IndexScrollListener {
+ private static final String HEADER_FONT_ID = "font.byteviewer.header";
+ private FieldPanel indexPanel;
+ private List allPanels = new ArrayList<>();
+ private boolean processingIndexRangeChanged;
+ private InteractivePanelManager panelManager;
+
+ ByteViewerIndexedView(FieldPanel indexPanel) {
+ super(new BorderLayout());
+ this.indexPanel = indexPanel;
+ allPanels.add(indexPanel);
+ panelManager = new InteractivePanelManager();
+ panelManager.setHeaderFont(Gui.getFont(HEADER_FONT_ID));
+
+ indexPanel.addIndexScrollListener(this);
+
+ panelManager.addComponent(ByteViewerComponentProvider.INDEX_COLUMN_NAME, indexPanel);
+ JComponent mainPanel = panelManager.getMainPanel();
+ add(mainPanel, BorderLayout.CENTER);
+ mainPanel.setBackground(new GColor("color.bg.byteviewer"));
+
+ addMouseWheelListener(e -> {
+ // this lets us scroll the byte viewer when the user is not over any panel, but still
+ // over the view
+ Layout firstLayout = indexPanel.getLayoutModel().getLayout(BigInteger.ZERO);
+ int layoutScrollHt = firstLayout != null //
+ ? firstLayout.getScrollableUnitIncrement(0, 1)
+ : 0;
+
+ double wheelRotation = e.getPreciseWheelRotation();
+ int scrollAmount =
+ (int) (wheelRotation * layoutScrollHt * FieldPanel.MOUSEWHEEL_LINES_TO_SCROLL);
+
+ indexPanel.scrollView(scrollAmount);
+ e.consume();
+ });
+ }
+
+ void addView(String viewName, ByteViewerComponent c) {
+ panelManager.addComponent(viewName, c);
+ allPanels.add(c);
+ c.addIndexScrollListener(this);
+ }
+
+ void removeView(ByteViewerComponent c) {
+ panelManager.removeComponent(c);
+ allPanels.remove(c);
+ c.removeIndexScrollListener(this);
+ }
+
+ JComponent getColumnHeader() {
+ return panelManager.getColumnHeader();
+ }
+
+ public List getViewNamesInDisplayOrder() {
+ List viewNames = new ArrayList<>();
+ List components = panelManager.getComponents();
+ for (JComponent component : components) {
+ if (component == indexPanel) {
+ continue;
+ }
+ if (component instanceof ByteViewerComponent byteViewerComponent) {
+ DataFormatModel model = byteViewerComponent.getDataModel();
+ viewNames.add(model.getName());
+ }
+ }
+ return viewNames;
+ }
+
+ void resetViewWidthToDefaults() {
+ List viewNames = getViewNamesInDisplayOrder();
+ for (String viewName : viewNames) {
+ panelManager.resetColumnWidthToPreferredWidth(viewName);
+ }
+ }
+
+ void setIndexName(String indexName) {
+ panelManager.setName(indexPanel, indexName);
+ }
+
+ int getViewWidth(String viewName) {
+ return panelManager.getColumnWidth(viewName);
+ }
+
+ void setColumnWidth(String viewName, int width) {
+ panelManager.setColumnWidth(viewName, width);
+ }
+
+ @Override
+ public void indexRangeChanged(BigInteger startIndex, BigInteger endIndex, int yStart,
+ int yEnd) {
+ if (processingIndexRangeChanged) {
+ return;
+ }
+ processingIndexRangeChanged = true;
+ try {
+ // need to sync up the view position of all views when any view is scrolled
+ for (FieldPanel fieldPanel : allPanels) {
+ fieldPanel.showIndex(startIndex, yStart);
+ }
+ }
+ finally {
+ processingIndexRangeChanged = false;
+ }
+
+ }
+
+ @Override
+ public void addIndexScrollListener(IndexScrollListener listener) {
+ indexPanel.addIndexScrollListener(listener);
+ }
+
+ @Override
+ public int getHeight(BigInteger index) {
+ return indexPanel.getHeight(index);
+ }
+
+ @Override
+ public BigInteger getIndexAfter(BigInteger index) {
+ return indexPanel.getIndexAfter(index);
+ }
+
+ @Override
+ public BigInteger getIndexBefore(BigInteger index) {
+ return indexPanel.getIndexBefore(index);
+ }
+
+ @Override
+ public BigInteger getIndexCount() {
+ return indexPanel.getIndexCount();
+ }
+
+ @Override
+ public boolean isUniformIndex() {
+ return true;
+ }
+
+ @Override
+ public void removeIndexScrollListener(IndexScrollListener listener) {
+ indexPanel.removeIndexScrollListener(listener);
+ }
+
+ @Override
+ public void scrollLineDown() {
+ indexPanel.scrollLineDown();
+ }
+
+ @Override
+ public void scrollLineUp() {
+ indexPanel.scrollLineUp();
+ }
+
+ @Override
+ public void scrollPageDown() {
+ indexPanel.scrollPageDown();
+ }
+
+ @Override
+ public void scrollPageUp() {
+ indexPanel.scrollPageUp();
+ }
+
+ @Override
+ public void showIndex(BigInteger index, int verticalOffset) {
+ indexPanel.showIndex(index, verticalOffset);
+ }
+
+ @Override
+ public void indexModelChanged() {
+ // handled by indexPanel
+ }
+
+ @Override
+ public void indexModelDataChanged(BigInteger start, BigInteger end) {
+ // handled by indexPanel
+ }
+
+ @Override
+ public void mouseWheelMoved(double preciseWheelRotation, boolean isHorizontal) {
+ indexPanel.mouseWheelMoved(preciseWheelRotation, isHorizontal);
+ }
+
+}
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java
index e968ce2fd6..0d14d964e4 100644
--- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java
@@ -21,17 +21,15 @@ import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
-import javax.swing.event.*;
import docking.widgets.fieldpanel.*;
import docking.widgets.fieldpanel.field.EmptyTextField;
import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.listener.*;
import docking.widgets.fieldpanel.support.*;
-import docking.widgets.indexedscrollpane.*;
+import docking.widgets.indexedscrollpane.IndexedScrollPane;
import docking.widgets.label.GDLabel;
import docking.widgets.label.GLabel;
-import generic.theme.GColor;
import generic.theme.Gui;
import ghidra.app.plugin.core.format.*;
import ghidra.app.util.viewer.listingpanel.AddressSetDisplayListener;
@@ -40,7 +38,6 @@ import ghidra.program.model.address.AddressSetView;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.exception.InvalidInputException;
-import ghidra.util.layout.HorizontalLayout;
import ghidra.util.layout.PairLayout;
import help.Help;
import help.HelpService;
@@ -49,10 +46,8 @@ import help.HelpService;
* Top level component that has a scrolled pane for the panel of components that show the
* view for each format.
*/
-public class ByteViewerPanel extends JPanel
- implements TableColumnModelListener, LayoutModel, LayoutListener {
+public class ByteViewerPanel extends JPanel implements LayoutModel, LayoutListener {
private static final String FONT_STATUS_ID = "font.byteviewer.status";
-// private ByteViewerPlugin plugin;
private List viewList; // list of field viewers
private FieldPanel indexPanel; // panel for showing indexes
private IndexFieldFactory indexFactory;
@@ -61,12 +56,9 @@ public class ByteViewerPanel extends JPanel
private JLabel offsetField;
private JLabel insertionField;
private JPanel statusPanel;
- private CompositePanel compPanel;
private int fontHeight;
- private FontMetrics fm;
+ private FontMetrics fontMetrics;
private int bytesPerLine;
- private IndexedScrollPane scrollp;
- private ByteViewerHeader columnHeader;
private ByteBlockSet blockSet;
private ByteBlock[] blocks;
private IndexMap indexMap; // maps indexes to the correct block and offset
@@ -78,12 +70,12 @@ public class ByteViewerPanel extends JPanel
private Color highlightColor;
private int highlightButton;
private List layoutListeners = new ArrayList<>(1);
- private int indexPanelWidth;
private boolean addingView; // don't respond to cursor location
// changes while this flag is true
private final ByteViewerComponentProvider provider;
private List displayListeners = new ArrayList<>();
+ private ByteViewerIndexedView indexedView;
protected ByteViewerPanel(ByteViewerComponentProvider provider) {
super();
@@ -136,45 +128,6 @@ public class ByteViewerPanel extends JPanel
super.paintComponent(g);
}
- // TableColumnModelListener interface methods
- @Override
- public void columnAdded(TableColumnModelEvent e) {
- // no-op
- }
-
- @Override
- public void columnMarginChanged(ChangeEvent e) {
- // no-op
- }
-
- /**
- * Interface method called when the columns move.
- */
- @Override
- public void columnMoved(TableColumnModelEvent e) {
-
- int fromIndex = e.getFromIndex();
- int toIndex = e.getToIndex();
- if (fromIndex == toIndex) {
- return;
- }
- compPanel.swapView(fromIndex, toIndex);
-
- invalidate();
- validate();
- repaint();
- }
-
- @Override
- public void columnRemoved(TableColumnModelEvent e) {
- // no-op
- }
-
- @Override
- public void columnSelectionChanged(ListSelectionEvent e) {
- // no-op
- }
-
//////////////////////////////////////////////////////////////////////////
// ** package-level methods **
//////////////////////////////////////////////////////////////////////////
@@ -252,17 +205,14 @@ public class ByteViewerPanel extends JPanel
endField.setText(lastBlock
.getLocationRepresentation(lastBlock.getLength().subtract(BigInteger.ONE)));
- indexPanelWidth = getIndexPanelWidth(blocks);
- int center = indexPanelWidth / 2;
- int startx = center - getMaxIndexSize() / 2;
- indexFactory.setStartX(startx);
clearSelection();
}
}
if (indexMap == null) {
indexMap = new IndexMap();
}
- indexFactory.setIndexMap(indexMap, indexPanelWidth);
+ indexFactory.setIndexMap(indexMap);
+ indexFactory.setSize(getIndexSizeInChars());
// Do the following loop twice - once with update off and then with update on.
// need to do this because all the byte view components must have their models
@@ -278,7 +228,7 @@ public class ByteViewerPanel extends JPanel
c.setIndexMap(indexMap);
}
if (blocks != null && blocks.length > 0) {
- columnHeader.setColumnName(indexPanel, blocks[0].getIndexName());
+ indexedView.setIndexName(blocks[0].getIndexName());
}
indexPanel.dataChanged(BigInteger.ZERO, indexMap.getNumIndexes());
indexSetChanged();
@@ -366,7 +316,8 @@ public class ByteViewerPanel extends JPanel
}
protected ByteViewerComponent newByteViewerComponent(DataFormatModel model) {
- return new ByteViewerComponent(this, new ByteViewerLayoutModel(), model, bytesPerLine, fm);
+ return new ByteViewerComponent(this, new ByteViewerLayoutModel(), model, bytesPerLine,
+ fontMetrics);
}
/**
@@ -399,10 +350,7 @@ public class ByteViewerPanel extends JPanel
c.setHighlightButton(highlightButton);
viewList.add(c);
c.setSize(c.getPreferredSize());
- compPanel.addByteViewerComponent(c);
- // tell column header it needs to grow
- columnHeader.addColumn(viewName, c);
-
+ indexedView.addView(viewName, c);
c.addListeners();
if (viewList.size() == 1) {
@@ -441,8 +389,7 @@ public class ByteViewerPanel extends JPanel
void removeView(ByteViewerComponent comp) {
viewList.remove(comp);
- compPanel.removeByteViewerComponent(comp);
- columnHeader.removeColumn(comp);
+ indexedView.removeView(comp);
if (currentView == comp) {
currentView = null;
@@ -485,10 +432,6 @@ public class ByteViewerPanel extends JPanel
ByteViewerComponent c = viewList.get(i);
c.refreshView();
}
-// PluginEvent lastSelectionEvent = plugin.getLastSelectionEvent();
-// if (lastSelectionEvent != null) {
-// plugin.firePluginEvent(lastSelectionEvent);
-// }
}
int getNumberOfViews() {
@@ -509,9 +452,11 @@ public class ByteViewerPanel extends JPanel
this.bytesPerLine = bytesPerLine;
updateIndexMap();
}
+ // reset view column widths to preferred width for new bytesPerline
+ indexedView.resetViewWidthToDefaults();
+
// force everything to get validated, or else the
// header columns do not get repainted properly...
-
invalidate();
validate();
repaint();
@@ -615,36 +560,11 @@ public class ByteViewerPanel extends JPanel
}
FontMetrics getCurrentFontMetrics() {
- return fm;
+ return fontMetrics;
}
- /**
- * Return array of names of views in the order that they appear in the panel. The name array
- * includes an entry for the index panel.
- * @return a DataModelInfo object that describes the current views
- */
- DataModelInfo getDataModelInfo() {
-
- DataModelInfo info = new DataModelInfo(viewList.size());
- Component[] c = compPanel.getComponents();
- int index = 0;
- for (Component element : c) {
- if (element instanceof JSeparator) {
- continue;
- }
- if (element == indexPanel) {
- // don't put the index panel into the data model info, as it is not configurable
- continue;
- }
- else if (element instanceof ByteViewerComponent) {
- DataFormatModel model = ((ByteViewerComponent) element).getDataModel();
- String name = model.getName();
- int groupSize = model.getGroupSize();
- info.set(index, name, groupSize);
- ++index;
- }
- }
- return info;
+ List getViewNamesInDisplayOrder() {
+ return indexedView.getViewNamesInDisplayOrder();
}
/**
@@ -679,11 +599,11 @@ public class ByteViewerPanel extends JPanel
/**
* Restore the configuration of the plugin.
*
- * @param fontMetrics font metrics
+ * @param metrics font metrics
* @param newEditColor color for showing edits
*/
- void restoreConfigState(FontMetrics fontMetrics, Color newEditColor) {
- setFontMetrics(fontMetrics);
+ void restoreConfigState(FontMetrics metrics, Color newEditColor) {
+ setFontMetrics(metrics);
setEditColor(newEditColor);
}
@@ -704,21 +624,13 @@ public class ByteViewerPanel extends JPanel
}
void setFontMetrics(FontMetrics fm) {
- this.fm = fm;
+ this.fontMetrics = fm;
for (int i = 0; i < viewList.size(); i++) {
ByteViewerComponent c = viewList.get(i);
c.setFontMetrics(fm);
}
indexFactory = new IndexFieldFactory(fm);
-
- int charWidth = fm.charWidth('W');
- indexFactory.setStartX(charWidth);
- indexPanelWidth =
- ByteViewerComponentProvider.DEFAULT_NUMBER_OF_CHARS * charWidth + (2 * charWidth);
- if (blocks != null) {
- indexPanelWidth = getIndexPanelWidth(blocks);
- }
- indexFactory.setIndexMap(indexMap, indexPanelWidth);
+ indexFactory.setSize(getIndexSizeInChars());
indexPanel.modelSizeChanged(IndexMapper.IDENTITY_MAPPER);
}
@@ -731,7 +643,7 @@ public class ByteViewerPanel extends JPanel
}
protected FontMetrics getFontMetrics() {
- return fm;
+ return fontMetrics;
}
protected int getBytesPerLine() {
@@ -745,13 +657,11 @@ public class ByteViewerPanel extends JPanel
setLayout(new BorderLayout(10, 0));
- columnHeader = new ByteViewerHeader(this);
-
- fm = getFontMetrics(Gui.getFont(ByteViewerComponentProvider.DEFAULT_FONT_ID));
- fontHeight = fm.getHeight();
+ fontMetrics = getFontMetrics(Gui.getFont(ByteViewerComponentProvider.DEFAULT_FONT_ID));
+ fontHeight = fontMetrics.getHeight();
// for the index/address column
- indexFactory = new IndexFieldFactory(fm);
+ indexFactory = new IndexFieldFactory(fontMetrics);
indexPanel = new FieldPanel(this, "Byte Viewer");
indexPanel.enableSelection(false);
@@ -759,21 +669,13 @@ public class ByteViewerPanel extends JPanel
indexPanel.setFocusable(false);
indexPanel.addLayoutListener(this);
- compPanel = new CompositePanel(indexPanel);
-
- scrollp = new IndexedScrollPane(compPanel);
- scrollp.setWheelScrollingEnabled(false);
-
- columnHeader = new ByteViewerHeader(this);
- columnHeader.addColumnModelListener(this);
-
- columnHeader.addColumn(ByteViewerComponentProvider.DEFAULT_INDEX_NAME, indexPanel);
- scrollp.setColumnHeaderComp(columnHeader);
-
- compPanel.setBackground(new GColor("color.bg.byteviewer"));
+ indexedView = new ByteViewerIndexedView(indexPanel);
+ IndexedScrollPane indexedScrollPane = new IndexedScrollPane(indexedView);
+ indexedScrollPane.setWheelScrollingEnabled(false);
+ indexedScrollPane.setColumnHeaderComp(indexedView.getColumnHeader());
statusPanel = createStatusPanel();
- add(scrollp, BorderLayout.CENTER);
+ add(indexedScrollPane, BorderLayout.CENTER);
add(statusPanel, BorderLayout.SOUTH);
HelpService help = Help.getHelpService();
@@ -852,8 +754,7 @@ public class ByteViewerPanel extends JPanel
}
indexMap = new IndexMap(blockSet, bytesPerLine, blockOffset);
- indexPanelWidth = getIndexPanelWidth(blocks);
- indexFactory.setIndexMap(indexMap, indexPanelWidth);
+ indexFactory.setIndexMap(indexMap);
ByteBlock block = null;
BigInteger offset = BigInteger.ZERO;
if (info != null) {
@@ -887,7 +788,7 @@ public class ByteViewerPanel extends JPanel
@Override
public Dimension getPreferredViewSize() {
- return new Dimension(indexPanelWidth, 500);
+ return new Dimension(500, 500);
}
@Override
@@ -926,26 +827,16 @@ public class ByteViewerPanel extends JPanel
}
}
- private int getIndexPanelWidth(ByteBlock[] blocks1) {
- FontMetrics headerFm = columnHeader.getFontMetrics(columnHeader.getFont());
- String indexName = ByteViewerComponentProvider.DEFAULT_INDEX_NAME;
- if (blocks1.length > 0) {
- indexName = blocks1[0].getIndexName();
+ private int getIndexSizeInChars() {
+ // set the field size at least the size of the column header name
+ int minChars = ByteViewerComponentProvider.INDEX_COLUMN_NAME.length();
+ if (blocks != null) {
+ for (ByteBlock element : blocks) {
+ int charCount = element.getMaxLocationRepresentationSize();
+ minChars = Math.max(minChars, charCount);
+ }
}
- int nameWidth = headerFm.stringWidth(indexName);
- int charWidth = fm.charWidth('W');
- return Math.max(nameWidth, getMaxIndexSize() + 2 * charWidth);
- }
-
- private int getMaxIndexSize() {
- int maxWidth = 0;
- int charWidth = fm.charWidth('W');
- for (ByteBlock element : blocks) {
- int width = element.getMaxLocationRepresentationSize() * charWidth;
- maxWidth = Math.max(maxWidth, width);
- }
-
- return maxWidth;
+ return minChars;
}
@Override
@@ -1024,175 +915,12 @@ public class ByteViewerPanel extends JPanel
public void removeDisplayListener(AddressSetDisplayListener listener) {
displayListeners.add(listener);
}
-}
-
-class CompositePanel extends JPanel implements IndexedScrollable, IndexScrollListener {
- FieldPanel indexPanel;
- BoundedRangeModel verticalScrollBarModel;
- BoundedRangeModel horizontalScrollBarModel;
- List viewList = new ArrayList<>();
- List allPanels = new ArrayList<>();
- private boolean processingIndexRangeChanged;
-
- CompositePanel(FieldPanel indexPanel) {
- super(new HorizontalLayout(0));
- this.indexPanel = indexPanel;
- indexPanel.addIndexScrollListener(this);
- addMouseWheelListener(e -> {
- // this lets us scroll the byte viewer when the user is not over any panel, but still over the view
- Layout firstLayout = indexPanel.getLayoutModel().getLayout(BigInteger.ZERO);
- int layoutScrollHt = firstLayout != null //
- ? firstLayout.getScrollableUnitIncrement(0, 1)
- : 0;
-
- double wheelRotation = e.getPreciseWheelRotation();
- int scrollAmount =
- (int) (wheelRotation * layoutScrollHt * FieldPanel.MOUSEWHEEL_LINES_TO_SCROLL);
-
- indexPanel.scrollView(scrollAmount);
- e.consume();
- });
-
- allPanels.add(indexPanel);
- rebuildPanels();
- }
-
- public void swapView(int fromIndex, int toIndex) {
- FieldPanel from = allPanels.get(fromIndex);
- FieldPanel to = allPanels.get(toIndex);
- allPanels.set(fromIndex, to);
- allPanels.set(toIndex, from);
- rebuildPanels();
- }
-
- void addByteViewerComponent(ByteViewerComponent comp) {
- comp.addIndexScrollListener(this);
- viewList.add(comp);
- allPanels.add(comp);
- rebuildPanels();
- }
-
- void removeByteViewerComponent(ByteViewerComponent comp) {
- comp.removeIndexScrollListener(this);
- viewList.remove(comp);
- allPanels.remove(comp);
- rebuildPanels();
- }
-
- private void rebuildPanels() {
- removeAll();
- int count = 0;
- for (FieldPanel panel : allPanels) {
- if (count++ != 0) {
- super.add(new JSeparator(SwingConstants.VERTICAL));
- }
- super.add(panel);
- }
-// setSize(getPreferredSize());
- invalidate();
- }
-
- @Override
- public Component add(Component comp) {
- throw new UnsupportedOperationException("External call to add(Component) not allowed");
- }
-
- @Override
- public void remove(Component comp) {
- throw new UnsupportedOperationException("External call to remove(Component) not allowed");
- }
-
- @Override
- public void addIndexScrollListener(IndexScrollListener listener) {
- indexPanel.addIndexScrollListener(listener);
- }
-
- @Override
- public int getHeight(BigInteger index) {
- return indexPanel.getHeight(index);
- }
-
- @Override
- public BigInteger getIndexAfter(BigInteger index) {
- return indexPanel.getIndexAfter(index);
- }
-
- @Override
- public BigInteger getIndexBefore(BigInteger index) {
- return indexPanel.getIndexBefore(index);
- }
-
- @Override
- public BigInteger getIndexCount() {
- return indexPanel.getIndexCount();
- }
-
- @Override
- public boolean isUniformIndex() {
- return true;
- }
-
- @Override
- public void removeIndexScrollListener(IndexScrollListener listener) {
- indexPanel.removeIndexScrollListener(listener);
- }
-
- @Override
- public void scrollLineDown() {
- indexPanel.scrollLineDown();
- }
-
- @Override
- public void scrollLineUp() {
- indexPanel.scrollLineUp();
- }
-
- @Override
- public void scrollPageDown() {
- indexPanel.scrollPageDown();
- }
-
- @Override
- public void scrollPageUp() {
- indexPanel.scrollPageUp();
- }
-
- @Override
- public void showIndex(BigInteger index, int verticalOffset) {
- indexPanel.showIndex(index, verticalOffset);
- }
-
- @Override
- public void indexModelChanged() {
- // handled by indexPanel
- }
-
- @Override
- public void indexModelDataChanged(BigInteger start, BigInteger end) {
- // handled by indexPanel
- }
-
- @Override
- public void mouseWheelMoved(double preciseWheelRotation, boolean isHorizontal) {
- indexPanel.mouseWheelMoved(preciseWheelRotation, isHorizontal);
- }
-
- @Override
- public void indexRangeChanged(BigInteger startIndex, BigInteger endIndex, int yStart,
- int yEnd) {
- if (processingIndexRangeChanged) {
- return;
- }
- processingIndexRangeChanged = true;
- try {
- // need to update all views
- for (FieldPanel fieldPanel : allPanels) {
- fieldPanel.showIndex(startIndex, yStart);
- }
- }
- finally {
- processingIndexRangeChanged = false;
- }
- }
-
+
+ public int getViewWidth(String viewName) {
+ return indexedView.getViewWidth(viewName);
+ }
+
+ public void setViewWidth(String viewName, int width) {
+ indexedView.setColumnWidth(viewName, width);
+ }
}
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/DataModelInfo.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/DataModelInfo.java
deleted file mode 100644
index 04dbb19b46..0000000000
--- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/DataModelInfo.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/* ###
- * 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.
- * 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 ghidra.app.plugin.core.byteviewer;
-
-import java.io.Serializable;
-
-/**
- * Class used only during serialization to keep the model name and the
- * group size of the model.
- */
-class DataModelInfo implements Serializable {
-
- private String[] names;
- private int[] groupSizes;
-
- /**
- * Constructor
- * @param id name of the model
- * @param groupSize group size for the model
- */
- DataModelInfo(int size) {
- names = new String[size];
- groupSizes = new int[size];
- }
-
- void set(int index, String name, int groupSize) {
- names[index] = name;
- groupSizes[index] = groupSize;
- }
-
- /**
- * Get the name of the model.
- *
- * @return String
- */
- String[] getNames() {
- return names;
- }
-}
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java
index 2889ff4180..5f4ac0b0ca 100644
--- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java
@@ -19,10 +19,12 @@ import java.awt.Color;
import java.awt.FontMetrics;
import java.math.BigInteger;
+import org.apache.commons.lang3.StringUtils;
+
import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.field.SimpleTextField;
-import docking.widgets.fieldpanel.support.Highlight;
import docking.widgets.fieldpanel.support.FieldHighlightFactory;
+import docking.widgets.fieldpanel.support.Highlight;
import ghidra.app.plugin.core.format.ByteBlockInfo;
/**
@@ -30,7 +32,7 @@ import ghidra.app.plugin.core.format.ByteBlockInfo;
*/
class IndexFieldFactory {
- private FontMetrics fm;
+ private FontMetrics metrics;
private int width;
private IndexMap indexMap;
private int charWidth;
@@ -41,21 +43,21 @@ class IndexFieldFactory {
/**
* Constructor
- * @param fieldModel field model
+ * @param metrics the FontMetrics this field should use to do size computations
*/
- IndexFieldFactory(FontMetrics fm) {
- this.fm = fm;
+ IndexFieldFactory(FontMetrics metrics) {
+ this.metrics = metrics;
- charWidth = fm.charWidth('W');
+ charWidth = metrics.charWidth('W');
width = ByteViewerComponentProvider.DEFAULT_NUMBER_OF_CHARS * charWidth;
missingValueColor = ByteViewerComponentProvider.SEPARATOR_COLOR;
+ startX = charWidth;
}
/**
* Gets a Field object for the given index.
- * This method is called for n times where n is the number of fields
- * in the model. In this case, we only have one field, so it gets
- * called once for each index.
+ * @param index the index to get a Field for
+ * @return The Field for the given index
*/
public Field getField(BigInteger index) {
@@ -74,8 +76,8 @@ class IndexFieldFactory {
}
if (info == null) {
if (indexMap.isBlockSeparatorIndex(index)) {
- SimpleTextField sf =
- new SimpleTextField(noValueStr, fm, startX, width, false, highlightFactory);
+ SimpleTextField sf = new SimpleTextField(noValueStr, metrics, startX, width,
+ false, highlightFactory);
sf.setForeground(missingValueColor);
return sf;
@@ -87,15 +89,16 @@ class IndexFieldFactory {
if (locRep == null) {
return null;
}
- return new SimpleTextField(locRep, fm, startX, width, false, highlightFactory);
+ return new SimpleTextField(locRep, metrics, startX, width, false, highlightFactory);
}
public FontMetrics getMetrics() {
- return fm;
+ return metrics;
}
/**
* Sets the starting x position for the fields generated by this factory
+ * @param x The
*/
public void setStartX(int x) {
startX = x;
@@ -103,6 +106,7 @@ class IndexFieldFactory {
/**
* Returns the starting x position for the fields generated by this factory.
+ * @return the starting x position for the fields generated by this factory.
*/
public int getStartX() {
return startX;
@@ -110,26 +114,30 @@ class IndexFieldFactory {
/**
* Returns the width of the fields associated with this Factory.
+ * @return the width of the fields associated with this Factory
*/
public int getWidth() {
return width;
}
/**
- * Set byte blocks.
- * @param blocks
+ * Sets the indexMap which is the data source for the generated fields.
+ * @param indexMap indexMap which produces the index string for specific indexes
*/
- void setIndexMap(IndexMap indexMap, int maxWidth) {
+ void setIndexMap(IndexMap indexMap) {
this.indexMap = indexMap;
- width = maxWidth - (2 * charWidth);
- int nchars = width / charWidth;
- if (indexMap != null) {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < nchars; i++) {
- sb.append(".");
- }
- noValueStr = sb.toString();
- }
+ }
+
+ /**
+ * Sets the size of this field based on the number of chars to display
+ * @param charCount the number of chars to
+ */
+ void setSize(int charCount) {
+ width = charCount * charWidth;
+ // add in space for margins
+ width += 2 * charWidth;
+
+ noValueStr = StringUtils.repeat('.', charCount);
}
void setMissingValueColor(Color c) {
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/InteractivePanelManager.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/InteractivePanelManager.java
new file mode 100644
index 0000000000..b2b90fe96b
--- /dev/null
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/InteractivePanelManager.java
@@ -0,0 +1,304 @@
+/* ###
+ * 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 ghidra.app.plugin.core.byteviewer;
+
+import java.awt.*;
+import java.beans.PropertyChangeEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+
+/**
+ * Creates a container for holding multiple horizontally aligned components and provides
+ * a {@link JTableHeader} that can be used to interactively reorder and resize the
+ * components that are managed by this container.
+ */
+public class InteractivePanelManager {
+ private JPanel mainPanel;
+ private JTableHeader header;
+ private TableColumnModel columnModel;
+ private int separatorWidth;
+
+ public InteractivePanelManager() {
+ JTable table = new JTable();
+ header = new JTableHeader();
+ table.setTableHeader(header);
+ columnModel = header.getColumnModel();
+ separatorWidth = (new JSeparator(SwingConstants.VERTICAL)).getPreferredSize().width;
+ mainPanel = new JPanel(new HeaderLayoutManager());
+ columnModel.addColumnModelListener(new PanelManagerColumnModelListener());
+ }
+
+ /**
+ * Sets the font for the header component.
+ * @param font the font to be used to display view names in the header
+ */
+ public void setHeaderFont(Font font) {
+ header.setFont(font);
+ }
+
+ /**
+ * Adds a component and it's name to the set of managed components.
+ * @param name the name to display in its column header.
+ * @param component the component to add
+ */
+ public void addComponent(String name, JComponent component) {
+ TableColumn column = new TableColumn();
+ column.addPropertyChangeListener(e -> columnPropertyChanged(e));
+ column.setHeaderValue(new ComponentData(name, component));
+ column.setPreferredWidth(component.getPreferredSize().width + separatorWidth);
+ column.setWidth(component.getPreferredSize().width);
+ columnModel.addColumn(column);
+ mainPanel.add(component);
+ mainPanel.add(new JSeparator(SwingConstants.VERTICAL));
+ }
+
+ /**
+ * Returns a list of the components being managed.
+ * @return a list of the components being managed.
+ */
+ public List getComponents() {
+ List components = new ArrayList<>();
+ for (int i = 0; i < columnModel.getColumnCount(); i++) {
+ TableColumn column = columnModel.getColumn(i);
+ components.add(((ComponentData) column.getHeaderValue()).component);
+ }
+ return components;
+ }
+
+ /**
+ * Sets the name for a component
+ * @param component the component for which to change its associated name
+ * @param newName the new name for the component
+ */
+ public void setName(JComponent component, String newName) {
+ for (int i = 0; i < columnModel.getColumnCount(); i++) {
+ TableColumn column = columnModel.getColumn(i);
+ ComponentData componentData = (ComponentData) column.getHeaderValue();
+ if (componentData.component() == component) {
+ column.setHeaderValue(new ComponentData(newName, component));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Removes the given component from being managed.
+ * @param component the component to be removed
+ */
+ public void removeComponent(JComponent component) {
+
+ int componentCount = mainPanel.getComponentCount();
+ for (int i = 0; i < componentCount; i++) {
+ if (mainPanel.getComponent(i) == component) {
+ mainPanel.remove(i);
+ mainPanel.remove(i); // also remove the JSeparator the follows it
+ break;
+ }
+ }
+ for (int i = 0; i < columnModel.getColumnCount(); i++) {
+ TableColumn column = columnModel.getColumn(i);
+ if (((ComponentData) column.getHeaderValue()).component == component) {
+ columnModel.removeColumn(column);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns the mainPanel containing the horizontally laid components.
+ * @return the mainPanel containing the horizontally laid components
+ */
+ public JComponent getMainPanel() {
+ return mainPanel;
+ }
+
+ /**
+ * Returns the {@link JTableHeader} component that can be used to reorder and resize
+ * the components
+ * @return the JTableHeader for managing the order and size of the components
+ */
+ public JComponent getColumnHeader() {
+ return header;
+ }
+
+ /**
+ * Returns the current width of the component with the given name.
+ * @param viewName the name of the component for which to get its width
+ * @return the current width of the component with the given name
+ */
+ public int getColumnWidth(String viewName) {
+ for (int i = 0; i < columnModel.getColumnCount(); i++) {
+ TableColumn column = columnModel.getColumn(i);
+ ComponentData data = (ComponentData) column.getHeaderValue();
+ if (data.name().equals(viewName)) {
+ return column.getWidth();
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Sets the width of the named component.
+ * @param viewName the name of the component to resize
+ * @param width the new width for the given component
+ */
+ public void setColumnWidth(String viewName, int width) {
+ for (int i = 0; i < columnModel.getColumnCount(); i++) {
+ TableColumn column = columnModel.getColumn(i);
+ ComponentData data = (ComponentData) column.getHeaderValue();
+ if (data.name().equals(viewName)) {
+ column.setWidth(width);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Resets the named component back to its preferred size.
+ * @param viewName the name of the component to restore to its preferred size
+ */
+ public void resetColumnWidthToPreferredWidth(String viewName) {
+ for (int i = 0; i < columnModel.getColumnCount(); i++) {
+ TableColumn column = columnModel.getColumn(i);
+ ComponentData data = (ComponentData) column.getHeaderValue();
+ if (data.name().equals(viewName)) {
+ column.setWidth(data.component().getPreferredSize().width);
+ return;
+ }
+ }
+ }
+
+ private void columnPropertyChanged(PropertyChangeEvent e) {
+ if ("width".equals(e.getPropertyName())) {
+ TableColumn column = (TableColumn) e.getSource();
+ column.setPreferredWidth((int) e.getNewValue());
+ update();
+ }
+ }
+
+ private void update() {
+ mainPanel.invalidate();
+ Container parent = mainPanel.getParent();
+ if (parent != null) {
+ parent.validate();
+ parent.repaint();
+ }
+ }
+
+ private class HeaderLayoutManager implements LayoutManager {
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+ // don't care
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+ // don't care
+ }
+
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ Insets insets = parent.getInsets();
+ int n = parent.getComponentCount();
+ int height = 0;
+ int width = columnModel.getTotalColumnWidth();
+
+ for (int i = 0; i < n; i++) {
+ Component c = parent.getComponent(i);
+ Dimension d = c.getPreferredSize();
+ height = Math.max(height, d.height);
+ }
+ return new Dimension(width + insets.left + insets.right,
+ height + insets.top + insets.bottom);
+
+ }
+
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ return preferredLayoutSize(parent);
+ }
+
+ @Override
+ public void layoutContainer(Container parent) {
+ int n = parent.getComponentCount();
+ Dimension d = parent.getSize();
+ Insets insets = parent.getInsets();
+ int height = d.height - insets.top - insets.bottom;
+
+ int x = insets.left;
+ int y = insets.top;
+ for (int i = 0; i < n; i++) {
+ // even components are the actual managed components, odd components are JSeparators
+ if (i % 2 == 0) {
+ TableColumn column = columnModel.getColumn(i / 2);
+ ComponentData componentData = (ComponentData) column.getHeaderValue();
+ JComponent c = componentData.component();
+ int width = column.getWidth() - separatorWidth;
+ c.setBounds(x, y, width, height);
+ x += width;
+ }
+ else {
+ Component c = parent.getComponent(i);
+ d = c.getPreferredSize();
+ c.setBounds(x, y, d.width, height);
+ x += d.width;
+ }
+ }
+ }
+
+ }
+
+ private class PanelManagerColumnModelListener implements TableColumnModelListener {
+
+ @Override
+ public void columnAdded(TableColumnModelEvent e) {
+ update();
+ }
+
+ @Override
+ public void columnRemoved(TableColumnModelEvent e) {
+ update();
+ }
+
+ @Override
+ public void columnMoved(TableColumnModelEvent e) {
+ update();
+ }
+
+ @Override
+ public void columnMarginChanged(ChangeEvent e) {
+ // ignore
+ }
+
+ @Override
+ public void columnSelectionChanged(ListSelectionEvent e) {
+ // ignore
+ }
+
+ }
+
+ record ComponentData(String name, JComponent component) {
+ public String toString() {
+ return name;
+ }
+ }
+
+}
diff --git a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin1Test.java b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin1Test.java
index bd52ae8b50..e5abd211ce 100644
--- a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin1Test.java
+++ b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin1Test.java
@@ -24,7 +24,8 @@ import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
-import javax.swing.event.TableColumnModelEvent;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumnModel;
import org.junit.*;
@@ -167,10 +168,9 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
assertEquals(3, panel.getNumberOfViews());
- DataModelInfo info = panel.getDataModelInfo();
- String[] names = info.getNames();
- assertEquals(3, names.length);
- Set viewNames = new HashSet<>(Arrays.asList(names));
+ List names = panel.getViewNamesInDisplayOrder();
+ assertEquals(3, names.size());
+ Set viewNames = new HashSet<>(names);
assertTrue(viewNames.contains("Hex"));
assertTrue(viewNames.contains("Octal"));
assertTrue(viewNames.contains("Ascii"));
@@ -196,10 +196,9 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
assertEquals(1, panel.getNumberOfViews());
- info = panel.getDataModelInfo();
- names = info.getNames();
- assertEquals(1, names.length);
- assertEquals("Octal", names[0]);
+ names = panel.getViewNamesInDisplayOrder();
+ assertEquals(1, names.size());
+ assertEquals("Octal", names.get(0));
}
@@ -618,56 +617,73 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testReorderViews() throws Exception {
loadViews("Ascii", "Octal");
- final ByteViewerHeader columnHeader =
- (ByteViewerHeader) findContainer(panel, ByteViewerHeader.class);
+
+ List names = panel.getViewNamesInDisplayOrder();
+ assertEquals("Hex", names.get(0));
+ assertEquals("Octal", names.get(1));
+ assertEquals("Ascii", names.get(2));
+
+ final JTableHeader columnHeader = (JTableHeader) findContainer(panel, JTableHeader.class);
// move column 3 to 2
runSwing(() -> {
- TableColumnModelEvent ev =
- new TableColumnModelEvent(columnHeader.getColumnModel(), 3, 2);
- panel.columnMoved(ev);
+ TableColumnModel columnModel = columnHeader.getColumnModel();
+ columnModel.moveColumn(3, 2);
});
- String[] names = panel.getDataModelInfo().getNames();
+ names = panel.getViewNamesInDisplayOrder();
+ assertEquals("Hex", names.get(0));
+ assertEquals("Ascii", names.get(1));
+ assertEquals("Octal", names.get(2));
- // move column 1 to 0
+ // move column 2 to 1
runSwing(() -> {
- TableColumnModelEvent ev =
- new TableColumnModelEvent(columnHeader.getColumnModel(), 2, 1);
- panel.columnMoved(ev);
+ TableColumnModel columnModel = columnHeader.getColumnModel();
+ columnModel.moveColumn(2, 1);
});
- String[] newNames = panel.getDataModelInfo().getNames();
- assertEquals(names[0], newNames[1]);
- assertEquals(names[1], newNames[0]);
- assertEquals(names[2], newNames[2]);
+ names = panel.getViewNamesInDisplayOrder();
+ assertEquals("Ascii", names.get(0));
+ assertEquals("Hex", names.get(1));
+ assertEquals("Octal", names.get(2));
}
+ @Test
+ public void testResizeViews() {
+ loadViews("Ascii", "Octal");
+ assertNotEquals(200, getViewWidth("Ascii"));
+
+ setViewWidth("Ascii", 200);
+
+ assertEquals(200, panel.getViewWidth("Ascii"));
+ }
+
+ @Test
+ public void testResizeViewsSaveState() {
+ loadViews("Ascii", "Octal");
+ assertNotEquals(200, getViewWidth("Ascii"));
+
+ setViewWidth("Ascii", 200);
+ env.saveRestoreToolState();
+
+ assertEquals(200, panel.getViewWidth("Ascii"));
+ }
+
@Test
public void testReorderViewsSaveState() throws Exception {
loadViews("Ascii", "Octal");
- final ByteViewerHeader columnHeader =
- (ByteViewerHeader) findContainer(panel, ByteViewerHeader.class);
- // move column 3 to 2
- runSwing(() -> {
- TableColumnModelEvent ev =
- new TableColumnModelEvent(columnHeader.getColumnModel(), 3, 2);
- panel.columnMoved(ev);
- });
+ final JTableHeader columnHeader = (JTableHeader) findContainer(panel, JTableHeader.class);
// move column 1 to 0
runSwing(() -> {
- TableColumnModelEvent ev =
- new TableColumnModelEvent(columnHeader.getColumnModel(), 1, 0);
- panel.columnMoved(ev);
+ TableColumnModel columnModel = columnHeader.getColumnModel();
+ columnModel.moveColumn(3, 2);
});
- String[] names = panel.getDataModelInfo().getNames();
+ List names = panel.getViewNamesInDisplayOrder();
env.saveRestoreToolState();
- String[] newNames = panel.getDataModelInfo().getNames();
- for (int i = 0; i < names.length; i++) {
- assertEquals(names[i], newNames[i]);
- }
+ List newNames = panel.getViewNamesInDisplayOrder();
+ assertEquals(names, newNames);
}
@Test
@@ -861,8 +877,8 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
}
private Address convertToAddr(ByteBlockInfo info) {
- return ((ProgramByteBlockSet) plugin.getProvider().getByteBlockSet()).getAddress(
- info.getBlock(), info.getOffset());
+ return ((ProgramByteBlockSet) plugin.getProvider().getByteBlockSet())
+ .getAddress(info.getBlock(), info.getOffset());
}
private boolean byteBlockSelectionEquals(ByteBlockSelection b1, ByteBlockSelection b2) {
@@ -942,4 +958,15 @@ public class ByteViewerPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
return null;
}
+ private void setViewWidth(String name, int width) {
+ runSwing(() -> {
+ panel.setViewWidth(name, width);
+ });
+ }
+
+ private int getViewWidth(String name) {
+ return runSwing(() -> {
+ return panel.getViewWidth("Ascii");
+ });
+ }
}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/indexedscrollpane/IndexedScrollable.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/indexedscrollpane/IndexedScrollable.java
index 94157daddf..a8a90db072 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/indexedscrollpane/IndexedScrollable.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/indexedscrollpane/IndexedScrollable.java
@@ -103,4 +103,5 @@ public interface IndexedScrollable {
* @param isHorizontal true if the rotation was horizontal, false for vertical
*/
public void mouseWheelMoved(double preciseWheelRotation, boolean isHorizontal);
+
}