GP-787: Refactored Regions,Modules/Sections,Mappings,Threads to use RowWrapped...

This commit is contained in:
Dan 2021-05-04 15:10:34 -04:00
parent 84c77bb90c
commit 085daeb39b
17 changed files with 159 additions and 149 deletions

View file

@ -18,7 +18,8 @@ package ghidra.app.plugin.core.debug.gui;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.event.*; import java.awt.event.*;
import java.util.*; import java.util.List;
import java.util.Set;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.function.Function; import java.util.function.Function;
@ -1560,11 +1561,11 @@ public interface DebuggerResources {
}; };
} }
static <V, R> void setSelectedRows(Set<V> sel, Map<V, R> rowMap, GTable table, static <V, R> void setSelectedRows(Set<V> sel, Function<V, R> rowMapper, GTable table,
RowObjectTableModel<R> model, GTableFilterPanel<R> filterPanel) { RowObjectTableModel<R> model, GTableFilterPanel<R> filterPanel) {
table.clearSelection(); table.clearSelection();
for (V v : sel) { for (V v : sel) {
R row = rowMap.get(v); R row = rowMapper.apply(v);
if (row == null) { if (row == null) {
continue; continue;
} }

View file

@ -971,14 +971,12 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
} }
public void setSelectedBreakpoints(Set<LogicalBreakpoint> sel) { public void setSelectedBreakpoints(Set<LogicalBreakpoint> sel) {
DebuggerResources.setSelectedRows(sel, breakpointTableModel.getMap(), breakpointTable, DebuggerResources.setSelectedRows(sel, breakpointTableModel::getRow, breakpointTable,
breakpointTableModel, breakpointFilterPanel); breakpointTableModel, breakpointFilterPanel);
} }
public void setSelectedLocations(Set<TraceBreakpoint> sel) { public void setSelectedLocations(Set<TraceBreakpoint> sel) {
DebuggerResources.setSelectedRows( DebuggerResources.setSelectedRows(sel, locationTableModel::getRow, locationTable,
sel.stream().map(b -> b.getObjectKey()).collect(Collectors.toSet()),
locationTableModel.getMap(), locationTable,
locationTableModel, locationFilterPanel); locationTableModel, locationFilterPanel);
} }
} }

View file

@ -31,8 +31,9 @@ import com.google.common.collect.Range;
import docking.ActionContext; import docking.ActionContext;
import docking.WindowPosition; import docking.WindowPosition;
import docking.action.*; import docking.action.*;
import docking.widgets.table.*; import docking.widgets.table.CustomToStringCellRenderer;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn; import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
import docking.widgets.table.RowWrappedEnumeratedColumnTableModel;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction; import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSelectAddressesAction;
@ -51,6 +52,7 @@ import ghidra.trace.model.Trace.TraceMemoryRegionChangeType;
import ghidra.trace.model.TraceDomainObjectListener; import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.memory.TraceMemoryManager; import ghidra.trace.model.memory.TraceMemoryManager;
import ghidra.trace.model.memory.TraceMemoryRegion; import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.util.database.ObjectKey;
import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTable;
import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.GhidraTableFilterPanel;
@ -112,6 +114,16 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
} }
} }
protected static class RegionTableModel
extends RowWrappedEnumeratedColumnTableModel< //
RegionTableColumns, ObjectKey, RegionRow, TraceMemoryRegion> {
public RegionTableModel() {
super("Regions", RegionTableColumns.class, TraceMemoryRegion::getObjectKey,
RegionRow::new);
}
}
protected static RegionRow getSelectedRegionRow(ActionContext context) { protected static RegionRow getSelectedRegionRow(ActionContext context) {
if (!(context instanceof DebuggerRegionActionContext)) { if (!(context instanceof DebuggerRegionActionContext)) {
return null; return null;
@ -150,26 +162,15 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
} }
private void regionAdded(TraceMemoryRegion region) { private void regionAdded(TraceMemoryRegion region) {
regionMap.computeIfAbsent(region, r -> { regionTableModel.addItem(region);
RegionRow rr = new RegionRow(r);
regionTableModel.add(rr);
return rr;
});
/**
* NOTE: No need to add sections here. A TraceModule is created empty, so when each
* section is added, we'll get the call.
*/
} }
private void regionChanged(TraceMemoryRegion region) { private void regionChanged(TraceMemoryRegion region) {
regionTableModel.notifyUpdated(regionMap.get(region)); regionTableModel.updateItem(region);
} }
private void regionDeleted(TraceMemoryRegion region) { private void regionDeleted(TraceMemoryRegion region) {
RegionRow rr = regionMap.remove(region); regionTableModel.deleteItem(region);
if (rr != null) {
regionTableModel.delete(rr);
}
} }
} }
@ -222,9 +223,7 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
private final RegionsListener regionsListener = new RegionsListener(); private final RegionsListener regionsListener = new RegionsListener();
protected final Map<TraceMemoryRegion, RegionRow> regionMap = new HashMap<>(); protected final RegionTableModel regionTableModel = new RegionTableModel();
protected final EnumeratedColumnTableModel<RegionRow> regionTableModel =
new DefaultEnumeratedColumnTableModel<>("Regions", RegionTableColumns.class);
protected GhidraTable regionTable; protected GhidraTable regionTable;
private GhidraTableFilterPanel<RegionRow> regionFilterPanel; private GhidraTableFilterPanel<RegionRow> regionFilterPanel;
@ -262,16 +261,13 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
} }
private void loadRegions() { private void loadRegions() {
regionMap.clear();
regionTableModel.clear(); regionTableModel.clear();
if (currentTrace == null) { if (currentTrace == null) {
return; return;
} }
TraceMemoryManager memoryManager = currentTrace.getMemoryManager(); TraceMemoryManager memoryManager = currentTrace.getMemoryManager();
for (TraceMemoryRegion region : memoryManager.getAllRegions()) { regionTableModel.addAllItems(memoryManager.getAllRegions());
regionTableModel.add(regionMap.computeIfAbsent(region, RegionRow::new));
}
} }
protected void buildMainPanel() { protected void buildMainPanel() {
@ -376,8 +372,8 @@ public class DebuggerRegionsProvider extends ComponentProviderAdapter {
} }
public void setSelectedRegions(Set<TraceMemoryRegion> sel) { public void setSelectedRegions(Set<TraceMemoryRegion> sel) {
DebuggerResources.setSelectedRows(sel, regionMap, regionTable, regionTableModel, DebuggerResources.setSelectedRows(sel, regionTableModel::getRow, regionTable,
regionFilterPanel); regionTableModel, regionFilterPanel);
} }
public Collection<RegionRow> getSelectedRows() { public Collection<RegionRow> getSelectedRows() {

View file

@ -64,6 +64,7 @@ import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.modules.*; import ghidra.trace.model.modules.*;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.database.ObjectKey;
import ghidra.util.datastruct.CollectionChangeListener; import ghidra.util.datastruct.CollectionChangeListener;
import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTable;
import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.GhidraTableFilterPanel;
@ -198,6 +199,25 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
return sections.iterator().next(); return sections.iterator().next();
} }
protected static class ModuleTableModel
extends RowWrappedEnumeratedColumnTableModel< //
ModuleTableColumns, ObjectKey, ModuleRow, TraceModule> {
public ModuleTableModel() {
super("Modules", ModuleTableColumns.class, TraceModule::getObjectKey, ModuleRow::new);
}
}
protected static class SectionTableModel
extends RowWrappedEnumeratedColumnTableModel< //
SectionTableColumns, ObjectKey, SectionRow, TraceSection> {
public SectionTableModel() {
super("Sections", SectionTableColumns.class, TraceSection::getObjectKey,
SectionRow::new);
}
}
protected static Set<TraceModule> getSelectedModules(ActionContext context) { protected static Set<TraceModule> getSelectedModules(ActionContext context) {
if (context instanceof DebuggerModuleActionContext) { if (context instanceof DebuggerModuleActionContext) {
DebuggerModuleActionContext ctx = (DebuggerModuleActionContext) context; DebuggerModuleActionContext ctx = (DebuggerModuleActionContext) context;
@ -253,54 +273,39 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
} }
private void moduleAdded(TraceModule module) { private void moduleAdded(TraceModule module) {
moduleMap.computeIfAbsent(module, m -> { moduleTableModel.addItem(module);
ModuleRow mr = new ModuleRow(m); /**
moduleTableModel.add(mr); * NOTE: No need to add sections here. A TraceModule is created empty, so when each
return mr; * section is added, we'll get the call.
});/** */
* NOTE: No need to add sections here. A TraceModule is created empty, so when each
* section is added, we'll get the call.
*/
} }
private void moduleChanged(TraceModule module) { private void moduleChanged(TraceModule module) {
moduleTableModel.notifyUpdated(moduleMap.get(module)); moduleTableModel.updateItem(module);
sectionTableModel.fireTableDataChanged(); // Because module name in section row sectionTableModel.fireTableDataChanged(); // Because module name in section row
} }
private void moduleDeleted(TraceModule module) { private void moduleDeleted(TraceModule module) {
ModuleRow mr = moduleMap.remove(module); moduleTableModel.deleteItem(module);
if (mr != null) {
moduleTableModel.delete(mr);
}
// NOTE: module.getSections() will be empty, now // NOTE: module.getSections() will be empty, now
for (Iterator<Entry<TraceSection, SectionRow>> it = sectionMap.entrySet().iterator(); it sectionTableModel.deleteAllItems(sectionTableModel.getMap()
.hasNext();) { .values()
Entry<TraceSection, SectionRow> ent = it.next(); .stream()
if (ent.getKey().getModule() == module) { .filter(r -> r.getModule() == module)
it.remove(); .map(r -> r.getSection())
sectionTableModel.delete(ent.getValue()); .collect(Collectors.toList()));
}
}
} }
private void sectionAdded(TraceSection section) { private void sectionAdded(TraceSection section) {
sectionMap.computeIfAbsent(section, s -> { sectionTableModel.addItem(section);
SectionRow sr = new SectionRow(s);
sectionTableModel.add(sr);
return sr;
});
} }
private void sectionChanged(TraceSection section) { private void sectionChanged(TraceSection section) {
sectionTableModel.notifyUpdated(sectionMap.get(section)); sectionTableModel.updateItem(section);
} }
private void sectionDeleted(TraceSection section) { private void sectionDeleted(TraceSection section) {
SectionRow sr = sectionMap.remove(section); sectionTableModel.deleteItem(section);
if (sr != null) {
sectionTableModel.delete(sr);
}
} }
} }
@ -516,15 +521,11 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
private final RecordersChangedListener recordersChangedListener = private final RecordersChangedListener recordersChangedListener =
new RecordersChangedListener(); new RecordersChangedListener();
protected final Map<TraceModule, ModuleRow> moduleMap = new HashMap<>(); protected final ModuleTableModel moduleTableModel = new ModuleTableModel();
protected final EnumeratedColumnTableModel<ModuleRow> moduleTableModel =
new DefaultEnumeratedColumnTableModel<>("Modules", ModuleTableColumns.class);
protected GhidraTable moduleTable; protected GhidraTable moduleTable;
private GhidraTableFilterPanel<ModuleRow> moduleFilterPanel; private GhidraTableFilterPanel<ModuleRow> moduleFilterPanel;
protected final Map<TraceSection, SectionRow> sectionMap = new HashMap<>(); protected final SectionTableModel sectionTableModel = new SectionTableModel();
protected final EnumeratedColumnTableModel<SectionRow> sectionTableModel =
new DefaultEnumeratedColumnTableModel<>("Sections", SectionTableColumns.class);
protected GhidraTable sectionTable; protected GhidraTable sectionTable;
protected GhidraTableFilterPanel<SectionRow> sectionFilterPanel; protected GhidraTableFilterPanel<SectionRow> sectionFilterPanel;
private final SectionsBySelectedModulesTableFilter filterSectionsBySelectedModules = private final SectionsBySelectedModulesTableFilter filterSectionsBySelectedModules =
@ -598,22 +599,16 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
} }
private void loadModules() { private void loadModules() {
moduleMap.clear();
moduleTableModel.clear(); moduleTableModel.clear();
sectionMap.clear();
sectionTableModel.clear(); sectionTableModel.clear();
if (currentTrace == null) { if (currentTrace == null) {
return; return;
} }
TraceModuleManager moduleManager = currentTrace.getModuleManager(); TraceModuleManager moduleManager = currentTrace.getModuleManager();
for (TraceModule module : moduleManager.getAllModules()) { moduleTableModel.addAllItems(moduleManager.getAllModules());
moduleTableModel.add(moduleMap.computeIfAbsent(module, ModuleRow::new)); sectionTableModel.addAllItems(moduleManager.getAllSections());
for (TraceSection section : module.getSections()) {
sectionTableModel.add(sectionMap.computeIfAbsent(section, SectionRow::new));
}
}
} }
protected void buildMainPanel() { protected void buildMainPanel() {
@ -1092,13 +1087,13 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
} }
public void setSelectedModules(Set<TraceModule> sel) { public void setSelectedModules(Set<TraceModule> sel) {
DebuggerResources.setSelectedRows(sel, moduleMap, moduleTable, moduleTableModel, DebuggerResources.setSelectedRows(sel, moduleTableModel::getRow, moduleTable,
moduleFilterPanel); moduleTableModel, moduleFilterPanel);
} }
public void setSelectedSections(Set<TraceSection> sel) { public void setSelectedSections(Set<TraceSection> sel) {
DebuggerResources.setSelectedRows(sel, sectionMap, sectionTable, sectionTableModel, DebuggerResources.setSelectedRows(sel, sectionTableModel::getRow, sectionTable,
sectionFilterPanel); sectionTableModel, sectionFilterPanel);
} }
private DataTreeDialog getProgramChooserDialog() { private DataTreeDialog getProgramChooserDialog() {

View file

@ -19,7 +19,8 @@ import java.awt.BorderLayout;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.HashSet;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import javax.swing.*; import javax.swing.*;
@ -54,6 +55,7 @@ import ghidra.trace.model.modules.TraceStaticMappingManager;
import ghidra.trace.model.program.TraceProgramView; import ghidra.trace.model.program.TraceProgramView;
import ghidra.util.MathUtilities; import ghidra.util.MathUtilities;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.database.ObjectKey;
import ghidra.util.database.UndoableTransaction; import ghidra.util.database.UndoableTransaction;
import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.GhidraTableFilterPanel;
@ -95,6 +97,16 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
} }
} }
protected static class MappingTableModel
extends RowWrappedEnumeratedColumnTableModel< //
StaticMappingTableColumns, ObjectKey, StaticMappingRow, TraceStaticMapping> {
public MappingTableModel() {
super("Mappings", StaticMappingTableColumns.class, TraceStaticMapping::getObjectKey,
StaticMappingRow::new);
}
}
protected class ListenerForStaticMappingDisplay extends TraceDomainObjectListener { protected class ListenerForStaticMappingDisplay extends TraceDomainObjectListener {
public ListenerForStaticMappingDisplay() { public ListenerForStaticMappingDisplay() {
listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored()); listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored());
@ -107,11 +119,11 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
} }
private void staticMappingAdded(TraceStaticMapping mapping) { private void staticMappingAdded(TraceStaticMapping mapping) {
addMapping(mapping); mappingTableModel.addItem(mapping);
} }
private void staticMappingDeleted(TraceStaticMapping mapping) { private void staticMappingDeleted(TraceStaticMapping mapping) {
mappingTableModel.deleteWith(rec -> rec.getMapping() == mapping); mappingTableModel.deleteItem(mapping);
} }
} }
@ -135,8 +147,7 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
private ListenerForStaticMappingDisplay listener = new ListenerForStaticMappingDisplay(); private ListenerForStaticMappingDisplay listener = new ListenerForStaticMappingDisplay();
protected final EnumeratedColumnTableModel<StaticMappingRow> mappingTableModel = protected final MappingTableModel mappingTableModel = new MappingTableModel();
new DefaultEnumeratedColumnTableModel<>("Mappings", StaticMappingTableColumns.class);
private JPanel mainPanel = new JPanel(new BorderLayout()); private JPanel mainPanel = new JPanel(new BorderLayout());
protected GTable mappingTable; protected GTable mappingTable;
@ -187,23 +198,13 @@ public class DebuggerStaticMappingProvider extends ComponentProviderAdapter
return myActionContext; return myActionContext;
} }
private void addMapping(TraceStaticMapping mapping) {
mappingTableModel.add(new StaticMappingRow(mapping));
}
private void addMappings(Collection<? extends TraceStaticMapping> entries) {
for (TraceStaticMapping ent : entries) {
addMapping(ent);
}
}
private void loadMappings() { private void loadMappings() {
mappingTableModel.clear(); mappingTableModel.clear();
if (currentTrace == null) { if (currentTrace == null) {
return; return;
} }
TraceStaticMappingManager manager = currentTrace.getStaticMappingManager(); TraceStaticMappingManager manager = currentTrace.getStaticMappingManager();
addMappings(manager.getAllEntries()); mappingTableModel.addAllItems(manager.getAllEntries());
} }
protected void buildMainPanel() { protected void buildMainPanel() {

View file

@ -214,11 +214,6 @@ public class ObjectEnumeratedColumnTableModel<C extends ObjectsEnumeratedTableCo
fireTableRowsInserted(startIndex, endIndex); fireTableRowsInserted(startIndex, endIndex);
} }
@Override
public RowIterator<R> rowIterator() {
return new TableRowIterator();
}
@Override @Override
public void notifyUpdated(R row) { public void notifyUpdated(R row) {
int rowIndex = modelData.indexOf(row); int rowIndex = modelData.indexOf(row);

View file

@ -30,7 +30,8 @@ import docking.action.*;
import docking.widgets.EventTrigger; import docking.widgets.EventTrigger;
import docking.widgets.HorizontalTabPanel; import docking.widgets.HorizontalTabPanel;
import docking.widgets.HorizontalTabPanel.TabListCellRenderer; import docking.widgets.HorizontalTabPanel.TabListCellRenderer;
import docking.widgets.table.*; import docking.widgets.table.GTable;
import docking.widgets.table.RowWrappedEnumeratedColumnTableModel;
import docking.widgets.timeline.TimelineListener; import docking.widgets.timeline.TimelineListener;
import ghidra.app.plugin.core.debug.DebuggerCoordinates; import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
@ -55,6 +56,7 @@ import ghidra.trace.model.thread.TraceThreadManager;
import ghidra.trace.model.time.TraceSchedule; import ghidra.trace.model.time.TraceSchedule;
import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.TraceSnapshot;
import ghidra.util.Swing; import ghidra.util.Swing;
import ghidra.util.database.ObjectKey;
import ghidra.util.datastruct.CollectionChangeListener; import ghidra.util.datastruct.CollectionChangeListener;
import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTable;
import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.GhidraTableFilterPanel;
@ -249,6 +251,16 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
} }
} }
protected static class ThreadTableModel
extends RowWrappedEnumeratedColumnTableModel< //
ThreadTableColumns, ObjectKey, ThreadRow, TraceThread> {
public ThreadTableModel(DebuggerThreadsProvider provider) {
super("Threads", ThreadTableColumns.class, TraceThread::getObjectKey,
t -> new ThreadRow(provider.modelService, t));
}
}
private class ThreadsListener extends TraceDomainObjectListener { private class ThreadsListener extends TraceDomainObjectListener {
public ThreadsListener() { public ThreadsListener() {
listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored()); listenForUntyped(DomainObject.DO_OBJECT_RESTORED, e -> objectRestored());
@ -267,23 +279,15 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
} }
private void threadAdded(TraceThread thread) { private void threadAdded(TraceThread thread) {
threadMap.computeIfAbsent(thread, t -> { threadTableModel.addItem(thread);
ThreadRow tr = new ThreadRow(modelService, t);
threadTableModel.add(tr);
doSetThread(thread);
return tr;
});
} }
private void threadChanged(TraceThread thread) { private void threadChanged(TraceThread thread) {
threadTableModel.notifyUpdatedWith(row -> row.getThread() == thread); threadTableModel.updateItem(thread);
} }
private void threadDeleted(TraceThread thread) { private void threadDeleted(TraceThread thread) {
ThreadRow tr = threadMap.remove(thread); threadTableModel.deleteItem(thread);
if (tr != null) {
threadTableModel.delete(tr);
}
} }
private void snapAdded(TraceSnapshot snapshot) { private void snapAdded(TraceSnapshot snapshot) {
@ -333,9 +337,7 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
private final CollectionChangeListener<TraceRecorder> recordersListener = private final CollectionChangeListener<TraceRecorder> recordersListener =
new RecordersChangeListener(); new RecordersChangeListener();
protected final Map<TraceThread, ThreadRow> threadMap = new HashMap<>(); protected final ThreadTableModel threadTableModel = new ThreadTableModel(this);
protected final EnumeratedColumnTableModel<ThreadRow> threadTableModel =
new DefaultEnumeratedColumnTableModel<>("Threads", ThreadTableColumns.class);
private JPanel mainPanel; private JPanel mainPanel;
private JSplitPane splitPane; private JSplitPane splitPane;
@ -453,7 +455,7 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
} }
try (Suppression supp = cbCoordinateActivation.suppress(null)) { try (Suppression supp = cbCoordinateActivation.suppress(null)) {
if (thread != null) { if (thread != null) {
threadFilterPanel.setSelectedItem(threadMap.get(thread)); threadFilterPanel.setSelectedItem(threadTableModel.getRow(thread));
} }
else { else {
threadTable.clearSelection(); threadTable.clearSelection();
@ -495,20 +497,13 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
} }
protected void loadThreads() { protected void loadThreads() {
threadMap.clear();
threadTableModel.clear(); threadTableModel.clear();
Trace curTrace = current.getTrace(); Trace curTrace = current.getTrace();
if (curTrace == null) { if (curTrace == null) {
return; return;
} }
TraceThreadManager manager = curTrace.getThreadManager(); TraceThreadManager manager = curTrace.getThreadManager();
for (TraceThread thread : manager.getAllThreads()) { threadTableModel.addAllItems(manager.getAllThreads());
threadMap.computeIfAbsent(thread, t -> {
ThreadRow tr = new ThreadRow(modelService, t);
threadTableModel.add(tr);
return tr;
});
}
updateTimelineMax(); updateTimelineMax();
} }

View file

@ -0,0 +1,27 @@
/* ###
* 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.trace.model;
import ghidra.util.database.ObjectKey;
public interface TraceObject {
/**
* Get an opaque unique id for this object, whose hash is immutable
*
* @return the opaque object id
*/
ObjectKey getObjectKey();
}

View file

@ -23,29 +23,22 @@ import com.google.common.collect.Range;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceObject;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.util.database.ObjectKey;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
* A breakpoint in a trace * A breakpoint in a trace
*/ */
public interface TraceBreakpoint { public interface TraceBreakpoint extends TraceObject {
/** /**
* Get the trace containning this breakpoint * Get the trace containing this breakpoint
* *
* @return the trace * @return the trace
*/ */
Trace getTrace(); Trace getTrace();
/**
* Get an opaque unique id for this object, whose hash is immutable
*
* @return the opaque object id
*/
ObjectKey getObjectKey();
/** /**
* Get the "full name" of this breakpoint * Get the "full name" of this breakpoint
* *

View file

@ -21,12 +21,13 @@ import com.google.common.collect.Range;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceObject;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
* A region of mapped target memory in a trace * A region of mapped target memory in a trace
*/ */
public interface TraceMemoryRegion { public interface TraceMemoryRegion extends TraceObject {
/** /**
* Get the trace containing this region * Get the trace containing this region
@ -105,7 +106,8 @@ public interface TraceMemoryRegion {
/** /**
* @see #setLifespan(Range) * @see #setLifespan(Range)
* *
* @param destructionSnap the destruction snap, or {@link Long#MAX_VALUE} for "to the end of time" * @param destructionSnap the destruction snap, or {@link Long#MAX_VALUE} for "to the end of
* time"
*/ */
void setDestructionSnap(long destructionSnap) void setDestructionSnap(long destructionSnap)
throws DuplicateNameException, TraceOverlappedRegionException; throws DuplicateNameException, TraceOverlappedRegionException;

View file

@ -21,6 +21,7 @@ import com.google.common.collect.Range;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceObject;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
@ -29,7 +30,7 @@ import ghidra.util.exception.DuplicateNameException;
* <p> * <p>
* This also serves as a namespace for storing the module's sections. * This also serves as a namespace for storing the module's sections.
*/ */
public interface TraceModule { public interface TraceModule extends TraceObject {
/** /**
* Get the trace containing this module * Get the trace containing this module

View file

@ -18,12 +18,13 @@ package ghidra.trace.model.modules;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceObject;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
* A section of a module in a trace * A section of a module in a trace
*/ */
public interface TraceSection { public interface TraceSection extends TraceObject {
/** /**
* Get the trace containing this section * Get the trace containing this section

View file

@ -23,11 +23,12 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceObject;
/** /**
* A mapped range from this trace to a Ghidra {@link Program} * A mapped range from this trace to a Ghidra {@link Program}
*/ */
public interface TraceStaticMapping { public interface TraceStaticMapping extends TraceObject {
/** /**
* Get the "from" trace, i.e., the trace containing this mapping * Get the "from" trace, i.e., the trace containing this mapping

View file

@ -21,12 +21,13 @@ import com.google.common.collect.Range;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceObject;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
* A thread in a trace * A thread in a trace
*/ */
public interface TraceThread { public interface TraceThread extends TraceObject {
/** /**
* Get the trace containing this thread * Get the trace containing this thread

View file

@ -213,11 +213,6 @@ public class DefaultEnumeratedColumnTableModel<C extends Enum<C> & EnumeratedTab
fireTableRowsInserted(startIndex, endIndex); fireTableRowsInserted(startIndex, endIndex);
} }
@Override
public RowIterator<R> rowIterator() {
return new TableRowIterator();
}
@Override @Override
public void notifyUpdated(R row) { public void notifyUpdated(R row) {
int rowIndex = modelData.indexOf(row); int rowIndex = modelData.indexOf(row);

View file

@ -27,8 +27,6 @@ public interface EnumeratedColumnTableModel<R> extends RowObjectTableModel<R> {
void addAll(Collection<R> c); void addAll(Collection<R> c);
ListIterator<R> rowIterator();
void notifyUpdated(R row); void notifyUpdated(R row);
List<R> notifyUpdatedWith(Predicate<R> predicate); List<R> notifyUpdatedWith(Predicate<R> predicate);

View file

@ -55,6 +55,10 @@ public class RowWrappedEnumeratedColumnTableModel<C extends Enum<C> & Enumerated
return c.stream().map(this::rowFor).collect(Collectors.toList()); return c.stream().map(this::rowFor).collect(Collectors.toList());
} }
public synchronized R getRow(T t) {
return map.get(keyFunc.apply(t));
}
public void addItem(T t) { public void addItem(T t) {
add(rowFor(t)); add(rowFor(t));
} }
@ -83,4 +87,10 @@ public class RowWrappedEnumeratedColumnTableModel<C extends Enum<C> & Enumerated
public synchronized Map<K, R> getMap() { public synchronized Map<K, R> getMap() {
return Map.copyOf(map); return Map.copyOf(map);
} }
@Override
public synchronized void clear() {
map.clear();
super.clear();
}
} }