diff --git a/Ghidra/Debug/Debugger/certification.manifest b/Ghidra/Debug/Debugger/certification.manifest
index 223beae5a3..71dd99cbf3 100644
--- a/Ghidra/Debug/Debugger/certification.manifest
+++ b/Ghidra/Debug/Debugger/certification.manifest
@@ -6,6 +6,7 @@
##MODULE IP: Tango Icons - Public Domain
Module.manifest||GHIDRA||||END|
data/ExtensionPoint.manifest||GHIDRA||||END|
+data/debugger.theme.properties||GHIDRA||||END|
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
src/main/help/help/shared/arrow.gif||GHIDRA||||END|
src/main/help/help/shared/close16.gif||GHIDRA||||END|
diff --git a/Ghidra/Debug/Debugger/data/debugger.theme.properties b/Ghidra/Debug/Debugger/data/debugger.theme.properties
new file mode 100644
index 0000000000..63729a015e
--- /dev/null
+++ b/Ghidra/Debug/Debugger/data/debugger.theme.properties
@@ -0,0 +1,199 @@
+[Defaults]
+
+color.bg.debugger.diff.marker = moccasin
+
+color.bg.debugger.listing.blended = color.bg
+color.bg.debugger.memory.state = color.bg
+
+color.debugger.plugin.plugin.memview.arrow = red
+color.debugger.plugin.memview.box = blue
+color.debugger.plugin.memview.box.type.instructions = rgb(128, 000, 000)
+color.debugger.plugin.memview.box.type.process = rgb(200, 200, 255)
+color.debugger.plugin.memview.box.type.thread = rgb(200, 255, 255)
+color.debugger.plugin.memview.box.type.module = lime
+color.debugger.plugin.memview.box.type.region = yellow
+color.debugger.plugin.memview.box.type.image = magenta
+color.debugger.plugin.memview.box.type.virtual.alloc = lightgray
+color.debugger.plugin.memview.box.type.heap.create = blue
+color.debugger.plugin.memview.box.type.heap.alloc = rgb(000, 100, 050)
+color.debugger.plugin.memview.box.type.pool = rgb(100, 000, 150)
+color.debugger.plugin.memview.box.type.stack = cyan
+color.debugger.plugin.memview.box.type.perfinfo = lightgray
+color.debugger.plugin.memview.box.type.read.memory = darkgray
+color.debugger.plugin.memview.box.type.write.memory = blue
+color.debugger.plugin.memview.box.type.breakpoint = red
+
+
+color.bg.debugger.plugin.objects.default = color.bg
+color.fg.debugger.plugin.objects.default = color.fg
+color.fg.debugger.plugin.objects.invisible = lightgray
+color.fg.debugger.plugin.objects.invalidated = lightgray
+color.fg.debugger.plugin.objects.modified = red
+color.fg.debugger.plugin.objects.subscribed = black
+color.fg.debugger.plugin.objects.error = color.fg.error
+color.fg.debugger.plugin.objects.intrinsic = blue
+color.fg.debugger.plugin.objects.target = magenta
+color.fg.debugger.plugin.objects.accessor = lightgray
+color.fg.debugger.plugin.objects.link = green
+
+color.bg.debugger.plugin.resources.stale = lightgray
+color.bg.debugger.plugin.resources.error = lightpink
+
+color.debugger.plugin.resources.register.marker = lightcoral
+color.debugger.plugin.resources.register.stale = gray
+color.debugger.plugin.resources.register.stale.selected = lightgray
+color.debugger.plugin.resources.register.changed = red
+color.debugger.plugin.resources.register.changed.selected = lightcoral
+
+color.debugger.plugin.resources.watch.stale = gray
+color.debugger.plugin.resources.watch.stale.selected = lightgray
+color.debugger.plugin.resources.watch.changed = red
+color.debugger.plugin.resources.watch.changed.selected = lightcoral
+
+color.debugger.plugin.resources.value.changed = red
+color.debugger.plugin.resources.value.changed.selected = lightcoral
+
+color.debugger.plugin.resources.pcode.counter = lightgreen
+
+color.debugger.plugin.resources.breakpoint.marker.enabled = lightsteelblue
+color.debugger.plugin.resources.breakpoint.marker.disabled = color.debugger.plugin.resources.breakpoint.marker.enabled
+color.debugger.plugin.resources.breakpoint.marker.enabled.ineffective = silver
+color.debugger.plugin.resources.breakpoint.marker.disabled.ineffective = color.debugger.plugin.resources.breakpoint.marker.enabled.ineffective
+
+icon.debugger.object.populated = object-populated.png
+icon.debugger.object.unpopulated = object-unpopulated.png
+
+font.debugger.object.tree.renderer = Tahoma-plain-11
+
+icon.debugger.display.graph = breakpoint-enable.png // TODO this icon was missing 'breakpoints.png'
+icon.debugger.display.graph.filtered = icon.debugger.display.graph
+icon.debugger.display.xml = text-xml.png
+icon.debugger.display.xml.filtered = icon.debugger.display.xml
+icon.debugger.display.export.facts = closedFolder.png
+icon.debugger.display.export.xml = text-xml.png
+icon.debugger.display.import.facts = closedFolder.png
+icon.debugger.display.import.xml = text-xml.png
+icon.debugger.open.windbg.trace = text-xml.png
+
+icon.debugger.node.object.empty = icon.debugger.object.unpopulated
+icon.debugger.node.object.event = register-marker.png
+icon.debugger.node.object.populated = icon.debugger.object.populated
+icon.debugger.node.object.running = object-running.png
+icon.debugger.node.object.terminated = object-terminated.png
+
+icon.debugger.table.object = icon.table
+icon.debugger.tree.object = icon.debugger.object.unpopulated
+
+icon.debugger = debugger.png
+icon.debugger.connect = connect.png
+icon.debugger.disconnect = disconnect.png
+icon.debugger.process = process.png
+icon.debugger.thread = thread.png
+icon.debugger.processor = memory16.gif // TODO this icon was missing 'kcmprocessor.png'
+icon.debugger.launch = launch.png
+icon.debugger.attach = attach.png
+icon.debugger.resume = resume.png
+icon.debugger.interrupt = interrupt.png
+icon.debugger.kill = kill.png
+icon.debugger.detach = detach.png
+icon.debugger.record = record.png
+icon.debugger.step.into = stepinto.png
+icon.debugger.step.over = stepover.png
+icon.debugger.step.back = stepback.png
+icon.debugger.step.finish = stepout.png
+icon.debugger.step.last = steplast.png
+icon.debugger.skip.over = skipover.png
+icon.debugger.snap.forward = 2rightarrow.png
+icon.debugger.snap.backward = 2leftarrow.png
+icon.debugger.seek.present = seek-present.png
+
+icon.debugger.breakpoint.set = breakpoint-enable.png
+icon.debugger.breakpoint.clear = breakpoint-clear.png
+icon.debugger.breakpoint.enable = breakpoint-enable.png
+icon.debugger.breakpoint.enable.all = breakpoints-enable-all.png
+icon.debugger.breakpoint.disable = breakpoint-disable.png
+icon.debugger.breakpoint.disable.all = breakpoints-disable-all.png
+icon.debugger.breakpoint.clear.all = breakpoints-clear-all.png
+icon.debugger.breakpoint.make.effective = breakpoints-make-effective.png
+
+icon.debugger.provider.listing = Browser.gif
+icon.debugger.provider.memory.bytes = binaryData.gif
+icon.debugger.provider.console = console.png
+icon.debugger.provider.registers = registers.png
+icon.debugger.provider.stack = stack.png
+icon.debugger.provider.breakpoints = breakpoint-mixed.png
+icon.debugger.provider.modules = modules.png
+icon.debugger.provider.pcode = stepinto.png
+icon.debugger.provider.regions = memory16.gif
+icon.debugger.provider.time = time.png
+icon.debugger.provider.objects = icon.debugger.object.populated
+icon.debugger.provider.model = function_graph.png
+
+icon.debugger.save = icon.save
+icon.debugger.close = x.gif
+icon.debugger.add = add.png
+icon.debugger.delete = delete.png
+icon.debugger.clear = erase16.png
+icon.debugger.refresh = view-refresh.png
+icon.debugger.filter = filter_off.png
+icon.debugger.select.rows = table_go.png
+icon.debugger.autoread = autoread.png
+
+
+icon.debugger.refresh.memory = icon.debugger.refresh
+icon.debugger.rename.snapshot = icon.debugger.provider.time
+icon.debugger.map.identically = doubleArrow.png
+icon.debugger.map.modules = modules.png
+icon.debugger.map.sections = icon.debugger.map.modules
+icon.debugger.map.regions = icon.debugger.map.modules
+icon.debugger.block = icon.debugger.map.sections
+icon.debugger.select.addresses = text_align_justify.png
+icon.debugger.data.types = dataTypes.png
+icon.debugger.capture.symbols = closedFolderLabels.png
+icon.debugger.log.fatal = edit-bomb.png
+icon.debugger.log.error = dialog-warning_red.png
+icon.debugger.log.warn = dialog-warning.png
+icon.debugger.sync = sync_enabled.png
+icon.debugger.visibility = format-text-bold.png
+icon.debugger.pin = pin.png
+icon.debugger.import = imported_bookmark.gif
+icon.debugger.blank = blank.png
+icon.debugger.package = debugger32.png
+icon.debugger.emulate = icon.debugger.process
+icon.debugger.config = conf.png
+icon.debugger.toggle = system-switch-user.png
+
+icon.debugger.diff = table_relationship.png
+icon.debugger.diff.previous = up.png
+icon.debugger.diff.next = down.png
+
+icon.debugger.edit.mode.read.only = write-disabled.png
+icon.debugger.edit.mode.write.target = write-target.png
+icon.debugger.edit.mode.write.trace = write-trace.png
+icon.debugger.edit.mode.write.emulator = write-emulator.png
+
+icon.debugger.marker.register = register-marker.png
+icon.debugger.marker.event = icon.debugger.marker.register
+
+icon.debugger.breakpoint.overlay.inconsistent = breakpoint-overlay-inconsistent.png
+icon.debugger.breakpoint.marker.enabled = icon.debugger.breakpoint.enable
+icon.debugger.breakpoint.marker.disabled = icon.debugger.breakpoint.disable
+icon.debugger.breakpoint.marker.mixed = breakpoint-mixed.png
+icon.debugger.breakpoint.marker.ineffective.enabled = breakpoint-enable-ineff.png
+icon.debugger.breakpoint.marker.ineffective.disabled = breakpoint-disable-ineff.png
+icon.debugger.breakpoint.marker.ineffective.mixed = breakpoint-mixed-ineff.png
+
+icon.debugger.unique.ref.read = cursor_arrow.gif [rotate(180)]
+icon.debugger.unique.ref.write = cursor_arrow.gif
+
+icon.debugger.select.registers = select-registers.png
+icon.debugger.enable.edits = editbytes.gif
+icon.debugger.disassemble = editbytes.gif // TODO this icon was missing 'disassemble.png'
+
+
+
+[Dark Defaults]
+
+
+
+
diff --git a/Ghidra/Debug/Debugger/src/main/help/help/shared/Frontpage.css b/Ghidra/Debug/Debugger/src/main/help/help/shared/Frontpage.css
index c8616e85e8..ff855bae04 100644
--- a/Ghidra/Debug/Debugger/src/main/help/help/shared/Frontpage.css
+++ b/Ghidra/Debug/Debugger/src/main/help/help/shared/Frontpage.css
@@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
-h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
+h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java
index 3db1d4c8ed..bbd5f24881 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java
@@ -30,6 +30,8 @@ import docking.action.ToggleDockingAction;
import docking.action.builder.*;
import docking.widgets.table.*;
import docking.widgets.tree.GTreeNode;
+import generic.theme.GColor;
+import generic.theme.GIcon;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
import ghidra.app.plugin.core.debug.gui.breakpoint.DebuggerBreakpointsPlugin;
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsolePlugin;
@@ -54,131 +56,129 @@ import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.util.PluginUtils;
import ghidra.program.database.ProgramContentHandler;
import ghidra.trace.model.Trace;
-import ghidra.util.*;
+import ghidra.util.HelpLocation;
+import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import resources.MultiIcon;
-import resources.ResourceManager;
-import resources.icons.RotateIcon;
public interface DebuggerResources {
String OPTIONS_CATEGORY_DEBUGGER = "Debugger";
String OPTIONS_CATEGORY_WORKFLOW = "Workflow";
- ImageIcon ICON_DEBUGGER = ResourceManager.loadImage("images/debugger.png");
+ Icon ICON_DEBUGGER = new GIcon("icon.debugger");
- ImageIcon ICON_CONNECTION = ResourceManager.loadImage("images/connect.png");
- ImageIcon ICON_DISCONNECT = ResourceManager.loadImage("images/disconnect.png");
+ Icon ICON_CONNECTION = new GIcon("icon.debugger.connect");
+ Icon ICON_DISCONNECT = new GIcon("icon.debugger.disconnect");
- ImageIcon ICON_PROCESS = ResourceManager.loadImage("images/process.png");
- ImageIcon ICON_TRACE = Trace.TRACE_ICON;
- ImageIcon ICON_THREAD = ResourceManager.loadImage("images/thread.png");
- ImageIcon ICON_PROGRAM = ProgramContentHandler.PROGRAM_ICON;
- ImageIcon ICON_PROCESSOR = ResourceManager.loadImage("images/kcmprocessor.png");
+ Icon ICON_PROCESS = new GIcon("icon.debugger.process");
+ Icon ICON_TRACE = Trace.TRACE_ICON;
+ Icon ICON_THREAD = new GIcon("icon.debugger.thread");
+ Icon ICON_PROGRAM = ProgramContentHandler.PROGRAM_ICON;
+ Icon ICON_PROCESSOR = new GIcon("icon.debugger.processor");
- ImageIcon ICON_LAUNCH = ResourceManager.loadImage("images/launch.png");
- ImageIcon ICON_ATTACH = ResourceManager.loadImage("images/attach.png");
- ImageIcon ICON_RESUME = ResourceManager.loadImage("images/resume.png");
- ImageIcon ICON_INTERRUPT = ResourceManager.loadImage("images/interrupt.png");
- ImageIcon ICON_KILL = ResourceManager.loadImage("images/kill.png");
- ImageIcon ICON_DETACH = ResourceManager.loadImage("images/detach.png");
- ImageIcon ICON_RECORD = ResourceManager.loadImage("images/record.png");
+ Icon ICON_LAUNCH = new GIcon("icon.debugger.launch");
+ Icon ICON_ATTACH = new GIcon("icon.debugger.attach");
+ Icon ICON_RESUME = new GIcon("icon.debugger.resume");
+ Icon ICON_INTERRUPT = new GIcon("icon.debugger.interrupt");
+ Icon ICON_KILL = new GIcon("icon.debugger.kill");
+ Icon ICON_DETACH = new GIcon("icon.debugger.detach");
+ Icon ICON_RECORD = new GIcon("icon.debugger.record");
- ImageIcon ICON_STEP_INTO = ResourceManager.loadImage("images/stepinto.png");
- ImageIcon ICON_STEP_OVER = ResourceManager.loadImage("images/stepover.png");
- ImageIcon ICON_SKIP_OVER = ResourceManager.loadImage("images/skipover.png");
- ImageIcon ICON_STEP_FINISH = ResourceManager.loadImage("images/stepout.png");
- ImageIcon ICON_STEP_BACK = ResourceManager.loadImage("images/stepback.png");
- ImageIcon ICON_STEP_LAST = ResourceManager.loadImage("images/steplast.png");
- // TODO: Draw new icons?
- ImageIcon ICON_SNAP_FORWARD = ResourceManager.loadImage("images/2rightarrow.png");
- ImageIcon ICON_SNAP_BACKWARD = ResourceManager.loadImage("images/2leftarrow.png");
- ImageIcon ICON_SEEK_PRESENT = ResourceManager.loadImage("images/seek-present.png");
+ Icon ICON_STEP_INTO = new GIcon("icon.debugger.step.into");
+ Icon ICON_STEP_OVER = new GIcon("icon.debugger.step.over");
+ Icon ICON_SKIP_OVER = new GIcon("icon.debugger.step.back");
+ Icon ICON_STEP_FINISH = new GIcon("icon.debugger.step.finish");
+ Icon ICON_STEP_BACK = new GIcon("icon.debugger.skip.over");
+ Icon ICON_STEP_LAST = new GIcon("icon.debugger.step.last");
- ImageIcon ICON_SET_BREAKPOINT = ResourceManager.loadImage("images/breakpoint-enable.png");
- ImageIcon ICON_CLEAR_BREAKPOINT = ResourceManager.loadImage("images/breakpoint-clear.png");
- ImageIcon ICON_ENABLE_BREAKPOINT = ResourceManager.loadImage("images/breakpoint-enable.png");
- ImageIcon ICON_ENABLE_ALL_BREAKPOINTS =
- ResourceManager.loadImage("images/breakpoints-enable-all.png");
- ImageIcon ICON_DISABLE_BREAKPOINT = ResourceManager.loadImage("images/breakpoint-disable.png");
- ImageIcon ICON_DISABLE_ALL_BREAKPOINTS =
- ResourceManager.loadImage("images/breakpoints-disable-all.png");
- ImageIcon ICON_CLEAR_ALL_BREAKPOINTS =
- ResourceManager.loadImage("images/breakpoints-clear-all.png");
- ImageIcon ICON_MAKE_BREAKPOINTS_EFFECTIVE =
- ResourceManager.loadImage("images/breakpoints-make-effective.png");
+ Icon ICON_SNAP_FORWARD = new GIcon("icon.debugger.snap.forward");
+ Icon ICON_SNAP_BACKWARD = new GIcon("icon.debugger.snap.backward");
+ Icon ICON_SEEK_PRESENT = new GIcon("icon.debugger.seek.present");
+
+ Icon ICON_SET_BREAKPOINT = new GIcon("icon.debugger.breakpoint.set");
+ Icon ICON_CLEAR_BREAKPOINT = new GIcon("icon.debugger.breakpoint.clear");
+ Icon ICON_ENABLE_BREAKPOINT = new GIcon("icon.debugger.breakpoint.enable");
+ Icon ICON_ENABLE_ALL_BREAKPOINTS =
+ new GIcon("icon.debugger.breakpoint.enable.all");
+ Icon ICON_DISABLE_BREAKPOINT = new GIcon("icon.debugger.breakpoint.disable");
+ Icon ICON_DISABLE_ALL_BREAKPOINTS =
+ new GIcon("icon.debugger.breakpoint.disable.all");
+ Icon ICON_CLEAR_ALL_BREAKPOINTS =
+ new GIcon("icon.debugger.breakpoint.clear.all");
+ Icon ICON_MAKE_BREAKPOINTS_EFFECTIVE =
+ new GIcon("icon.debugger.breakpoint.make.effective");
// TODO: Some overlay to indicate dynamic, or new icon altogether
- ImageIcon ICON_LISTING = ResourceManager.loadImage("images/Browser.gif");
- ImageIcon ICON_MEMORY_BYTES = ResourceManager.loadImage("images/binaryData.gif");
- ImageIcon ICON_CONSOLE = ResourceManager.loadImage("images/console.png");
- ImageIcon ICON_REGISTERS = ResourceManager.loadImage("images/registers.png");
- ImageIcon ICON_STACK = ResourceManager.loadImage("images/stack.png");
- ImageIcon ICON_BREAKPOINTS = ResourceManager.loadImage("images/breakpoint-mixed.png");
- ImageIcon ICON_MODULES = ResourceManager.loadImage("images/modules.png");
- ImageIcon ICON_MAPPINGS = ICON_PROGRAM; // TODO: A better icon
- ImageIcon ICON_PCODE = ResourceManager.loadImage("images/stepinto.png"); // TODO
- //ResourceManager.loadImage("images/mappings.png");
- ImageIcon ICON_REGIONS = ResourceManager.loadImage("images/memory16.gif");
- ImageIcon ICON_TIME = ResourceManager.loadImage("images/time.png");
+ Icon ICON_LISTING = new GIcon("icon.debugger.provider.listing");
+ Icon ICON_MEMORY_BYTES = new GIcon("icon.debugger.provider.memory.bytes");
+ Icon ICON_CONSOLE = new GIcon("icon.debugger.provider.console");
+ Icon ICON_REGISTERS = new GIcon("icon.debugger.provider.registers");
+ Icon ICON_STACK = new GIcon("icon.debugger.provider.stack");
+ Icon ICON_BREAKPOINTS = new GIcon("icon.debugger.provider.breakpoints");
+ Icon ICON_MODULES = new GIcon("icon.debugger.provider.modules");
+ Icon ICON_MAPPINGS = ICON_PROGRAM; // TODO: A better icon
+ Icon ICON_PCODE = new GIcon("icon.debugger.provider.pcode"); // TODO
+ Icon ICON_REGIONS = new GIcon("icon.debugger.provider.regions");
+ Icon ICON_TIME = new GIcon("icon.debugger.provider.time");
// TODO: Draw a real icon. object-populated duplicates breakpoint-enabled
- ImageIcon ICON_OBJECTS = ResourceManager.loadImage("images/object-populated.png");
+ Icon ICON_OBJECTS = new GIcon("icon.debugger.provider.objects");
- ImageIcon ICON_SAVE = ResourceManager.loadImage("images/disk.png");
- ImageIcon ICON_CLOSE = ResourceManager.loadImage("images/x.gif");
- ImageIcon ICON_ADD = ResourceManager.loadImage("images/add.png");
- ImageIcon ICON_DELETE = ResourceManager.loadImage("images/delete.png");
- ImageIcon ICON_CLEAR = ResourceManager.loadImage("images/erase16.png");
- ImageIcon ICON_REFRESH = ResourceManager.loadImage("images/view-refresh.png");
- ImageIcon ICON_FILTER = ResourceManager.loadImage("images/filter_off.png"); // Eww.
- ImageIcon ICON_SELECT_ROWS = ResourceManager.loadImage("images/table_go.png");
- ImageIcon ICON_AUTOREAD = ResourceManager.loadImage("images/autoread.png");
+ Icon ICON_SAVE = new GIcon("icon.debugger.save");
+ Icon ICON_CLOSE = new GIcon("icon.debugger.close");
+ Icon ICON_ADD = new GIcon("icon.debugger.add");
+ Icon ICON_DELETE = new GIcon("icon.debugger.delete");
+ Icon ICON_CLEAR = new GIcon("icon.debugger.clear");
+ Icon ICON_REFRESH = new GIcon("icon.debugger.refresh");
+ Icon ICON_FILTER = new GIcon("icon.debugger.filter"); // Eww.
+ Icon ICON_SELECT_ROWS = new GIcon("icon.debugger.select.rows");
+ Icon ICON_AUTOREAD = new GIcon("icon.debugger.autoread");
- ImageIcon ICON_OBJECT_POPULATED = ResourceManager.loadImage("images/object-populated.png");
- ImageIcon ICON_OBJECT_UNPOPULATED = ResourceManager.loadImage("images/object-unpopulated.png");
+ Icon ICON_OBJECT_POPULATED = new GIcon("icon.debugger.object.populated");
+ Icon ICON_OBJECT_UNPOPULATED = new GIcon("icon.debugger.object.unpopulated");
// TODO: Draw a real icon.
- ImageIcon ICON_REFRESH_MEMORY = ICON_REFRESH;
+ Icon ICON_REFRESH_MEMORY = new GIcon("icon.debugger.refresh.memory");
- ImageIcon ICON_RENAME_SNAPSHOT = ICON_TIME;
+ Icon ICON_RENAME_SNAPSHOT = new GIcon("icon.debugger.rename.snapshot");
// TODO: Draw an icon
- ImageIcon ICON_MAP_IDENTICALLY = ResourceManager.loadImage("images/doubleArrow.png");
- ImageIcon ICON_MAP_MODULES = ResourceManager.loadImage("images/modules.png");
- ImageIcon ICON_MAP_SECTIONS = ICON_MAP_MODULES; // TODO
- ImageIcon ICON_MAP_REGIONS = ICON_MAP_MODULES; // TODO
- ImageIcon ICON_BLOCK = ICON_MAP_SECTIONS; // TODO
+ Icon ICON_MAP_IDENTICALLY = new GIcon("icon.debugger.map.identically");
+ Icon ICON_MAP_MODULES = new GIcon("icon.debugger.map.modules");
+ Icon ICON_MAP_SECTIONS = new GIcon("icon.debugger.map.sections"); // TODO
+ Icon ICON_MAP_REGIONS = new GIcon("icon.debugger.map.regions"); // TODO
+ Icon ICON_BLOCK = new GIcon("icon.debugger.block"); // TODO
// TODO: Draw an icon
- ImageIcon ICON_SELECT_ADDRESSES = ResourceManager.loadImage("images/text_align_justify.png");
+ Icon ICON_SELECT_ADDRESSES = new GIcon("icon.debugger.select.addresses");
// TODO: Draw an icon?
- ImageIcon ICON_DATA_TYPES = ResourceManager.loadImage("images/dataTypes.png");
+ Icon ICON_DATA_TYPES = new GIcon("icon.debugger.data.types");
// TODO: Draw an icon?
- ImageIcon ICON_CAPTURE_SYMBOLS = ResourceManager.loadImage("images/closedFolderLabels.png");
+ Icon ICON_CAPTURE_SYMBOLS = new GIcon("icon.debugger.capture.symbols");
- ImageIcon ICON_LOG_FATAL = ResourceManager.loadImage("images/edit-bomb.png");
- ImageIcon ICON_LOG_ERROR = ResourceManager.loadImage("images/dialog-warning_red.png");
- ImageIcon ICON_LOG_WARN = ResourceManager.loadImage("images/dialog-warning.png");
+ Icon ICON_LOG_FATAL = new GIcon("icon.debugger.log.fatal");
+ Icon ICON_LOG_ERROR = new GIcon("icon.debugger.log.error");
+ Icon ICON_LOG_WARN = new GIcon("icon.debugger.log.warn");
- ImageIcon ICON_SYNC = ResourceManager.loadImage("images/sync_enabled.png");
- ImageIcon ICON_VISIBILITY = ResourceManager.loadImage("images/format-text-bold.png");
+ Icon ICON_SYNC = new GIcon("icon.debugger.sync");
+ Icon ICON_VISIBILITY = new GIcon("icon.debugger.visibility");
- ImageIcon ICON_PIN = ResourceManager.loadImage("images/pin.png");
+ Icon ICON_PIN = new GIcon("icon.debugger.pin");
// TODO: Find better icon?
- ImageIcon ICON_IMPORT = ResourceManager.loadImage("images/imported_bookmark.gif");
- ImageIcon ICON_BLANK = ResourceManager.loadImage("images/blank.png");
- ImageIcon ICON_PACKAGE = ResourceManager.loadImage("images/debugger32.png");
- ImageIcon ICON_EMULATE = ICON_PROCESS; // TODO
- ImageIcon ICON_CONFIG = ResourceManager.loadImage("images/conf.png");
- ImageIcon ICON_TOGGLE = ResourceManager.loadImage("images/system-switch-user.png");
+ Icon ICON_IMPORT = new GIcon("icon.debugger.import");
+ Icon ICON_BLANK = new GIcon("icon.debugger.blank");
+ Icon ICON_PACKAGE = new GIcon("icon.debugger.package");
+ Icon ICON_EMULATE = new GIcon("icon.debugger.emulate"); // TODO
+ Icon ICON_CONFIG = new GIcon("icon.debugger.config");
+ Icon ICON_TOGGLE = new GIcon("icon.debugger.toggle");
- ImageIcon ICON_DIFF = ResourceManager.loadImage("images/table_relationship.png");
- ImageIcon ICON_DIFF_PREV = ResourceManager.loadImage("images/up.png");
- ImageIcon ICON_DIFF_NEXT = ResourceManager.loadImage("images/down.png");
+ Icon ICON_DIFF = new GIcon("icon.debugger.diff");
+ Icon ICON_DIFF_PREV = new GIcon("icon.debugger.diff.previous");
+ Icon ICON_DIFF_NEXT = new GIcon("icon.debugger.diff.next");
- ImageIcon ICON_EDIT_MODE_READ_ONLY = ResourceManager.loadImage("images/write-disabled.png");
- ImageIcon ICON_EDIT_MODE_WRITE_TARGET = ResourceManager.loadImage("images/write-target.png");
- ImageIcon ICON_EDIT_MODE_WRITE_TRACE = ResourceManager.loadImage("images/write-trace.png");
- ImageIcon ICON_EDIT_MODE_WRITE_EMULATOR =
- ResourceManager.loadImage("images/write-emulator.png");
+ Icon ICON_EDIT_MODE_READ_ONLY = new GIcon("icon.debugger.edit.mode.read.only");
+ Icon ICON_EDIT_MODE_WRITE_TARGET = new GIcon("icon.debugger.edit.mode.write.target");
+ Icon ICON_EDIT_MODE_WRITE_TRACE = new GIcon("icon.debugger.edit.mode.write.trace");
+ Icon ICON_EDIT_MODE_WRITE_EMULATOR =
+ new GIcon("icon.debugger.edit.mode.write.emulator");
String NAME_EDIT_MODE_READ_ONLY = "Control Target w/ Edits Disabled";
String NAME_EDIT_MODE_WRITE_TARGET = "Control Target";
@@ -190,82 +190,82 @@ public interface DebuggerResources {
String HELP_ANCHOR_PLUGIN = "plugin";
String TITLE_PROVIDER_BREAKPOINTS = "Breakpoints";
- ImageIcon ICON_PROVIDER_BREAKPOINTS = ICON_BREAKPOINTS;
+ Icon ICON_PROVIDER_BREAKPOINTS = ICON_BREAKPOINTS;
HelpLocation HELP_PROVIDER_BREAKPOINTS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerBreakpointsPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_CONSOLE = "Debug Console";
- ImageIcon ICON_PROVIDER_CONSOLE = ICON_CONSOLE;
+ Icon ICON_PROVIDER_CONSOLE = ICON_CONSOLE;
HelpLocation HELP_PROVIDER_CONSOLE = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerConsolePlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_LISTING = "Dynamic";
- ImageIcon ICON_PROVIDER_LISTING = ICON_LISTING;
+ Icon ICON_PROVIDER_LISTING = ICON_LISTING;
HelpLocation HELP_PROVIDER_LISTING = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerListingPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_MAPPINGS = "Static Mappings";
- ImageIcon ICON_PROVIDER_MAPPINGS = ICON_MAPPINGS;
+ Icon ICON_PROVIDER_MAPPINGS = ICON_MAPPINGS;
HelpLocation HELP_PROVIDER_MAPPINGS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerStaticMappingPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_MEMORY_BYTES = "Memory";
- ImageIcon ICON_PROVIDER_MEMORY_BYTES = ICON_MEMORY_BYTES;
+ Icon ICON_PROVIDER_MEMORY_BYTES = ICON_MEMORY_BYTES;
HelpLocation HELP_PROVIDER_MEMORY_BYTES = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerMemoryBytesPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_MODULES = "Modules";
- ImageIcon ICON_PROVIDER_MODULES = ICON_MODULES;
+ Icon ICON_PROVIDER_MODULES = ICON_MODULES;
HelpLocation HELP_PROVIDER_MODULES = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerModulesPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_PCODE = "Pcode Stepper";
- ImageIcon ICON_PROVIDER_PCODE = ICON_PCODE;
+ Icon ICON_PROVIDER_PCODE = ICON_PCODE;
HelpLocation HELP_PROVIDER_PCODE = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerPcodeStepperPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_REGIONS = "Regions";
- ImageIcon ICON_PROVIDER_REGIONS = ICON_REGIONS;
+ Icon ICON_PROVIDER_REGIONS = ICON_REGIONS;
HelpLocation HELP_PROVIDER_REGIONS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerRegionsPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_REGISTERS = "Registers";
- ImageIcon ICON_PROVIDER_REGISTERS = ICON_REGISTERS;
+ Icon ICON_PROVIDER_REGISTERS = ICON_REGISTERS;
HelpLocation HELP_PROVIDER_REGISTERS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerRegistersPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_TARGETS = "Debugger Targets";
- ImageIcon ICON_PROVIDER_TARGETS = ICON_CONNECTION; // TODO: Same icon as action
+ Icon ICON_PROVIDER_TARGETS = ICON_CONNECTION; // TODO: Same icon as action
HelpLocation HELP_PROVIDER_TARGETS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerTargetsPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_STACK = "Stack";
- ImageIcon ICON_PROVIDER_STACK = ICON_STACK;
+ Icon ICON_PROVIDER_STACK = ICON_STACK;
HelpLocation HELP_PROVIDER_STACK = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerStackPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_THREADS = "Threads";
- ImageIcon ICON_PROVIDER_THREADS = ICON_DEBUGGER;
+ Icon ICON_PROVIDER_THREADS = ICON_DEBUGGER;
HelpLocation HELP_PROVIDER_THREADS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerThreadsPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_TIME = "Time";
- ImageIcon ICON_PROVIDER_TIME = ICON_TIME;
+ Icon ICON_PROVIDER_TIME = ICON_TIME;
HelpLocation HELP_PROVIDER_TIME = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerTimePlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_OBJECTS = "Objects";
- ImageIcon ICON_PROVIDER_OBJECTS = ResourceManager.loadImage("images/time.png");
+ Icon ICON_PROVIDER_OBJECTS = new GIcon("icon.debugger.provider.objects");
HelpLocation HELP_PROVIDER_OBJECTS = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerObjectsPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_MODEL = "Model"; // TODO: An icon
- ImageIcon ICON_PROVIDER_MODEL = ResourceManager.loadImage("images/function_graph.png");
+ Icon ICON_PROVIDER_MODEL = new GIcon("icon.debugger.provider.model");
HelpLocation HELP_PROVIDER_MODEL = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerModelPlugin.class), HELP_ANCHOR_PLUGIN);
String TITLE_PROVIDER_WATCHES = "Watches";
- ImageIcon ICON_PROVIDER_WATCHES = ICON_AUTOREAD; // TODO: Another icon?
+ Icon ICON_PROVIDER_WATCHES = ICON_AUTOREAD; // TODO: Another icon?
HelpLocation HELP_PROVIDER_WATCHES = new HelpLocation(
PluginUtils.getPluginNameFromClass(DebuggerWatchesPlugin.class), HELP_ANCHOR_PLUGIN);
@@ -274,44 +274,51 @@ public interface DebuggerResources {
String BOOKMARK_CATEGORY_MEMORY_READ_ERROR = "Debugger Memory Read Error";
String OPTION_NAME_COLORS_STALE_MEMORY = "Colors.Stale Memory";
- Color DEFAULT_COLOR_BACKGROUND_STALE = Color.LIGHT_GRAY;
+ Color DEFAULT_COLOR_BACKGROUND_STALE = new GColor("color.bg.debugger.plugin.resources.stale");
String OPTION_NAME_COLORS_ERROR_MEMORY = "Colors.Error Memory";
- Color DEFAULT_COLOR_BACKGROUND_ERROR = new Color(1.0f, 0.75f, 0.75f);
+ Color DEFAULT_COLOR_BACKGROUND_ERROR = new GColor("color.bg.debugger.plugin.resources.error");
int PRIORITY_REGISTER_MARKER = 10;
String OPTION_NAME_COLORS_TRACKING_MARKERS = "Colors.Tracking Markers";
- Color DEFAULT_COLOR_REGISTER_MARKERS = new Color(0.75f, 0.875f, 0.75f);
- ImageIcon ICON_REGISTER_MARKER = ResourceManager.loadImage("images/register-marker.png");
+ Color DEFAULT_COLOR_REGISTER_MARKERS =
+ new GColor("color.debugger.plugin.resources.register.marker");
+ Icon ICON_REGISTER_MARKER = new GIcon("icon.debugger.marker.register");
- ImageIcon ICON_EVENT_MARKER = ICON_REGISTER_MARKER; // TODO: Another icon?
+ Icon ICON_EVENT_MARKER = new GIcon("icon.debugger.marker.event"); // TODO: Another icon?
// At least rename to "marker-arrow", and then have both ref it.
+ //@formatter:off
String OPTION_NAME_COLORS_REGISTER_STALE = "Colors.Stale Registers";
- Color DEFAULT_COLOR_REGISTER_STALE = Color.GRAY;
+ Color DEFAULT_COLOR_REGISTER_STALE = new GColor("color.debugger.plugin.resources.register.stale");
String OPTION_NAME_COLORS_REGISTER_STALE_SEL = "Colors.Stale Registers (selected)";
- Color DEFAULT_COLOR_REGISTER_STALE_SEL = Color.LIGHT_GRAY;
+ Color DEFAULT_COLOR_REGISTER_STALE_SEL = new GColor("color.debugger.plugin.resources.register.stale.selected");
String OPTION_NAME_COLORS_REGISTER_CHANGED = "Colors.Changed Registers";
- Color DEFAULT_COLOR_REGISTER_CHANGED = Color.RED;
+ Color DEFAULT_COLOR_REGISTER_CHANGED = new GColor("color.debugger.plugin.resources.register.changed");
String OPTION_NAME_COLORS_REGISTER_CHANGED_SEL = "Colors.Changed Registers (selected)";
- Color DEFAULT_COLOR_REGISTER_CHANGED_SEL = ColorUtils.blend(Color.RED, Color.WHITE, 0.5f);
+ Color DEFAULT_COLOR_REGISTER_CHANGED_SEL = new GColor("color.debugger.plugin.resources.register.changed.selected");
+ //@formatter:on
+ //@formatter:off
String OPTION_NAME_COLORS_WATCH_STALE = "Colors.Stale Watches";
- Color DEFAULT_COLOR_WATCH_STALE = Color.GRAY;
+ Color DEFAULT_COLOR_WATCH_STALE = new GColor("color.debugger.plugin.resources.watch.stale");
String OPTION_NAME_COLORS_WATCH_STALE_SEL = "Colors.Stale Watches (selected)";
- Color DEFAULT_COLOR_WATCH_STALE_SEL = Color.LIGHT_GRAY;
+ Color DEFAULT_COLOR_WATCH_STALE_SEL = new GColor("color.debugger.plugin.resources.watch.stale.selected");
String OPTION_NAME_COLORS_WATCH_CHANGED = "Colors.Changed Watches";
- Color DEFAULT_COLOR_WATCH_CHANGED = Color.RED;
+ Color DEFAULT_COLOR_WATCH_CHANGED = new GColor("color.debugger.plugin.resources.watch.changed");
String OPTION_NAME_COLORS_WATCH_CHANGED_SEL = "Colors.Changed Watches (selected)";
- Color DEFAULT_COLOR_WATCH_CHANGED_SEL = ColorUtils.blend(Color.RED, Color.WHITE, 0.5f);
+ Color DEFAULT_COLOR_WATCH_CHANGED_SEL = new GColor("color.debugger.plugin.resources.watch.changed.selected");
+ //@formatter:on
+ //@formatter:off
String OPTION_NAME_COLORS_VALUE_CHANGED = "Colors.Changed Values";
- Color DEFAULT_COLOR_VALUE_CHANGED = Color.RED;
+ Color DEFAULT_COLOR_VALUE_CHANGED = new GColor("color.debugger.plugin.resources.value.changed");
String OPTION_NAME_COLORS_VALUE_CHANGED_SEL = "Colors.Changed Values (selected)";
- Color DEFAULT_COLOR_VALUE_CHANGED_SEL = ColorUtils.blend(Color.RED, Color.WHITE, 0.5f);
+ Color DEFAULT_COLOR_VALUE_CHANGED_SEL = new GColor("color.debugger.plugin.resources.value.changed.selected");
+ //@formatter:on
String OPTION_NAME_COLORS_PCODE_COUNTER = "Colors.Pcode Counter";
- Color DEFAULT_COLOR_PCODE_COUNTER = new Color(0.75f, 0.875f, 0.75f);
+ Color DEFAULT_COLOR_PCODE_COUNTER = new GColor("color.debugger.plugin.resources.pcode.counter");
String NAME_BREAKPOINT_MARKER_ENABLED = "Enabled Breakpoint";
String NAME_BREAKPOINT_MARKER_DISABLED = "Disabled Breakpoint";
@@ -323,19 +330,19 @@ public interface DebuggerResources {
String NAME_BREAKPOINT_MARKER_INCON_DIS = "Inconsistent Disabled Breakpoint";
String NAME_BREAKPOINT_MARKER_INCON_MIX = "Inconsistent Mixed Breakpoint";
- ImageIcon ICON_BREAKPOINT_OVERLAY_INCONSISTENT =
- ResourceManager.loadImage("images/breakpoint-overlay-inconsistent.png");
- ImageIcon ICON_BREAKPOINT_MARKER_ENABLED = ICON_ENABLE_BREAKPOINT;
- ImageIcon ICON_BREAKPOINT_MARKER_DISABLED = ICON_DISABLE_BREAKPOINT;
- ImageIcon ICON_BREAKPOINT_MARKER_MIXED =
- ResourceManager.loadImage("images/breakpoint-mixed.png");
+ Icon ICON_BREAKPOINT_OVERLAY_INCONSISTENT =
+ new GIcon("icon.debugger.breakpoint.overlay.inconsistent");
+ Icon ICON_BREAKPOINT_MARKER_ENABLED = new GIcon("icon.debugger.breakpoint.marker.enabled");
+ Icon ICON_BREAKPOINT_MARKER_DISABLED = new GIcon("icon.debugger.breakpoint.marker.disabled");
+ Icon ICON_BREAKPOINT_MARKER_MIXED =
+ new GIcon("icon.debugger.breakpoint.marker.mixed");
- ImageIcon ICON_BREAKPOINT_MARKER_INEFF_EN =
- ResourceManager.loadImage("images/breakpoint-enable-ineff.png");
- ImageIcon ICON_BREAKPOINT_MARKER_INEFF_DIS =
- ResourceManager.loadImage("images/breakpoint-disable-ineff.png");
- ImageIcon ICON_BREAKPOINT_MARKER_INEFF_MIX =
- ResourceManager.loadImage("images/breakpoint-mixed-ineff.png");
+ Icon ICON_BREAKPOINT_MARKER_INEFF_EN =
+ new GIcon("icon.debugger.breakpoint.marker.ineffective.enabled");
+ Icon ICON_BREAKPOINT_MARKER_INEFF_DIS =
+ new GIcon("icon.debugger.breakpoint.marker.ineffective.disabled");
+ Icon ICON_BREAKPOINT_MARKER_INEFF_MIX =
+ new GIcon("icon.debugger.breakpoint.marker.ineffective.disabled");
Icon ICON_BREAKPOINT_MARKER_INCON_EN =
new MultiIcon(ICON_BREAKPOINT_MARKER_ENABLED, ICON_BREAKPOINT_OVERLAY_INCONSISTENT);
@@ -344,22 +351,20 @@ public interface DebuggerResources {
Icon ICON_BREAKPOINT_MARKER_INCON_MIX =
new MultiIcon(ICON_BREAKPOINT_MARKER_MIXED, ICON_BREAKPOINT_OVERLAY_INCONSISTENT);
- Icon ICON_UNIQUE_REF_READ =
- new RotateIcon(ResourceManager.loadImage("images/cursor_arrow.gif"), 180); // TODO
- ImageIcon ICON_UNIQUE_REF_WRITE = ResourceManager.loadImage("images/cursor_arrow.gif"); // TODO
+ Icon ICON_UNIQUE_REF_READ = new GIcon("icon.debugger.unique.ref.read"); // TODO
+ Icon ICON_UNIQUE_REF_WRITE = new GIcon("icon.debugger.unique.ref.write"); // TODO
Icon ICON_UNIQUE_REF_RW = new MultiIcon(ICON_UNIQUE_REF_READ, ICON_UNIQUE_REF_WRITE); // TODO
+ //@formatter:off
String OPTION_NAME_COLORS_ENABLED_BREAKPOINT_MARKERS = "Colors.Enabled Breakpoint Markers";
- Color DEFAULT_COLOR_ENABLED_BREAKPOINT_MARKERS = new Color(0.75f, 0.75f, 0.875f);
+ Color DEFAULT_COLOR_ENABLED_BREAKPOINT_MARKERS = new GColor("color.debugger.plugin.resources.breakpoint.marker.enabled");
String OPTION_NAME_COLORS_DISABLED_BREAKPOINT_MARKERS = "Colors.Disabled Breakpoint Markers";
- Color DEFAULT_COLOR_DISABLED_BREAKPOINT_MARKERS = DEFAULT_COLOR_ENABLED_BREAKPOINT_MARKERS;
- String OPTION_NAME_COLORS_INEFF_EN_BREAKPOINT_MARKERS =
- "Colors.Ineffective Enabled Breakpoint Markers";
- Color DEFAULT_COLOR_INEFF_EN_BREAKPOINT_MARKERS = new Color(0.75f, 0.75f, 0.75f);
- String OPTION_NAME_COLORS_INEFF_DIS_BREAKPOINT_MARKERS =
- "Colors.Ineffective Disabled Breakpoint Markers";
- Color DEFAULT_COLOR_INEFF_DIS_BREAKPOINT_MARKERS =
- DEFAULT_COLOR_INEFF_EN_BREAKPOINT_MARKERS;
+ Color DEFAULT_COLOR_DISABLED_BREAKPOINT_MARKERS = new GColor("color.debugger.plugin.resources.breakpoint.marker.disabled");
+ String OPTION_NAME_COLORS_INEFF_EN_BREAKPOINT_MARKERS = "Colors.Ineffective Enabled Breakpoint Markers";
+ Color DEFAULT_COLOR_INEFF_EN_BREAKPOINT_MARKERS = new GColor("color.debugger.plugin.resources.breakpoint.marker.enabled.ineffective");
+ String OPTION_NAME_COLORS_INEFF_DIS_BREAKPOINT_MARKERS = "Colors.Ineffective Disabled Breakpoint Markers";
+ Color DEFAULT_COLOR_INEFF_DIS_BREAKPOINT_MARKERS = new GColor("color.debugger.plugin.resources.breakpoint.marker.disabled.ineffective");
+ //@formatter:on
String OPTION_NAME_COLORS_ENABLED_BREAKPOINT_COLORING_BACKGROUND =
"Colors.Enabled Breakpoint Markers Have Background";
@@ -1037,7 +1042,7 @@ public interface DebuggerResources {
String NAME = "Select Registers";
String DESCRIPTION = "Select registers to display/modify";
String GROUP = "aa";
- Icon ICON = ResourceManager.loadImage("images/select-registers.png");
+ Icon ICON = new GIcon("icon.debugger.select.registers");
String HELP_ANCHOR = "select_registers";
static ActionBuilder builder(Plugin owner) {
@@ -1053,7 +1058,7 @@ public interface DebuggerResources {
String NAME = "Clone Window";
String DESCRIPTION = "Create a disconnected copy of this window";
String GROUP = "zzzz";
- Icon ICON = ResourceManager.loadImage("images/camera-photo.png");
+ Icon ICON = new GIcon("icon.provider.clone");
String HELP_ANCHOR = "clone_window";
static ActionBuilder builder(Plugin owner) {
@@ -1069,7 +1074,7 @@ public interface DebuggerResources {
String NAME = "Enable Edits";
String DESCRIPTION = "Enable editing of recorded or live values";
String GROUP = "yyyy2";
- Icon ICON = ResourceManager.loadImage("images/editbytes.gif");
+ Icon ICON = new GIcon("icon.debugger.enable.edits");
String HELP_ANCHOR = "enable_edits";
static ToggleActionBuilder builder(Plugin owner) {
@@ -1084,7 +1089,7 @@ public interface DebuggerResources {
interface DisassembleAsAction {
String NAME = "Disassemble as";
String DESCRIPTION = "Disassemble using an alternative language";
- Icon ICON = ResourceManager.loadImage("images/disassemble.png");
+ Icon ICON = new GIcon("icon.debugger.disassemble");
String HELP_ANCHOR = "disassemble_as";
static ActionBuilder builder(Plugin owner) {
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java
index 44eca5be13..26659b9a67 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/diff/DebuggerTraceViewDiffPlugin.java
@@ -28,6 +28,7 @@ import javax.swing.event.ChangeListener;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToggleDockingAction;
+import generic.theme.GColor;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel;
import ghidra.app.plugin.core.debug.*;
@@ -57,28 +58,19 @@ import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.time.schedule.TraceSchedule;
import ghidra.util.Msg;
-@PluginInfo(
- shortDescription = "Compare memory state between times in a trace",
- description = "Provides a side-by-side diff view between snapshots (points in time) in a " +
- "trace. The comparison is limited to raw bytes.",
- category = PluginCategoryNames.DEBUGGER,
- packageName = DebuggerPluginPackage.NAME,
- status = PluginStatus.RELEASED,
- eventsConsumed = {
+@PluginInfo(shortDescription = "Compare memory state between times in a trace", description = "Provides a side-by-side diff view between snapshots (points in time) in a " +
+ "trace. The comparison is limited to raw bytes.", category = PluginCategoryNames.DEBUGGER, packageName = DebuggerPluginPackage.NAME, status = PluginStatus.RELEASED, eventsConsumed = {
TraceClosedPluginEvent.class,
- },
- eventsProduced = {},
- servicesRequired = {
+ }, eventsProduced = {}, servicesRequired = {
DebuggerListingService.class,
- },
- servicesProvided = {})
+ }, servicesProvided = {})
public class DebuggerTraceViewDiffPlugin extends AbstractDebuggerPlugin {
protected static final String MARKER_NAME = "Trace Diff";
protected static final String MARKER_DESCRIPTION = "Difference between snapshots in this trace";
public static final String DIFF_COLOR_CATEGORY = "Listing Fields";
public static final String DIFF_COLOR_NAME = "Selection Colors.Difference Color";
- public static final Color DEFAULT_DIFF_COLOR = new Color(255, 230, 180); // light orange
+ public static final Color DEFAULT_DIFF_COLOR = new GColor("color.bg.debugger.diff.marker");
protected class ListingCoordinationListener implements CoordinatedListingPanelListener {
@Override
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java
index 2c928fe299..eb380fbce7 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/interpreters/AbstractDebuggerWrappedConsoleConnection.java
@@ -22,7 +22,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.swing.ImageIcon;
+import javax.swing.Icon;
import docking.ActionContext;
import docking.action.DockingAction;
@@ -152,7 +152,7 @@ public abstract class AbstractDebuggerWrappedConsoleConnection>> inserter = list -> {
try (UndoableTransaction tid = UndoableTransaction.start(obj, "AddRandom")) {
- int i = 0;
for (Entry
+
Note that multi-user merge does not currently support
merging of Program Options (including Analysis Options). Options stored in shared Program database
following a conflicting checkin may not reflect option settings specified prior to checkin.
@@ -182,9 +182,9 @@
the current program.
-
+
Access to stored configurations is not currently
- aupported across different versions of Ghidra.
+ supported across different versions of Ghidra.
+
When using an external GNU demangler,
please understand the risks associated with using that version of the
software. The demangler_gnu_v2_24 version of the
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/Data.htm b/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/Data.htm
index 103809ad82..4319372e67 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/Data.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/DataPlugin/Data.htm
@@ -23,7 +23,7 @@
-Data is created by applying Data Types to bytes in +
Data is created by applying Data Types to bytes in memory. Data Types interpret bytes as values and provide a visual interpretation of those bytes based on the Data Type used, e.g., a four byte IEEE floating point number or a two byte little endian @@ -583,7 +583,7 @@
-
Regardless of how a data type is applied, data is only created if the data type will fit within the available undefined bytes.
Drag from Data Type Manager
+Drag from Data Type Manager
Use the
Cycle Groups
+ "Cycle__float_double"> Cycle Groups-Cycle Groups are an easy way to apply basic data types (byte, word, float, @@ -679,7 +678,7 @@
Favorites
+Favorites
-A Favorite data type is a data type that you use frequently and want to apply @@ -703,7 +702,7 @@ Shortcut. Key Bindings allow you to assign "hot keys" to any menu item.
Recently Used Data Type
+Recently Used Data Type
The last applied data type is always available at the bottom of the data menu. By diff --git a/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm b/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm index 6c8abbef53..db73da2d09 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm @@ -448,12 +448,11 @@
- File Status +File Status -Sample Icon in Project Data - Tree +Sample Icon -Description +Description diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm b/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm index 93025be9bf..0e488d20e4 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm @@ -25,7 +25,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC- - +
-Action
@@ -97,7 +97,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-B
+B
- +Back Reference
@@ -197,7 +197,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Call Block Model
@@ -319,7 +319,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Data (item)
@@ -436,7 +436,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +ELF
@@ -491,7 +491,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Fall Through Address
@@ -555,7 +555,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Ghidra
@@ -606,7 +606,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Hex Integer
@@ -636,7 +636,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +IDA Pro
@@ -688,7 +688,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Key Binding
@@ -698,7 +698,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Label
@@ -756,7 +756,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-@@ -848,7 +848,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +- +Name Space
@@ -865,7 +865,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Offcut
@@ -906,7 +906,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Partitioned Code Model
@@ -1058,7 +1058,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Read-Only Project
@@ -1108,7 +1108,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Scalar
@@ -1239,7 +1239,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Tabbed Window
@@ -1297,7 +1297,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Unconditional Call
@@ -1352,7 +1352,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Version Control
@@ -1383,7 +1383,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-- +Workspace
@@ -1394,7 +1394,7 @@ xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-XREF
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm b/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm index 1b28628dec..4719feaa67 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm @@ -294,16 +294,11 @@-
- - -Tool Options
-- Option +Option -Description +Description @@ -398,15 +393,11 @@ -
@@ -290,14 +290,14 @@ parameter information is stripped.- Tool - Options -- Option +Option -Description +Description @@ -445,7 +436,7 @@ of the UI. Doing this effectively creates a Dark Theme, which some users find less visually straining. - +diff --git a/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java b/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java index 476d3c14c1..f55db72821 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/GhidraOptions.java @@ -15,9 +15,9 @@ */ package ghidra; -import java.awt.Color; import java.awt.event.MouseEvent; +import generic.theme.GColor; import ghidra.framework.options.Options; /** @@ -156,7 +156,7 @@ public interface GhidraOptions { final String HIGHLIGHT_CURSOR_LINE_COLOR = "Cursor." + HIGHLIGHT_CURSOR_LINE_COLOR_OPTION_NAME; - final Color DEFAULT_CURSOR_LINE_COLOR = new Color(232, 242, 254); + final GColor DEFAULT_CURSOR_LINE_COLOR = new GColor("color.bg.currentline.listing"); final String HIGHLIGHT_CURSOR_LINE_OPTION_NAME = "Highlight Cursor Line"; @@ -176,6 +176,7 @@ public interface GhidraOptions { public static enum CURSOR_MOUSE_BUTTON_NAMES { LEFT(MouseEvent.BUTTON1), MIDDLE(MouseEvent.BUTTON2), RIGHT(MouseEvent.BUTTON3); + private int mouseEventID; CURSOR_MOUSE_BUTTON_NAMES(int mouseEventID) { @@ -190,10 +191,9 @@ public interface GhidraOptions { // end cursor highlight final String OPTION_SELECTION_COLOR = "Selection Colors.Selection Color"; - final Color DEFAULT_SELECTION_COLOR = new Color(180, 255, 180); + final GColor DEFAULT_SELECTION_COLOR = new GColor("color.bg.selection.listing"); final String OPTION_HIGHLIGHT_COLOR = "Selection Colors.Highlight Color"; - final Color DEFAULT_HIGHLIGHT_COLOR = new Color(255, 255, 180); + final GColor DEFAULT_HIGHLIGHT_COLOR = new GColor("color.bg.highlight.listing"); final String APPLY_ENABLED = "apply.enabled"; - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java b/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java index b7e5951772..22ad3f23f7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java @@ -38,7 +38,6 @@ import ghidra.program.database.ProgramDB; import ghidra.util.*; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskLauncher; -import ghidra.util.task.TaskMonitorAdapter; /** * Main Ghidra application class. Creates @@ -73,7 +72,6 @@ public class GhidraRun implements GhidraLaunchable { Runnable mainTask = () -> { GhidraApplicationConfiguration configuration = new GhidraApplicationConfiguration(); - configuration.setTaskMonitor(new StatusReportingTaskMonitor()); Application.initializeApplication(layout, configuration); log = LogManager.getLogger(GhidraRun.class); @@ -243,15 +241,3 @@ public class GhidraRun implements GhidraLaunchable { // this exists just to allow access to the constructor } } - -class StatusReportingTaskMonitor extends TaskMonitorAdapter { - @Override - public synchronized void setCancelEnabled(boolean enable) { - // Not permitted - } - - @Override - public void setMessage(String message) { - SplashScreen.updateSplashScreenStatus(message); - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeConstants.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeConstants.java index 520d1c6360..b6975fff0a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeConstants.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeConstants.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,36 +17,37 @@ package ghidra.app.merge; import java.awt.Color; +import generic.theme.GThemeDefaults.Colors.Palette; public interface MergeConstants { - public static final int RESULT = 0; - public static final int LATEST = 1; - public static final int MY = 2; - public static final int ORIGINAL = 3; - public static final String RESULT_TITLE = "Result"; - public static final String ORIGINAL_TITLE = "Original"; - public static final String LATEST_TITLE = "Latest"; - public static final String MY_TITLE = "Checked Out"; - - public Color CONFLICT_COLOR = new Color(140, 0, 0); - public static final Color HIGHLIGHT_COLOR = new Color(230,230,230); - - // The following are standardized names for use in passing resolve - // information between individual merge managers. - // For example: - // the data type merger knows what data type in the result is equivalent - // to a given data type from my checked out program. The code unit and - // function mergers need to be able to get this information so they - // don't unknowingly re-introduce a data type that was already eliminated - // by a data type conflict. - public static final String RESOLVED_LATEST_DTS = "ResolvedLatestDataTypes"; - public static final String RESOLVED_MY_DTS = "ResolvedMyDataTypes"; - public static final String RESOLVED_ORIGINAL_DTS = "ResolvedOriginalDataTypes"; - public static final String RESOLVED_CODE_UNITS = "ResolvedCodeUnits"; - public static final String PICKED_LATEST_CODE_UNITS = "PickedLatestCodeUnits"; - public static final String PICKED_MY_CODE_UNITS = "PickedMyCodeUnits"; - public static final String PICKED_ORIGINAL_CODE_UNITS = "PickedOriginalCodeUnits"; - public static final String RESOLVED_LATEST_SYMBOLS = "ResolvedLatestSymbols"; - public static final String RESOLVED_MY_SYMBOLS = "ResolvedMySymbols"; - public static final String RESOLVED_ORIGINAL_SYMBOLS = "ResolvedOriginalSymbols"; + public static final int RESULT = 0; + public static final int LATEST = 1; + public static final int MY = 2; + public static final int ORIGINAL = 3; + public static final String RESULT_TITLE = "Result"; + public static final String ORIGINAL_TITLE = "Original"; + public static final String LATEST_TITLE = "Latest"; + public static final String MY_TITLE = "Checked Out"; + + public Color CONFLICT_COLOR = Palette.MAROON; + public static final Color HIGHLIGHT_COLOR = Palette.LIGHT_GRAY; + + // The following are standardized names for use in passing resolve + // information between individual merge managers. + // For example: + // the data type merger knows what data type in the result is equivalent + // to a given data type from my checked out program. The code unit and + // function mergers need to be able to get this information so they + // don't unknowingly re-introduce a data type that was already eliminated + // by a data type conflict. + public static final String RESOLVED_LATEST_DTS = "ResolvedLatestDataTypes"; + public static final String RESOLVED_MY_DTS = "ResolvedMyDataTypes"; + public static final String RESOLVED_ORIGINAL_DTS = "ResolvedOriginalDataTypes"; + public static final String RESOLVED_CODE_UNITS = "ResolvedCodeUnits"; + public static final String PICKED_LATEST_CODE_UNITS = "PickedLatestCodeUnits"; + public static final String PICKED_MY_CODE_UNITS = "PickedMyCodeUnits"; + public static final String PICKED_ORIGINAL_CODE_UNITS = "PickedOriginalCodeUnits"; + public static final String RESOLVED_LATEST_SYMBOLS = "ResolvedLatestSymbols"; + public static final String RESOLVED_MY_SYMBOLS = "ResolvedMySymbols"; + public static final String RESOLVED_ORIGINAL_SYMBOLS = "ResolvedOriginalSymbols"; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManagerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManagerProvider.java index d323b5a605..ef1f0e0736 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManagerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeManagerProvider.java @@ -26,6 +26,7 @@ import docking.options.editor.ButtonPanelFactory; import docking.util.image.ToolIconURL; import docking.widgets.OptionDialog; import docking.widgets.label.*; +import generic.theme.GIcon; import ghidra.app.context.ListingActionContext; import ghidra.app.merge.tool.ListingMergePanel; import ghidra.app.nav.Navigatable; @@ -36,7 +37,6 @@ import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.program.util.ProgramLocation; import ghidra.util.HelpLocation; import ghidra.util.layout.VerticalLayout; -import resources.ResourceManager; /** * Component that displays merge components as needed. @@ -59,7 +59,7 @@ class MergeManagerProvider extends ComponentProviderAdapter { private JButton cancelButton; private boolean wasCanceled; - private ImageIcon MERGE_ICON = ResourceManager.loadImage("images/Merge.png"); + private Icon MERGE_ICON = new GIcon("icon.plugin.merge"); private JPanel mainPanel; public MergeManagerProvider(MergeManagerPlugin plugin, String title) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeProgressPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeProgressPanel.java index 500cdd1164..4528cdd672 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeProgressPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/MergeProgressPanel.java @@ -16,17 +16,18 @@ package ghidra.app.merge; import java.awt.BorderLayout; -import java.awt.Color; import java.util.HashMap; +import java.util.Map; import javax.swing.*; import javax.swing.border.Border; import docking.widgets.label.GIconLabel; import docking.widgets.label.GLabel; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.util.Msg; import ghidra.util.layout.VerticalLayout; -import resources.ResourceManager; /** * The MergeProgressPanel displays the name of each merge phase along with an icon indicating @@ -34,11 +35,10 @@ import resources.ResourceManager; */ public class MergeProgressPanel extends JPanel { - public static ImageIcon DEFINED_ICON = ResourceManager.loadImage("images/bullet_green.png"); - public static ImageIcon IN_PROGRESS_ICON = ResourceManager.loadImage("images/right.png"); - public static ImageIcon COMPLETED_ICON = - ResourceManager.loadImage("images/checkmark_green.gif"); - private HashMap
As a prototype feature, this feature has many known issues, including:
imageMap = new HashMap<>(); + public static Icon DEFINED_ICON = new GIcon("icon.plugin.merge.status.pending"); + public static Icon IN_PROGRESS_ICON = new GIcon("icon.plugin.merge.status.in.progress"); + public static Icon COMPLETED_ICON = new GIcon("icon.plugin.merge.status.complete"); + private Map imageMap = new HashMap<>(); private static int INDENT_IN_PIXELS = 20; /** @@ -52,7 +52,7 @@ public class MergeProgressPanel extends JPanel { private JPanel getProgressTitlePanel() { JPanel phasesTitlePanel = new JPanel(); Border insideBorder = BorderFactory.createEmptyBorder(0, 0, 2, 0); - Border outsideBorder = BorderFactory.createMatteBorder(0, 0, 2, 0, Color.BLUE); + Border outsideBorder = BorderFactory.createMatteBorder(0, 0, 2, 0, Palette.BLUE); Border compoundBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder); phasesTitlePanel.setBorder(compoundBorder); BoxLayout bl = new BoxLayout(phasesTitlePanel, BoxLayout.X_AXIS); @@ -139,9 +139,6 @@ public class MergeProgressPanel extends JPanel { return buf.toString(); } - /** - * @param args - */ public static void main(String[] args) { MergeProgressPanel panel = new MergeProgressPanel(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/PhaseProgressPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/PhaseProgressPanel.java index 8d0247b923..a1ea20516b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/PhaseProgressPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/PhaseProgressPanel.java @@ -17,14 +17,12 @@ package ghidra.app.merge; import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import javax.swing.*; import docking.widgets.label.GDLabel; import docking.widgets.label.GIconLabel; -import resources.ResourceManager; +import resources.Icons; /** * The PhaseProgressPanel provides a title, progress bar and message for the current phase that is @@ -33,7 +31,7 @@ import resources.ResourceManager; public class PhaseProgressPanel extends JPanel { private final static String DEFAULT_INFO = "Merge programs in progress..."; - private ImageIcon INFORM_ICON = ResourceManager.loadImage("images/information.png"); + private Icon INFORM_ICON = Icons.INFO_ICON; private JLabel titleLabel; private JProgressBar progressBar; @@ -105,12 +103,7 @@ public class PhaseProgressPanel extends JPanel { doSetMessage(DEFAULT_INFO); // Sets up the timer for updating the GUI. - updateTimer = new Timer(250, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - update(); - } - }); + updateTimer = new Timer(250, e -> update()); } // Method for use by the timer to update the progress bar or message. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergePanel.java index 98f2478ddc..fc6004f353 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergePanel.java @@ -30,7 +30,7 @@ import ghidra.app.merge.MergeConstants; import ghidra.app.merge.util.ConflictCountPanel; import ghidra.framework.data.DomainObjectMergeManager; import ghidra.program.model.data.*; -import resources.ResourceManager; +import resources.Icons; /** * Panel to select a data type in order to resolve a conflict. @@ -86,9 +86,6 @@ class DataTypeMergePanel extends JPanel { buttonGroup.add(originalRB); } - /** - * - */ int getSelectedOption() { if (latestRB.isSelected()) { return DataTypeMergeManager.OPTION_LATEST; @@ -105,13 +102,10 @@ class DataTypeMergePanel extends JPanel { private void create() { buttonGroup = new ButtonGroup(); - ItemListener listener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - mergeManager.clearStatusText(); - mergeManager.setApplyEnabled(true); - } + ItemListener listener = e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + mergeManager.clearStatusText(); + mergeManager.setApplyEnabled(true); } }; @@ -180,7 +174,7 @@ class DataTypeMergePanel extends JPanel { private JPanel createInfoPanel() { - Icon icon = ResourceManager.loadImage("images/information.png"); + Icon icon = Icons.INFO_ICON; JLabel imageLabel = new GIconLabel(icon); MultiLineLabel label = diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java index 66b337e14e..f18266061d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java @@ -23,6 +23,7 @@ import javax.swing.JPanel; import javax.swing.JTextPane; import javax.swing.text.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.merge.MergeConstants; import ghidra.docking.settings.Settings; import ghidra.docking.settings.SettingsDefinition; @@ -39,8 +40,7 @@ import ghidra.util.UniversalID; */ class DataTypePanel extends JPanel { - private static final long serialVersionUID = 1L; - public Color SOURCE_COLOR = new Color(0, 140, 0); + public Color SOURCE_COLOR = Palette.GREEN; private DataType dataType; private JTextPane textPane; private StyledDocument doc; @@ -110,28 +110,28 @@ class DataTypePanel extends JPanel { offsetAttrSet = new SimpleAttributeSet(); offsetAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); offsetAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - offsetAttrSet.addAttribute(StyleConstants.Foreground, Color.BLACK); + offsetAttrSet.addAttribute(StyleConstants.Foreground, Palette.BLACK); contentAttrSet = new SimpleAttributeSet(); contentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); contentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - contentAttrSet.addAttribute(StyleConstants.Foreground, Color.BLUE); + contentAttrSet.addAttribute(StyleConstants.Foreground, Palette.BLUE); fieldNameAttrSet = new SimpleAttributeSet(); fieldNameAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); fieldNameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - fieldNameAttrSet.addAttribute(StyleConstants.Foreground, new Color(204, 0, 204)); + fieldNameAttrSet.addAttribute(StyleConstants.Foreground, Palette.MAGENTA); commentAttrSet = new SimpleAttributeSet(); commentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); commentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - commentAttrSet.addAttribute(StyleConstants.Foreground, new Color(0, 204, 51)); + commentAttrSet.addAttribute(StyleConstants.Foreground, Palette.LIME); deletedAttrSet = new SimpleAttributeSet(); deletedAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); deletedAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); deletedAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - deletedAttrSet.addAttribute(StyleConstants.Foreground, Color.RED); + deletedAttrSet.addAttribute(StyleConstants.Foreground, Palette.RED); setDataType(dataType); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchiveMergePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchiveMergePanel.java index 1fd2d12f61..0130697b7c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchiveMergePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchiveMergePanel.java @@ -30,7 +30,7 @@ import ghidra.app.merge.MergeConstants; import ghidra.app.merge.util.ConflictCountPanel; import ghidra.framework.data.DomainObjectMergeManager; import ghidra.program.model.data.SourceArchive; -import resources.ResourceManager; +import resources.Icons; /** * Panel to select a source archive in order to resolve a conflict. @@ -104,13 +104,10 @@ class SourceArchiveMergePanel extends JPanel { private void create() { buttonGroup = new ButtonGroup(); - ItemListener listener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - mergeManager.clearStatusText(); - mergeManager.setApplyEnabled(true); - } + ItemListener listener = e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + mergeManager.clearStatusText(); + mergeManager.setApplyEnabled(true); } }; @@ -175,7 +172,7 @@ class SourceArchiveMergePanel extends JPanel { private JPanel createInfoPanel() { - Icon icon = ResourceManager.loadImage("images/information.png"); + Icon icon = Icons.INFO_ICON; JLabel imageLabel = new GIconLabel(icon); MultiLineLabel label = new MultiLineLabel( diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchivePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchivePanel.java index 9a8afdf1a8..be7b60743e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchivePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/SourceArchivePanel.java @@ -15,17 +15,18 @@ */ package ghidra.app.merge.datatypes; -import ghidra.program.model.data.ArchiveType; -import ghidra.program.model.data.SourceArchive; - import java.awt.BorderLayout; -import java.awt.Color; import java.util.Date; import javax.swing.JPanel; import javax.swing.JTextPane; import javax.swing.text.*; +import generic.theme.GThemeDefaults.Colors.Palette; +import ghidra.program.model.data.ArchiveType; +import ghidra.program.model.data.SourceArchive; +import ghidra.util.Msg; + /** * Panel to show the contents of a Source Archive. */ @@ -37,47 +38,47 @@ class SourceArchivePanel extends JPanel { private SimpleAttributeSet headingAttrSet; private SimpleAttributeSet valueAttrSet; private SimpleAttributeSet deletedAttrSet; - + SourceArchivePanel() { super(new BorderLayout()); create(); } - + public void setSourceArchive(SourceArchive sourceArchive) { this.sourceArchive = sourceArchive; textPane.setText(""); - formatSourceArchive(); + formatSourceArchive(); textPane.setCaretPosition(0); } - + private void create() { - textPane = new JTextPane(); + textPane = new JTextPane(); doc = textPane.getStyledDocument(); add(textPane, BorderLayout.CENTER); textPane.setEditable(false); - + headingAttrSet = new SimpleAttributeSet(); headingAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); - headingAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12)); - headingAttrSet.addAttribute(StyleConstants.Foreground, Color.BLUE); - + headingAttrSet.addAttribute(StyleConstants.FontSize, 12); + headingAttrSet.addAttribute(StyleConstants.Foreground, Palette.BLUE); + valueAttrSet = new SimpleAttributeSet(); valueAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - valueAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11)); + valueAttrSet.addAttribute(StyleConstants.FontSize, 11); valueAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); deletedAttrSet = new SimpleAttributeSet(); deletedAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - deletedAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12)); + deletedAttrSet.addAttribute(StyleConstants.FontSize, 12); deletedAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - deletedAttrSet.addAttribute(StyleConstants.Foreground, Color.RED); - + deletedAttrSet.addAttribute(StyleConstants.Foreground, Palette.RED); + setSourceArchive(null); } - + private void formatSourceArchive() { if (sourceArchive == null) { - insertString("\n\nDeleted", deletedAttrSet); + insertString("\n\nDeleted", deletedAttrSet); return; } // formatArchiveID(); @@ -87,62 +88,55 @@ class SourceArchivePanel extends JPanel { formatSyncTime(); formatDirtyFlag(); } - + @SuppressWarnings("unused") private void formatArchiveID() { insertString(" Archive ID: ", headingAttrSet); insertString(sourceArchive.getSourceArchiveID().getValue() + "\n", valueAttrSet); } - + private void formatName() { insertString("Name: ", headingAttrSet); insertString(sourceArchive.getName() + "\n", valueAttrSet); } - + @SuppressWarnings("unused") private void formatFileID() { insertString(" File ID: ", headingAttrSet); insertString(sourceArchive.getDomainFileID() + "\n", valueAttrSet); } - + @SuppressWarnings("unused") private void formatType() { ArchiveType archiveType = sourceArchive.getArchiveType(); String typeString = (archiveType == ArchiveType.FILE) ? "File Archive" : (archiveType == ArchiveType.PROGRAM) ? "Program" - : (archiveType == ArchiveType.PROJECT) ? "Project Archive" - : (archiveType == ArchiveType.BUILT_IN) ? "Built-In" - : "Invalid"; + : (archiveType == ArchiveType.PROJECT) ? "Project Archive" + : (archiveType == ArchiveType.BUILT_IN) ? "Built-In" + : "Invalid"; insertString(" Type: ", headingAttrSet); insertString(typeString + "\n", valueAttrSet); } - + private void formatSyncTime() { String syncTime = new Date(sourceArchive.getLastSyncTime()).toString(); insertString("Last Sync Time: ", headingAttrSet); insertString(syncTime + "\n", valueAttrSet); } - + private void formatDirtyFlag() { insertString("Changed Since Last Sync? ", headingAttrSet); insertString((sourceArchive.isDirty() ? "yes" : "no") + "\n", valueAttrSet); } - -// private String pad(String str, int length) { -// StringBuffer sb = new StringBuffer(str); -// int len = length - str.length(); -// for (int i=0; i " + value + ""); + buf.append("" + value + ""); } private void addAddress(StringBuffer buf, Address addr) { buf.append( - "" + HTMLUtilities.escapeHTML(addr.toString()) + ""); + "" + HTMLUtilities.escapeHTML(addr.toString()) + + ""); } private void updateWest() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalAddConflictPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalAddConflictPanel.java index 09c68737e8..0a22b15bcc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalAddConflictPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalAddConflictPanel.java @@ -26,6 +26,7 @@ import docking.widgets.button.GRadioButton; import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import docking.widgets.label.GIconLabel; +import generic.theme.GIcon; import ghidra.app.merge.MergeConstants; import ghidra.app.merge.MergeManager; import ghidra.app.merge.util.ConflictCountPanel; @@ -45,7 +46,6 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSet; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.ExternalLocation; -import resources.ResourceManager; import resources.icons.EmptyIcon; /** @@ -60,8 +60,8 @@ class ExternalAddConflictPanel extends JPanel implements CodeFormatService { public static final String MERGE_BOTH_BUTTON_NAME = ExternalFunctionMerger.MERGE_BOTH_BUTTON_NAME; - private static Icon hideIcon = ResourceManager.loadImage("images/collapse.gif"); - private static Icon showIcon = ResourceManager.loadImage("images/expand.gif"); + private static final Icon HIDE_ICON = new GIcon("icons.base.listing.conflict.collapse"); + private static final Icon SHOW_ICON = new GIcon("icons.base.listing.conflict.expand"); private DomainObjectMergeManager mergeManager; private int totalConflicts; @@ -291,18 +291,18 @@ class ExternalAddConflictPanel extends JPanel implements CodeFormatService { class ShowHeaderButton extends EmptyBorderButton { ShowHeaderButton() { - super(showIcon); + super(SHOW_ICON); setFocusable(false); setToolTipText("Toggle Format Header"); addActionListener(e -> { if (isSelected()) { setSelected(false); - setIcon(showIcon); + setIcon(SHOW_ICON); latestPanel.showHeader(false); } else { setSelected(true); - setIcon(hideIcon); + setIcon(HIDE_ICON); latestPanel.showHeader(true); } }); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalConflictInfoPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalConflictInfoPanel.java index 8dd01a4d7c..8c386b1c90 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalConflictInfoPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalConflictInfoPanel.java @@ -21,6 +21,7 @@ import javax.swing.*; import javax.swing.border.TitledBorder; import docking.widgets.label.GDHtmlLabel; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.merge.util.ConflictUtility; /** @@ -103,11 +104,11 @@ public class ExternalConflictInfoPanel extends JPanel { } private void addCount(StringBuffer buf, int value) { - buf.append("" + value + ""); + buf.append("" + value + ""); } private void addName(StringBuffer buf, String name) { - buf.append("" + name + ""); + buf.append("" + name + ""); } private void updateWest() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionTagMerger.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionTagMerger.java index 07ab588388..03ccec54df 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionTagMerger.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionTagMerger.java @@ -15,15 +15,14 @@ */ package ghidra.app.merge.listing; -import java.awt.Color; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.*; import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.merge.*; import ghidra.app.util.HelpTopics; import ghidra.program.database.function.FunctionManagerDB; @@ -102,7 +101,6 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { // the middle of resolving multiple conflicts. private long currentlyMergingTagID; - /** * Constructor. * @@ -160,7 +158,6 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { } } - @Override public void merge(TaskMonitor monitor) throws Exception { autoMerge(); @@ -270,7 +267,7 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { // If the source program tag doesn't exist then the user has chosen to // keep a deleted tag, so make sure the corresponding tag in Result // is deleted as well. - if (tag == null ) { + if (tag == null) { if (resultTag != null) { resultTag.delete(); } @@ -279,8 +276,9 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { // If the source tag exists, but the Result tag doesn't, we have to create a new // one in Result. else if (resultTag == null) { - functionManagerDBResult.getFunctionTagManager().createFunctionTag(tag.getName(), - tag.getComment()); + functionManagerDBResult.getFunctionTagManager() + .createFunctionTag(tag.getName(), + tag.getComment()); } // If the source tag exists and Result tag exists, just update the tag @@ -409,7 +407,7 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { functionTag.setName(tagMy.getName()); functionTag.setComment(tagMy.getComment()); } - + } } } @@ -574,37 +572,29 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { private void showMergePanel(long id, TaskMonitor monitor) { try { - final ChangeListener changeListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - conflictOption = conflictPanel.getSelectedOptions(); - if (conflictOption == ASK_USER || conflictOption == CANCELED) { - if (mergeManager != null) { - mergeManager.setApplyEnabled(false); - } - return; - } + final ChangeListener changeListener = e -> { + conflictOption = conflictPanel.getSelectedOptions(); + if (conflictOption == ASK_USER || conflictOption == CANCELED) { if (mergeManager != null) { - mergeManager.clearStatusText(); + mergeManager.setApplyEnabled(false); } - try { - merge(conflictOption, monitor); - if (mergeManager != null) { - mergeManager.setApplyEnabled(true); - } - } - catch (CancelledException e1) { - // user cancel - no need to log + return; + } + if (mergeManager != null) { + mergeManager.clearStatusText(); + } + try { + merge(conflictOption, monitor); + if (mergeManager != null) { + mergeManager.setApplyEnabled(true); } + } + catch (CancelledException e1) { + // user cancel - no need to log + } - } }; - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - setupConflictPanel(id, changeListener, monitor); - } - }); + SwingUtilities.invokeAndWait(() -> setupConflictPanel(id, changeListener, monitor)); } catch (InterruptedException | InvocationTargetException e) { Msg.error(this, "Unexpected error showing merge panel for tag " + id, e); @@ -712,19 +702,20 @@ public class FunctionTagMerger implements MergeResolver, ListingMergeConstants { * @return */ private String getConflictInfo(TaskMonitor monitor) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append( " " + "Resolving conflict " + (monitor.getProgress() + 1) + " of " + tagConflicts.size() + " "); buf.append(HTMLUtilities.HTML_NEW_LINE); buf.append("Tag Id:"); buf.append(HTMLUtilities.spaces(21)); - buf.append(HTMLUtilities.colorString(Color.BLUE, String.valueOf(currentlyMergingTagID))); + buf.append( + HTMLUtilities.colorString(Messages.NORMAL, String.valueOf(currentlyMergingTagID))); buf.append(HTMLUtilities.HTML_NEW_LINE); buf.append("Reason for Conflict:"); buf.append(HTMLUtilities.spaces(1)); buf.append( - HTMLUtilities.colorString(Color.BLUE, tagConflicts.get(currentlyMergingTagID))); + HTMLUtilities.colorString(Messages.NORMAL, tagConflicts.get(currentlyMergingTagID))); buf.append(HTMLUtilities.HTML_NEW_LINE); buf.append(HTMLUtilities.HTML_NEW_LINE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VariousChoicesPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VariousChoicesPanel.java index fc9a0f6435..db28e89df4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VariousChoicesPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VariousChoicesPanel.java @@ -15,22 +15,12 @@ */ package ghidra.app.merge.listing; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; +import java.awt.*; +import java.awt.event.*; import java.util.ArrayList; import java.util.Iterator; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.SwingConstants; +import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeListener; @@ -39,6 +29,7 @@ import docking.widgets.button.GRadioButton; import docking.widgets.checkbox.GCheckBox; import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.app.merge.util.ConflictUtility; import ghidra.util.HTMLUtilities; import ghidra.util.layout.MaximizeSpecificColumnGridLayout; @@ -55,7 +46,7 @@ public class VariousChoicesPanel extends ConflictPanel { private final static long serialVersionUID = 1; private static final Border UNDERLINE_BORDER = - BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK); + BorderFactory.createMatteBorder(0, 0, 1, 0, Java.BORDER); private JPanel rowPanel; private GDHtmlLabel headerLabel; @@ -76,7 +67,7 @@ public class VariousChoicesPanel extends ConflictPanel { /** * Constructor for a various choices panel. - * @param isDoubleBuffered + * @param isDoubleBuffered true if double buffered */ public VariousChoicesPanel(boolean isDoubleBuffered) { super(isDoubleBuffered); @@ -199,17 +190,14 @@ public class VariousChoicesPanel extends ConflictPanel { MyRadioButton[] rb = new MyRadioButton[choices.length]; final int row = rows.size(); final ChoiceRow choiceRow = new ChoiceRow(titleComp, rb); - ItemListener itemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - adjustUseForAllEnablement(); - if (listener != null) { - Object source = e.getSource(); - if (((MyRadioButton) source).isSelected()) { - ResolveConflictChangeEvent re = - new ResolveConflictChangeEvent(source, row, choiceRow.getChoice()); - listener.stateChanged(re); - } + ItemListener itemListener = e -> { + adjustUseForAllEnablement(); + if (listener != null) { + Object source = e.getSource(); + if (((MyRadioButton) source).isSelected()) { + ResolveConflictChangeEvent re = + new ResolveConflictChangeEvent(source, row, choiceRow.getChoice()); + listener.stateChanged(re); } } }; @@ -246,15 +234,12 @@ public class VariousChoicesPanel extends ConflictPanel { MyCheckBox[] cb = new MyCheckBox[choices.length]; final int row = rows.size(); final ChoiceRow choiceRow = new ChoiceRow(titleComp, cb); - ItemListener itemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - adjustUseForAllEnablement(); - if (listener != null) { - ResolveConflictChangeEvent re = - new ResolveConflictChangeEvent(e.getSource(), row, choiceRow.getChoice()); - listener.stateChanged(re); - } + ItemListener itemListener = e -> { + adjustUseForAllEnablement(); + if (listener != null) { + ResolveConflictChangeEvent re = + new ResolveConflictChangeEvent(e.getSource(), row, choiceRow.getChoice()); + listener.stateChanged(re); } }; for (int i = 0; i < choices.length; i++) { @@ -291,8 +276,8 @@ public class VariousChoicesPanel extends ConflictPanel { rowPanel.add(choiceRow.titleLabel); - for (int i = 0; i < choiceRow.rb.length; i++) { - rowPanel.add(choiceRow.rb[i]); + for (JComponent element : choiceRow.rb) { + rowPanel.add(element); } if (row == 0) { add(rowPanel, BorderLayout.CENTER); @@ -303,8 +288,8 @@ public class VariousChoicesPanel extends ConflictPanel { ChoiceRow cr = rows.get(rowNum); rowPanel.remove(cr.titleLabel); JComponent[] comps = cr.rb; - for (int i = 0; i < comps.length; i++) { - rowPanel.remove(comps[i]); + for (JComponent comp : comps) { + rowPanel.remove(comp); } rows.remove(rowNum); } @@ -404,8 +389,7 @@ public class VariousChoicesPanel extends ConflictPanel { } private void removeListeners(ChoiceRow cr) { - for (int i = 0; i < cr.rb.length; i++) { - JComponent comp = cr.rb[i]; + for (JComponent comp : cr.rb) { if (comp instanceof MyRadioButton) { MyRadioButton rb = (MyRadioButton) comp; ItemListener[] listeners = rb.getItemListeners(); @@ -496,8 +480,8 @@ public class VariousChoicesPanel extends ConflictPanel { } boolean hasChoices() { - for (int i = 0; i < rb.length; i++) { - if ((rb[i] instanceof MyRadioButton) || (rb[i] instanceof MyCheckBox)) { + for (JComponent element : rb) { + if ((element instanceof MyRadioButton) || (element instanceof MyCheckBox)) { return true; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VerticalChoicesPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VerticalChoicesPanel.java index 2976a74aee..b131ab07e7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VerticalChoicesPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/VerticalChoicesPanel.java @@ -15,27 +15,12 @@ */ package ghidra.app.merge.listing; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Insets; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; +import java.awt.*; +import java.awt.event.*; import java.util.ArrayList; -import java.util.Iterator; import java.util.ListIterator; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.SwingConstants; +import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeListener; @@ -44,6 +29,7 @@ import docking.widgets.button.GRadioButton; import docking.widgets.checkbox.GCheckBox; import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.app.merge.util.ConflictUtility; import ghidra.util.HTMLUtilities; import ghidra.util.datastruct.LongArrayList; @@ -88,17 +74,11 @@ public class VerticalChoicesPanel extends ConflictPanel { private Insets textVsButtonInsets; private Insets textVsCheckBoxInsets; - /** - * Creates an emptyVerticalChoicesPanel- */ public VerticalChoicesPanel() { super(); init(); } - /** - * @param isDoubleBuffered - */ public VerticalChoicesPanel(boolean isDoubleBuffered) { super(isDoubleBuffered); init(); @@ -179,8 +159,8 @@ public class VerticalChoicesPanel extends ConflictPanel { JComponent[] headerComps = getRowComponents(0); if (headerComps != null) { // remove the header - for (int i = 0; i < headerComps.length; i++) { - rowPanel.remove(headerComps[i]); + for (JComponent headerComp : headerComps) { + rowPanel.remove(headerComp); } headerComps = null; if (rowComps.isEmpty()) { @@ -196,7 +176,8 @@ public class VerticalChoicesPanel extends ConflictPanel { else { rowTypes.set(0, (long) HEADER); } - if ((items != null) && (items.length > 0)) { + + if (items.length > 0) { if (rows.isEmpty()) { rows.add(0, items); } @@ -209,7 +190,7 @@ public class VerticalChoicesPanel extends ConflictPanel { headerComps[i] = new MyLabel(items[i]); headerComps[i].setName(getComponentName(0, i)); setRowComponent(headerComps[i], 0, i, defaultInsets); - headerComps[i].setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK)); + headerComps[i].setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Java.BORDER)); } } rowPanel.validate(); @@ -278,14 +259,11 @@ public class VerticalChoicesPanel extends ConflictPanel { final MyRadioButton firstComp = new MyRadioButton(items[0], conflictOption); group.add(firstComp); firstComp.setName(name); - ItemListener itemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (listener != null && ((JRadioButton) e.getSource()).isSelected()) { - ResolveConflictChangeEvent event = - new ResolveConflictChangeEvent(firstComp, row, getSelectedOptions()); - listener.stateChanged(event); - } + ItemListener itemListener = e -> { + if (listener != null && ((JRadioButton) e.getSource()).isSelected()) { + ResolveConflictChangeEvent event = + new ResolveConflictChangeEvent(firstComp, row, getSelectedOptions()); + listener.stateChanged(event); } }; firstComp.addItemListener(itemListener); @@ -315,12 +293,9 @@ public class VerticalChoicesPanel extends ConflictPanel { rows.add(items); MyCheckBox firstComp = new MyCheckBox(items[0], conflictOption); firstComp.setName(name); - ItemListener itemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (listener != null) { - listener.stateChanged(null); - } + ItemListener itemListener = e -> { + if (listener != null) { + listener.stateChanged(null); } }; firstComp.addItemListener(itemListener); @@ -432,9 +407,6 @@ public class VerticalChoicesPanel extends ConflictPanel { return count; } - /** - * @return - */ protected int getSelectedOptions() { int option = 0; for (int row = 0; row < rows.size(); row++) { @@ -449,11 +421,6 @@ public class VerticalChoicesPanel extends ConflictPanel { return option; } - /** - * @param row - * @param i - * @return - */ private JComponent getComponent(int row, int column) { JComponent[] comps = getRowComponents(row); if (column < comps.length) { @@ -639,8 +606,7 @@ public class VerticalChoicesPanel extends ConflictPanel { int rowCount = rowComps.size(); for (int row = 0; row < rowCount; row++) { JComponent[] comps = getRowComponents(row); - for (int i = 0; i < comps.length; i++) { - JComponent component = comps[i]; + for (JComponent component : comps) { if (component instanceof MyRadioButton && ((MyRadioButton) component).isSelected()) { conflictOption |= ((MyRadioButton) component).option; @@ -666,8 +632,8 @@ public class VerticalChoicesPanel extends ConflictPanel { */ @Override public boolean hasChoice() { - for (Iteratoriterator = rowTypes.iterator(); iterator.hasNext();) { - long rowType = iterator.next().longValue(); + for (Long rowType2 : rowTypes) { + long rowType = rowType2.longValue(); if (rowType == RADIO_BUTTON || rowType == CHECK_BOX) { return true; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java index 7786c510cc..4d31877284 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java @@ -28,6 +28,7 @@ import docking.widgets.checkbox.GCheckBox; import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import docking.widgets.fieldpanel.support.BackgroundColorModel; +import generic.theme.GIcon; import ghidra.app.merge.MergeConstants; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.core.codebrowser.hover.*; @@ -54,12 +55,11 @@ import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; import ghidra.util.exception.NotYetImplementedException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class ListingMergePanel extends JPanel implements MergeConstants, FocusListener, CodeFormatService { - private static Icon hideIcon = ResourceManager.loadImage("images/collapse.gif"); - private static Icon showIcon = ResourceManager.loadImage("images/expand.gif"); + private static final Icon HIDE_ICON = new GIcon("icon.plugin.merge.conflict.collapse"); + private static final Icon SHOW_ICON = new GIcon("icon.plugin.merge.conflict.expand"); private JComponent topComp; private JComponent bottomComp; @@ -297,9 +297,8 @@ public class ListingMergePanel extends JPanel } /** - * Color the background of all 4 listings to the indicated color for - * the indicated addresses. - * @param addrSet + * Color the background of all 4 listings to the indicated color for the indicated addresses. + * @param addrSet the addresses */ public void paintAllBackgrounds(AddressSetView addrSet) { backgroundColorModel.setAddressSet(addrSet); @@ -509,18 +508,18 @@ public class ListingMergePanel extends JPanel private class ShowHeaderButton extends EmptyBorderButton { ShowHeaderButton() { - super(showIcon); + super(SHOW_ICON); setFocusable(false); setToolTipText("Toggle Format Header"); addActionListener(e -> { if (isSelected()) { setSelected(false); - setIcon(showIcon); + setIcon(SHOW_ICON); listingPanels[RESULT].showHeader(false); } else { setSelected(true); - setIcon(hideIcon); + setIcon(HIDE_ICON); listingPanels[RESULT].showHeader(true); } }); @@ -616,14 +615,12 @@ public class ListingMergePanel extends JPanel } class LockComponent extends GCheckBox { - private static final Icon lock = ResourceManager.loadImage("images/lock.gif"); - private static final Icon unlock = ResourceManager.loadImage("images/unlock.gif"); LockComponent() { - super(unlock); + super(new GIcon("icon.plugin.merge.conflict.unlock")); setToolTipText("Lock/Unlock with other views"); setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0)); - setSelectedIcon(lock); + setSelectedIcon(new GIcon("icon.plugin.merge.conflict.lock")); setSelected(true); } @@ -635,26 +632,3 @@ class LockComponent extends GCheckBox { setSelected(lock); } } -/*** -// class LockComponent extends ToolbarButton { -// private static final Icon lock = ResourceManager.loadImage("images/lock.gif"); -// private static final Icon unlock = ResourceManager.loadImage("images/unlock.gif"); -// LockComponent() { -// super(unlock); -// setBorder(BorderFactory.createEmptyBorder(0,2,0,2)); -// setSelectedIcon(lock); -// setSelected(true); -// addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// setSelected(!isSelected()); -// } -// }); -// } -// boolean isLocked() { -// return isSelected(); -// } -// void setLocked(boolean lock) { -// setSelected(lock); -// } -// } - ***/ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ViewInstructionDetailsAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ViewInstructionDetailsAction.java index c1da04e5b4..97910b13c5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ViewInstructionDetailsAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ViewInstructionDetailsAction.java @@ -15,15 +15,8 @@ */ package ghidra.app.merge.tool; -import ghidra.app.context.ListingActionContext; -import ghidra.app.context.ListingContextAction; -import ghidra.app.merge.listing.CodeUnitDetails; -import ghidra.program.model.address.Address; -import ghidra.program.model.listing.*; -import ghidra.program.util.ProgramLocation; -import ghidra.util.HelpLocation; - -import java.awt.*; +import java.awt.Dimension; +import java.awt.Insets; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; @@ -33,6 +26,14 @@ import docking.DialogComponentProvider; import docking.action.KeyBindingData; import docking.action.MenuData; import docking.widgets.fieldpanel.FieldPanel; +import generic.theme.Gui; +import ghidra.app.context.ListingActionContext; +import ghidra.app.context.ListingContextAction; +import ghidra.app.merge.listing.CodeUnitDetails; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.*; +import ghidra.program.util.ProgramLocation; +import ghidra.util.HelpLocation; public class ViewInstructionDetailsAction extends ListingContextAction { @@ -47,8 +48,8 @@ public class ViewInstructionDetailsAction extends ListingContextAction { setKeyBindingData(new KeyBindingData(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); setEnabled(true); - setDescription("Display a dialog indicating details, such as references, for the " - + "instruction at the current cursor location."); + setDescription("Display a dialog indicating details, such as references, for the " + + "instruction at the current cursor location."); setHelpLocation(HELP_LOCATION); } @@ -87,13 +88,11 @@ public class ViewInstructionDetailsAction extends ListingContextAction { } private JScrollPane createDetailsPane(String details) { - Font font = new Font("Monospaced", Font.PLAIN, 12); - JTextArea textArea = new JTextArea(); + Gui.registerFont(textArea, "font.monospaced"); textArea.setLineWrap(false); textArea.setEditable(false); textArea.setMargin(new Insets(5, 5, 5, 5)); - textArea.setFont(font); textArea.setOpaque(true); textArea.setCaretPosition(0); textArea.setText(details); @@ -102,8 +101,10 @@ public class ViewInstructionDetailsAction extends ListingContextAction { JViewport vp = scrolledDetails.getViewport(); vp.add(textArea); - scrolledDetails.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scrolledDetails.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrolledDetails + .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrolledDetails + .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); return scrolledDetails; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/NameConflictsPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/NameConflictsPanel.java index a1195cd901..0240c47d96 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/NameConflictsPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/NameConflictsPanel.java @@ -16,7 +16,6 @@ package ghidra.app.merge.tree; import java.awt.BorderLayout; -import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.*; @@ -27,7 +26,7 @@ import docking.widgets.label.GDLabel; import docking.widgets.label.GIconLabel; import ghidra.app.merge.MergeConstants; import ghidra.program.model.listing.Program; -import resources.ResourceManager; +import resources.Icons; /** * Panel to get user input to resolve name conflicts when private name of tree @@ -129,7 +128,7 @@ class NameConflictsPanel extends JPanel { iconPanel.setLayout(new BoxLayout(iconPanel, BoxLayout.X_AXIS)); conflictsLabel = new GDLabel("'My' name already exists in Latest Version"); - ImageIcon icon = ResourceManager.loadImage("images/information.png"); + Icon icon = Icons.INFO_ICON; iconPanel.add(new GIconLabel(icon)); iconPanel.add(Box.createHorizontalStrut(5)); iconPanel.add(conflictsLabel); @@ -158,12 +157,9 @@ class NameConflictsPanel extends JPanel { panel.add(rbPanel, BorderLayout.CENTER); add(panel); - ItemListener itemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (listener != null) { - listener.stateChanged(null); - } + ItemListener itemListener = e -> { + if (listener != null) { + listener.stateChanged(null); } }; keepOtherRB.addItemListener(itemListener); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/TreeChangePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/TreeChangePanel.java index 9bc47d765d..09b03e4193 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/TreeChangePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/TreeChangePanel.java @@ -21,8 +21,11 @@ import javax.swing.*; import docking.widgets.label.GDLabel; import docking.widgets.label.GIconLabel; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.util.layout.PairLayout; -import resources.ResourceManager; +import resources.Icons; /** * Panel to show whether tree name and tree structure changed. @@ -39,11 +42,10 @@ class TreeChangePanel extends JPanel { private JLabel nameIconLabel; private JLabel structureIconLabel; - private final static ImageIcon CHANGED_ICON = ResourceManager.loadImage("images/changed16.gif"); - private final static ImageIcon NO_CHANGE_ICON = - ResourceManager.loadImage("images/EmptyIcon16.gif"); - private final static Color CHANGED_COLOR = Color.BLACK; - private final static Color NO_CHANGE_COLOR = Color.GRAY; + private final static Icon CHANGED_ICON = new GIcon("icon.plugin.merge.changed"); + private final static Icon NO_CHANGE_ICON = Icons.EMPTY_ICON; + private final static Color CHANGED_COLOR = Colors.FOREGROUND; + private final static Color NO_CHANGE_COLOR = Messages.HINT; TreeChangePanel(String title) { super(new BorderLayout()); @@ -73,7 +75,7 @@ class TreeChangePanel extends JPanel { treeNameLabel = new GDLabel("Tree Name"); Font font = treeNameLabel.getFont(); - font = new Font(font.getName(), Font.BOLD, font.getSize()); + font = font.deriveFont(Font.BOLD); treeNameLabel.setFont(font); nameLabel = new GDLabel("Name Changed"); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/util/ConflictCountPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/util/ConflictCountPanel.java index 970ebc0632..66b513876e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/util/ConflictCountPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/util/ConflictCountPanel.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +16,13 @@ package ghidra.app.merge.util; import java.awt.BorderLayout; -import java.awt.Color; import javax.swing.*; import javax.swing.text.*; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.merge.MergeConstants; +import ghidra.util.Msg; /** * Panel that shows the current conflict number and the total number of @@ -45,6 +45,7 @@ public class ConflictCountPanel extends JPanel { super(new BorderLayout()); create(); } + /** * Update the counts, e.g., Conflict # 1 of 3. * @param currentCount current @@ -52,39 +53,41 @@ public class ConflictCountPanel extends JPanel { */ public void updateCount(int currentCount, int totalCount) { textPane.setText(""); - + int offset = doc.getLength(); try { doc.insertString(offset, "Conflict # ", textAttrSet); offset = doc.getLength(); - doc.insertString(offset, " "+currentCount +" ", countAttrSet); + doc.insertString(offset, " " + currentCount + " ", countAttrSet); offset = doc.getLength(); doc.insertString(offset, " of ", textAttrSet); offset = doc.getLength(); - doc.insertString(offset, " "+totalCount +" ", countAttrSet); - } catch (BadLocationException e) { + doc.insertString(offset, " " + totalCount + " ", countAttrSet); } - + catch (BadLocationException e) { + Msg.debug(this, "Exception updating text", e); + } + } private void create() { - + setBorder(BorderFactory.createTitledBorder("Current Conflict")); textPane = new JTextPane(); textPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 0)); textPane.setEditable(false); add(textPane); - + doc = textPane.getStyledDocument(); - + textPane.setBackground(getBackground()); - + SimpleAttributeSet set = new SimpleAttributeSet(); set.addAttribute(StyleConstants.Bold, Boolean.TRUE); - set.addAttribute(StyleConstants.Foreground, Color.RED); + set.addAttribute(StyleConstants.Foreground, Messages.ERROR); textAttrSet = new SimpleAttributeSet(); - textAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12)); + textAttrSet.addAttribute(StyleConstants.FontSize, 12); countAttrSet = new SimpleAttributeSet(); countAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/DecoratorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/DecoratorPanel.java index 5cdf223f49..35c7ddf2bf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/DecoratorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/DecoratorPanel.java @@ -20,24 +20,24 @@ import java.awt.Color; import javax.swing.*; +import generic.theme.GColor; + public class DecoratorPanel extends JPanel { - + + private static final Color DISCONNECTED = new GColor("color.border.provider.disconnected"); + public DecoratorPanel(JComponent component, boolean isConnected) { setLayout(new BorderLayout()); add(component); - setConnected( isConnected ); - } - - public void setConnected( boolean isConnected ) { - if ( !isConnected ) { - setBorder( BorderFactory.createLineBorder( Color.ORANGE, 2 ) ); - } - else { - setBorder( BorderFactory.createEmptyBorder() ); - } + setConnected(isConnected); } -// public void setNorthPanel(JComponent comp) { -// add(comp, BorderLayout.NORTH); -// } + public void setConnected(boolean isConnected) { + if (!isConnected) { + setBorder(BorderFactory.createLineBorder(DISCONNECTED, 2)); + } + else { + setBorder(BorderFactory.createEmptyBorder()); + } + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/ListingPanelContainer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/ListingPanelContainer.java index 49190d06f3..5c4061d60a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/ListingPanelContainer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/ListingPanelContainer.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +15,18 @@ */ package ghidra.app.nav; -import ghidra.app.util.viewer.util.TitledPanel; - import java.awt.BorderLayout; import java.awt.Color; import javax.swing.*; +import generic.theme.GColor; +import ghidra.app.util.viewer.util.TitledPanel; + public class ListingPanelContainer extends JPanel { + private static final Color DISCONNECTED = new GColor("color.border.provider.disconnected"); + private JSplitPane splitPane; private TitledPanel leftTitlePanel; private TitledPanel rightTitlePanelPanel; @@ -35,7 +37,7 @@ public class ListingPanelContainer extends JPanel { this.leftListingPanel = leftListingPanel; setLayout(new BorderLayout()); add(leftListingPanel); - setConnnected( isConnected ); + setConnnected(isConnected); } public ListingPanelContainer(JComponent leftListingPanel, JComponent rightListingPanel, @@ -46,12 +48,12 @@ public class ListingPanelContainer extends JPanel { setOtherPanel(rightListingPanel, leftTitle, rightTitle); } - public void setConnnected( boolean isConnected ) { - if ( !isConnected ) { - setBorder( BorderFactory.createLineBorder( Color.ORANGE, 2 ) ); + public void setConnnected(boolean isConnected) { + if (!isConnected) { + setBorder(BorderFactory.createLineBorder(DISCONNECTED, 2)); } else { - setBorder( BorderFactory.createEmptyBorder() ); + setBorder(BorderFactory.createEmptyBorder()); } } @@ -59,7 +61,8 @@ public class ListingPanelContainer extends JPanel { removeAll(); leftTitlePanel = new TitledPanel(leftTitle, leftListingPanel, 20); rightTitlePanelPanel = new TitledPanel(rightTitle, rightListingPanel, 20); - splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftTitlePanel, rightTitlePanelPanel); + splitPane = + new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftTitlePanel, rightTitlePanelPanel); splitPane.setDividerLocation(0.5); splitPane.setResizeWeight(0.5); add(splitPane, BorderLayout.CENTER); @@ -83,7 +86,8 @@ public class ListingPanelContainer extends JPanel { } public void setOrientation(boolean isSideBySide) { - splitPane.setOrientation(isSideBySide ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT); + splitPane.setOrientation( + isSideBySide ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT); splitPane.setDividerLocation(0.5); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NavigatableIconFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NavigatableIconFactory.java index 6285ab7611..8899e862ac 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NavigatableIconFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NavigatableIconFactory.java @@ -21,6 +21,8 @@ import java.awt.Point; import javax.swing.Icon; import javax.swing.ImageIcon; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors.Palette; import resources.MultiIcon; import resources.ResourceManager; import resources.icons.OvalColorIcon; @@ -28,8 +30,7 @@ import resources.icons.TranslateIcon; public class NavigatableIconFactory { - private static final ImageIcon SNAPSHOT_ICON = - ResourceManager.loadImage("images/camera-photo.png"); + private static final Icon SNAPSHOT_ICON = new GIcon("icon.provider.clone"); public static ImageIcon createSnapshotOverlayIcon(Icon primaryIcon) { MultiIcon newOuterIcon = new MultiIcon(primaryIcon); @@ -50,7 +51,7 @@ public class NavigatableIconFactory { private static ImageIcon getHighlightIcon(Icon primaryIcon) { int primaryWidth = primaryIcon.getIconWidth(); int primaryHeight = primaryIcon.getIconHeight(); - Color color = new Color(255, 255, 0, 255); + Color color = Palette.YELLOW; return ResourceManager.getImageIcon( new OvalColorIcon(color, primaryWidth + 4, primaryHeight + 4)); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisEnablementTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisEnablementTableModel.java index 0b3b5dd01e..d50651da09 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisEnablementTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisEnablementTableModel.java @@ -23,10 +23,11 @@ import javax.swing.JComponent; import javax.swing.JTable; import docking.widgets.table.*; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.docking.settings.Settings; import ghidra.framework.plugintool.ServiceProvider; import ghidra.framework.plugintool.ServiceProviderStub; -import ghidra.util.ColorUtils; import ghidra.util.table.column.AbstractGColumnRenderer; import ghidra.util.table.column.GColumnRenderer; @@ -36,8 +37,12 @@ import ghidra.util.table.column.GColumnRenderer; public class AnalysisEnablementTableModel extends GDynamicColumnTableModel { - private static Color BG_COLOR_NOT_DEFAULT_ENABLEMENT = new Color(255, 255, 200); - private static Color BG_COLOR_NOT_DEFAULT_ENABLEMENT_SELECTED = new Color(177, 212, 236); + private static Color FG_COLOR_PROTOTYPE = new GColor("color.fg.analysis.options.prototype"); + + private static Color BG_COLOR_NOT_DEFAULT_ENABLEMENT = + new GColor("color.bg.analysis.options.not.default.enablement"); + private static Color BG_COLOR_NOT_DEFAULT_ENABLEMENT_SELECTED = + new GColor("color.bg.analysis.options.not.default.enablement.selected"); private List analyzerStates; private AnalysisPanel panel; @@ -203,10 +208,10 @@ public class AnalysisEnablementTableModel } String analyzerName = (String) value; - if (analyzerName.endsWith(AnalysisPanel.PROTOTYPE)) { - component.setForeground( - ColorUtils.deriveForeground(component.getBackground(), ColorUtils.HUE_RED)); + if (!data.isSelected()) { + component.setForeground(FG_COLOR_PROTOTYPE); + } } AnalyzerEnablementState state = (AnalyzerEnablementState) data.getRowObject(); @@ -215,10 +220,10 @@ public class AnalysisEnablementTableModel return component; } - // not the default enablement + // not the default enablement + component.setForeground(Palette.BLACK); if (data.isSelected()) { component.setBackground(BG_COLOR_NOT_DEFAULT_ENABLEMENT_SELECTED); - component.setForeground(Color.BLACK); } else { component.setBackground(BG_COLOR_NOT_DEFAULT_ENABLEMENT); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalyzeAllOpenProgramsTask.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalyzeAllOpenProgramsTask.java index 93cb4dbc1d..7af6077bb5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalyzeAllOpenProgramsTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalyzeAllOpenProgramsTask.java @@ -25,6 +25,7 @@ import javax.swing.text.html.HTMLEditorKit; import docking.widgets.OptionDialog; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.GhidraOptions; import ghidra.app.services.ProgramManager; import ghidra.framework.model.DomainObject; @@ -270,7 +271,7 @@ class AnalyzeAllOpenProgramsTask extends Task { appendTableHeader(buffy); - String specialFontOpen = ""; + String specialFontOpen = ""; String specialFontClose = ""; for (Program program : validList) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java index 488fa252c7..44296a8617 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java @@ -21,6 +21,7 @@ import java.beans.PropertyEditorSupport; import javax.swing.*; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.framework.options.CustomOptionsEditor; import ghidra.util.layout.PairLayout; @@ -86,7 +87,7 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport } JPanel panel = new JPanel(new PairLayout(6, 10)); - + panel.add(new GDLabel("")); GDLabel label = new GDLabel("seconds", SwingConstants.RIGHT); panel.add(label); @@ -95,8 +96,8 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport label = new GDLabel(taskName, SwingConstants.RIGHT); label.setToolTipText(taskName); panel.add(label); - - Long timeMS = times.getTime(taskName); + + Long timeMS = times.getTime(taskName); if (timeMS == null) { continue; } @@ -115,12 +116,10 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport new JTextField(StoredAnalyzerTimes.formatTimeMS(times.getTotalTime())); valueField.setEditable(false); valueField.setHorizontalAlignment(SwingConstants.RIGHT); - valueField.setBorder(BorderFactory.createLineBorder(Color.black, 2)); + valueField.setBorder(BorderFactory.createLineBorder(Java.BORDER, 2)); panel.add(valueField); return panel; } - - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/ArchiveDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/ArchiveDialog.java index 266649b249..16468e6176 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/ArchiveDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/ArchiveDialog.java @@ -94,7 +94,7 @@ public class ArchiveDialog extends DialogComponentProvider { } }); Font font = archiveBrowse.getFont(); - archiveBrowse.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); + archiveBrowse.setFont(font.deriveFont(Font.BOLD)); archiveBrowse.setName("archiveBrowse"); // Layout the components. @@ -269,8 +269,10 @@ public class ArchiveDialog extends DialogComponentProvider { return true; } - return file.getAbsolutePath().toLowerCase().endsWith( - ArchivePlugin.ARCHIVE_EXTENSION); + return file.getAbsolutePath() + .toLowerCase() + .endsWith( + ArchivePlugin.ARCHIVE_EXTENSION); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/RestoreDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/RestoreDialog.java index 8dbf68512f..30dc9cfebd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/RestoreDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/RestoreDialog.java @@ -114,7 +114,7 @@ public class RestoreDialog extends DialogComponentProvider { } }); Font font = archiveBrowse.getFont(); - archiveBrowse.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); + archiveBrowse.setFont(font.deriveFont(Font.BOLD)); restoreLabel = new GDLabel(" Restore Directory "); restoreField = new JTextField(); @@ -131,7 +131,7 @@ public class RestoreDialog extends DialogComponentProvider { } }); font = restoreBrowse.getFont(); - restoreBrowse.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); + restoreBrowse.setFont(font.deriveFont(Font.BOLD)); projectNameLabel = new GDLabel(" Project Name "); projectNameField = new JTextField(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/AssemblyDualTextField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/AssemblyDualTextField.java index d1137a7634..2a0068ac4f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/AssemblyDualTextField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/AssemblyDualTextField.java @@ -27,6 +27,8 @@ import docking.EmptyBorderToggleButton; import docking.widgets.autocomplete.*; import docking.widgets.label.GDLabel; import docking.widgets.textfield.TextFieldLinker; +import generic.theme.*; +import generic.theme.GThemeDefaults.Colors; import ghidra.GhidraApplicationLayout; import ghidra.GhidraLaunchable; import ghidra.app.plugin.assembler.Assembler; @@ -41,7 +43,6 @@ import ghidra.program.model.address.Address; import ghidra.program.model.lang.LanguageID; import ghidra.program.model.listing.Instruction; import ghidra.util.NumericUtilities; -import resources.ResourceManager; /** * A pair of text fields suitable for guided assembly @@ -60,6 +61,14 @@ import resources.ResourceManager; * Otherwise, the usual autocompletion behavior is applied automatically. */ public class AssemblyDualTextField { + private static final String FONT_ID = "font.plugin.assembly.dual.text.field"; + private static Color FG_PREFERENCE_MOST = + new GColor("color.fg.plugin.assembler.completion.most"); + private static Color FG_PREFERENCE_MIDDLE = + new GColor("color.fg.plugin.assembler.completion.middle"); + private static Color FG_PREFERENCE_LEAST = + new GColor("color.fg.plugin.assembler.completion.least"); + protected final TextFieldLinker linker = new TextFieldLinker(); protected final JTextField mnemonic = new JTextField(); protected final JTextField operands = new JTextField(); @@ -179,8 +188,8 @@ public class AssemblyDualTextField { public AssemblyInstruction(String text, byte[] data, int preference) { // TODO?: Description to display constructor tree information super("", NumericUtilities.convertBytesToString(data, " "), - preference == 10000 ? Color.BLUE - : preference == 5000 ? new Color(0, 0, 128) : new Color(0, 128, 0), + preference == 10000 ? FG_PREFERENCE_MOST + : preference == 5000 ? FG_PREFERENCE_MIDDLE : FG_PREFERENCE_LEAST, -preference); this.data = data; } @@ -220,7 +229,7 @@ public class AssemblyDualTextField { private String text; public AssemblyError(String text, String desc) { - super(text, desc, Color.RED, 1); + super(text, desc, Colors.ERROR, 1); this.text = text; } @@ -326,7 +335,7 @@ public class AssemblyDualTextField { @Override protected void addContent(JPanel content) { Box controls = Box.createHorizontalBox(); - Icon icon = ResourceManager.loadImage("images/question_zero.png"); + Icon icon = new GIcon("icon.plugin.assembler.question"); EmptyBorderToggleButton button = new EmptyBorderToggleButton(icon); button.setToolTipText("Exhaust unspecified bits, otherwise zero them"); button.addActionListener((e) -> { @@ -442,7 +451,7 @@ public class AssemblyDualTextField { * Set the "existing" instruction used for ordering proposed instructions by "most similar" * * @see #computePreference(AssemblyResolvedPatterns) - * @param existing + * @param existing the existing instruction */ public void setExisting(Instruction existing) { this.existing = existing; @@ -468,6 +477,7 @@ public class AssemblyDualTextField { /** * For single mode: Get the text field containing the full assembly text + * @return the text field */ public JTextField getAssemblyField() { return assembly; @@ -550,18 +560,13 @@ public class AssemblyDualTextField { if (assembly.isVisible()) { throw new AssertionError(); } - else { - return VisibilityMode.DUAL_VISIBLE; - } + return VisibilityMode.DUAL_VISIBLE; } - else { - if (assembly.isVisible()) { - return VisibilityMode.SINGLE_VISIBLE; - } - else { - return VisibilityMode.INVISIBLE; - } + + if (assembly.isVisible()) { + return VisibilityMode.SINGLE_VISIBLE; } + return VisibilityMode.INVISIBLE; } /** @@ -653,8 +658,7 @@ public class AssemblyDualTextField { * @param field the field to configure */ protected void configureField(JTextField field) { - Font mono = new Font(Font.MONOSPACED, Font.PLAIN, 12); // TODO: Font size from options - field.setFont(mono); + Gui.registerFont(field, FONT_ID); } /** @@ -695,7 +699,6 @@ public class AssemblyDualTextField { * one are preferred. Last, the shortest instructions are preferred. * * @param rc a resolved instruction - * @param existing the instruction, if any, currently under the user's cursor * @return a preference */ protected int computePreference(AssemblyResolvedPatterns rc) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchDataAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchDataAction.java index 4951dbb01b..926057a9a5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchDataAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchDataAction.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.assembler; -import java.awt.Color; import java.awt.Font; import java.awt.event.FocusListener; import java.awt.event.KeyListener; @@ -26,6 +25,7 @@ import docking.action.KeyBindingData; import docking.action.MenuData; import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GThemeDefaults.Colors; import ghidra.framework.plugintool.Plugin; import ghidra.program.database.util.ProgramTransaction; import ghidra.program.model.address.*; @@ -56,7 +56,7 @@ public class PatchDataAction extends AbstractPatchAction { setKeyBindingData(new KeyBindingData(KEYBIND_PATCH_DATA)); setHelpLocation(new HelpLocation(owner.getName(), "patch_data")); - input.setBorder(BorderFactory.createLineBorder(Color.RED, 2)); + input.setBorder(BorderFactory.createLineBorder(Colors.ERROR, 2)); init(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchInstructionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchInstructionAction.java index 84b1fbb6d9..48184fbc21 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchInstructionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/assembler/PatchInstructionAction.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.assembler; -import java.awt.Color; import java.awt.Font; import java.awt.event.FocusListener; import java.awt.event.KeyListener; @@ -33,6 +32,7 @@ import docking.action.MenuData; import docking.widgets.autocomplete.*; import docking.widgets.fieldpanel.*; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.assembler.Assembler; import ghidra.app.plugin.assembler.Assemblers; import ghidra.app.plugin.core.assembler.AssemblyDualTextField.*; @@ -146,9 +146,9 @@ public class PatchInstructionAction extends AbstractPatchAction { setKeyBindingData(new KeyBindingData(KEYBIND_PATCH_INSTRUCTION)); setHelpLocation(new HelpLocation(owner.getName(), "patch_instruction")); - input.getMnemonicField().setBorder(BorderFactory.createLineBorder(Color.RED, 2)); - input.getOperandsField().setBorder(BorderFactory.createLineBorder(Color.RED, 2)); - input.getAssemblyField().setBorder(BorderFactory.createLineBorder(Color.RED, 2)); + input.getMnemonicField().setBorder(BorderFactory.createLineBorder(Colors.ERROR, 2)); + input.getOperandsField().setBorder(BorderFactory.createLineBorder(Colors.ERROR, 2)); + input.getAssemblyField().setBorder(BorderFactory.createLineBorder(Colors.ERROR, 2)); input.getAutocompleter().addAutocompletionListener(listenerForAccept); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkNavigator.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkNavigator.java index 469c83fc2e..bf29ce1268 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkNavigator.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkNavigator.java @@ -17,10 +17,12 @@ package ghidra.app.plugin.core.bookmark; import java.awt.Color; -import javax.swing.ImageIcon; +import javax.swing.Icon; import org.apache.commons.lang3.StringUtils; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.app.services.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSet; @@ -28,7 +30,6 @@ import ghidra.program.model.listing.*; import ghidra.program.util.MarkerLocation; import ghidra.util.HTMLUtilities; import ghidra.util.Swing; -import resources.ResourceManager; /** * Handles navigation/display of bookmarks in the browser marker margins. @@ -37,13 +38,12 @@ public class BookmarkNavigator { private static final int BIG_CHANGE = 1000; - final static ImageIcon NOTE_ICON = ResourceManager.loadImage("images/notes.gif"); - final static ImageIcon INFO_ICON = ResourceManager.loadImage("images/information.png"); - final static ImageIcon WARNING_ICON = ResourceManager.loadImage("images/warning.png"); - final static ImageIcon ERROR_ICON = ResourceManager.loadImage("images/edit-delete.png"); - final static ImageIcon ANALYSIS_ICON = - ResourceManager.loadImage("images/applications-system.png"); - final static ImageIcon DEFAULT_ICON = ResourceManager.loadImage("images/unknown.gif"); + final static Icon NOTE_ICON = new GIcon("icon.plugin.bookmark.type.note"); + final static Icon INFO_ICON = new GIcon("icon.plugin.bookmark.type.info"); + final static Icon WARNING_ICON = new GIcon("icon.plugin.bookmark.type.warning"); + final static Icon ERROR_ICON = new GIcon("icon.plugin.bookmark.type.error"); + final static Icon ANALYSIS_ICON = new GIcon("icon.plugin.bookmark.type.analysis"); + final static Icon DEFAULT_ICON = new GIcon("icon.plugin.bookmark.type.default"); final static int NOTE_PRIORITY = MarkerService.BOOKMARK_PRIORITY; final static int ERROR_PRIORITY = MarkerService.BOOKMARK_PRIORITY + BIG_CHANGE; @@ -52,12 +52,12 @@ public class BookmarkNavigator { final static int ANALYSIS_PRIORITY = MarkerService.BOOKMARK_PRIORITY + 6; final static int DEFAULT_PRIORITY = MarkerService.BOOKMARK_PRIORITY + 8; - final static Color NOTE_COLOR = new Color(128, 0, 255); // Purple - final static Color INFO_COLOR = new Color(0, 255, 255); // Cyan - final static Color WARNING_COLOR = new Color(255, 196, 51); // Dark Yellow - final static Color ERROR_COLOR = new Color(204, 0, 51); // Dark Red - final static Color ANALYSIS_COLOR = new Color(255, 128, 0); // Orange - final static Color DEFAULT_COLOR = new Color(255, 0, 255); // Magenta + final static Color NOTE_COLOR = new GColor("color.bg.plugin.bookmark.note"); + final static Color INFO_COLOR = new GColor("color.bg.plugin.bookmark.info"); + final static Color WARNING_COLOR = new GColor("color.bg.plugin.bookmark.warning"); + final static Color ERROR_COLOR = new GColor("color.bg.plugin.bookmark.error"); + final static Color ANALYSIS_COLOR = new GColor("color.bg.plugin.bookmark.analysis"); + final static Color DEFAULT_COLOR = new GColor("color.bg.plugin.bookmark.default"); private String type; private MarkerService markerService; @@ -80,7 +80,7 @@ public class BookmarkNavigator { priority = DEFAULT_PRIORITY; } - ImageIcon icon = bmt.getIcon(); + Icon icon = bmt.getIcon(); if (icon == null) { icon = DEFAULT_ICON; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java index 7759366a64..0fa54915d9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java @@ -26,6 +26,7 @@ import docking.Tool; import docking.action.*; import docking.actions.PopupActionProvider; import docking.widgets.table.GTable; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.plugin.PluginCategoryNames; @@ -43,7 +44,8 @@ import ghidra.program.util.*; import ghidra.util.Msg; import ghidra.util.table.SelectionNavigationAction; import ghidra.util.task.SwingUpdateManager; -import resources.*; +import resources.Icons; +import resources.MultiIconBuilder; /** * Plugin to for adding/deleting/editing bookmarks. @@ -115,7 +117,7 @@ public class BookmarkPlugin extends ProgramPlugin tool.addAction(addAction); MultiIconBuilder builder = new MultiIconBuilder(Icons.CONFIGURE_FILTER_ICON); - builder.addLowerRightIcon(ResourceManager.loadImage("images/check.png")); + builder.addLowerRightIcon(new GIcon("icon.plugin.bookmark.add")); Icon filterTypesChanged = builder.build(); Icon filterTypesUnchanged = Icons.CONFIGURE_FILTER_ICON; DockingAction filterAction = new DockingAction("Filter Bookmarks", getName()) { @@ -150,7 +152,7 @@ public class BookmarkPlugin extends ProgramPlugin provider.delete(); } }; - Icon icon = ResourceManager.loadImage("images/edit-delete.png"); + Icon icon = new GIcon("icon.plugin.bookmark.delete"); deleteAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0)); deleteAction.setPopupMenuData(new MenuData(new String[] { "Delete" }, icon)); deleteAction.setDescription("Delete Selected Bookmarks"); @@ -164,7 +166,7 @@ public class BookmarkPlugin extends ProgramPlugin select(provider.getBookmarkLocations()); } }; - icon = ResourceManager.loadImage("images/text_align_justify.png"); + icon = new GIcon("icon.plugin.bookmark.select"); selectionAction.setPopupMenuData( new MenuData(new String[] { "Select Bookmark Locations" }, icon)); selectionAction.setToolBarData(new ToolBarData(icon)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/CreateBookmarkDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/CreateBookmarkDialog.java index ec815e7a67..986bd75627 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/CreateBookmarkDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/CreateBookmarkDialog.java @@ -49,10 +49,6 @@ public class CreateBookmarkDialog extends DialogComponentProvider { private JTextField commentTextField; private JCheckBox selectionCB; - /** - * Creates new CreateBookmarkDialog - * - */ CreateBookmarkDialog(BookmarkPlugin plugin, CodeUnit cu, boolean hasSelection) { super(BookmarkType.NOTE + " Bookmark", true, true, true, false); @@ -71,6 +67,7 @@ public class CreateBookmarkDialog extends DialogComponentProvider { setHelpLocation(new HelpLocation("BookmarkPlugin", "CreateBookmarkDialog")); } + @Override public void dispose() { this.plugin = null; this.program = null; @@ -202,7 +199,7 @@ public class CreateBookmarkDialog extends DialogComponentProvider { gbc.anchor = GridBagConstraints.WEST; mainPanel.add(commentTextField, gbc); - ImageIcon icon = BookmarkNavigator.NOTE_ICON; + Icon icon = BookmarkNavigator.NOTE_ICON; JLabel imageLabel = new GIconLabel(icon); imageLabel.setPreferredSize( new Dimension(icon.getIconWidth() + 20, icon.getIconHeight() + 20)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java index 61a457b56b..797ffd5954 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java @@ -23,6 +23,7 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.DockingAction; import docking.action.MenuData; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.context.ListingActionContext; import ghidra.app.plugin.PluginCategoryNames; @@ -37,7 +38,6 @@ import ghidra.program.model.symbol.ReferenceManager; import ghidra.program.util.ProgramLocation; import ghidra.util.HelpLocation; import resources.Icons; -import resources.ResourceManager; /** * Assuming a function foo, this plugin will show all callers of foo and all @@ -58,9 +58,8 @@ import resources.ResourceManager; public class CallTreePlugin extends ProgramPlugin { static final Icon PROVIDER_ICON = Icons.ARROW_DOWN_RIGHT_ICON; - static final Icon FUNCTION_ICON = ResourceManager.loadImage("images/FunctionScope.gif"); - static final Icon RECURSIVE_ICON = - ResourceManager.loadImage("images/arrow_rotate_clockwise.png"); + static final Icon FUNCTION_ICON = new GIcon("icon.plugin.calltree.function"); + static final Icon RECURSIVE_ICON = new GIcon("icon.plugin.calltree.recursive"); private List providers = new ArrayList<>(); private DockingAction showCallTreeFromMenuAction; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java index d39226f30d..52ee26081e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java @@ -33,6 +33,7 @@ import docking.widgets.tree.*; import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin; import docking.widgets.tree.support.GTreeSelectionListener; import docking.widgets.tree.tasks.GTreeExpandAllTask; +import generic.theme.GIcon; import ghidra.app.events.ProgramLocationPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.services.GoToService; @@ -51,18 +52,18 @@ import ghidra.util.exception.CancelledException; import ghidra.util.task.SwingUpdateManager; import ghidra.util.task.TaskMonitor; import resources.Icons; -import resources.ResourceManager; public class CallTreeProvider extends ComponentProviderAdapter implements DomainObjectListener { static final String EXPAND_ACTION_NAME = "Fully Expand Selected Nodes"; static final String TITLE = "Function Call Trees"; - private static final Icon EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif"); + private static final Icon EMPTY_ICON = Icons.EMPTY_ICON; private static final Icon EXPAND_ICON = Icons.EXPAND_ALL_ICON; private static final Icon COLLAPSE_ICON = Icons.COLLAPSE_ALL_ICON; - private static ImageIcon REFRESH_ICON = Icons.REFRESH_ICON; - private static Icon REFRESH_NOT_NEEDED_ICON = ResourceManager.getDisabledIcon(REFRESH_ICON, 60); + private static Icon REFRESH_ICON = new GIcon("icon.plugin.calltree.refresh"); + private static Icon REFRESH_NOT_NEEDED_ICON = + new GIcon("icon.plugin.calltree.refresh.not.needed"); private static final String RECURSE_DEPTH_PROPERTY_NAME = "call.tree.recurse.depth"; private static final String DEFAULT_RECURSE_DEPTH = "5"; @@ -350,8 +351,8 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain return true; } }; - goToSourceAction.setPopupMenuData( - new MenuData(new String[] { "Go To Call Source" }, goToMenu)); + goToSourceAction + .setPopupMenuData(new MenuData(new String[] { "Go To Call Source" }, goToMenu)); goToSourceAction.setHelpLocation( new HelpLocation(plugin.getName(), "Call_Tree_Context_Action_Goto_Source")); tool.addLocalAction(this, goToSourceAction); @@ -365,12 +366,12 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain doUpdate(); } }; - filterDuplicates.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/application_double.png"), - filterOptionsToolbarGroup, "1")); + filterDuplicates + .setToolBarData(new ToolBarData(new GIcon("icon.plugin.calltree.filter.duplicates"), + filterOptionsToolbarGroup, "1")); filterDuplicates.setSelected(true); - filterDuplicates.setHelpLocation( - new HelpLocation(plugin.getName(), "Call_Tree_Action_Filter")); + filterDuplicates + .setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Action_Filter")); tool.addLocalAction(this, filterDuplicates); // @@ -393,8 +394,8 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain "Recurse Depth window."); + "Invalidated equates can be automatically removed now or
Limits the depth to " + "which recursing tree operations" + "
will go. Example operations include Expand All and filtering"); recurseIcon = new NumberIcon(recurseDepth.get()); - recurseDepthAction.setToolBarData( - new ToolBarData(recurseIcon, filterOptionsToolbarGroup, "2")); + recurseDepthAction + .setToolBarData(new ToolBarData(recurseIcon, filterOptionsToolbarGroup, "2")); recurseDepthAction.setHelpLocation( new HelpLocation(plugin.getName(), "Call_Tree_Action_Recurse_Depth")); @@ -414,8 +415,8 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain "Listing to
the source location of the call"); navigationOutgoingAction.setToolBarData(new ToolBarData( Icons.NAVIGATE_ON_OUTGOING_EVENT_ICON, navigationOptionsToolbarGroup, "1")); - navigationOutgoingAction.setHelpLocation( - new HelpLocation(plugin.getName(), "Call_Tree_Action_Navigation")); + navigationOutgoingAction + .setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Action_Navigation")); tool.addLocalAction(this, navigationOutgoingAction); // @@ -503,7 +504,7 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain return true; } }; - ImageIcon icon = ResourceManager.loadImage("images/text_align_justify.png"); + Icon icon = new GIcon("icon.plugin.calltree.filter.select.source"); selectSourceAction.setPopupMenuData( new MenuData(new String[] { "Select Call Source" }, icon, selectionMenuGroup)); selectSourceAction.setHelpLocation( @@ -581,8 +582,7 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain return currentFunction != null; } }; - homeAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/go-home.png"), homeToolbarGroup)); + homeAction.setToolBarData(new ToolBarData(Icons.HOME_ICON, homeToolbarGroup)); homeAction.setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Action_Home")); tool.addLocalAction(this, homeAction); @@ -596,8 +596,8 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain refreshAction.setEnabled(true); refreshAction.setDescription("Push at any time to refresh the current trees.
" + "This is highlighted when the data may be stale.
"); - refreshAction.setHelpLocation( - new HelpLocation(plugin.getName(), "Call_Tree_Action_Refresh")); + refreshAction + .setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Action_Refresh")); tool.addLocalAction(this, refreshAction); // @@ -671,8 +671,8 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain "Call_Tree_Context_Action_Show_Call_Tree_For_Function")); newCallTree.setPopupMenuData(new MenuData(new String[] { "Show Call Tree For Function" }, CallTreePlugin.PROVIDER_ICON, newTreeMenu)); - newCallTree.setDescription("Show the Function Call Tree window for the function " + - "selected in the call tree"); + newCallTree.setDescription( + "Show the Function Call Tree window for the function " + "selected in the call tree"); tool.addLocalAction(this, newCallTree); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/DeadEndNode.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/DeadEndNode.java index 96e19bb588..bce14bc4f6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/DeadEndNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/DeadEndNode.java @@ -15,6 +15,14 @@ */ package ghidra.app.plugin.core.calltree; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.swing.Icon; + +import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; @@ -23,18 +31,9 @@ import ghidra.program.util.ProgramLocation; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.widgets.tree.GTreeNode; - public class DeadEndNode extends CallNode { - private static final Icon ICON = ResourceManager.loadImage("images/stopNode.png"); + private static final Icon ICON = new GIcon("icon.plugin.calltree.node.dead.end"); private final Reference reference; private String name; @@ -100,6 +99,6 @@ public class DeadEndNode extends CallNode { @Override public ListgenerateChildren(TaskMonitor monitor) throws CancelledException { - return new ArrayList (); + return new ArrayList<>(); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/ExternalCallNode.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/ExternalCallNode.java index 8e9fbc8655..d4269e8791 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/ExternalCallNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/ExternalCallNode.java @@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.swing.Icon; import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.util.FunctionSignatureFieldLocation; @@ -29,12 +30,11 @@ import ghidra.program.util.ProgramLocation; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; import resources.MultiIcon; -import resources.ResourceManager; import resources.icons.TranslateIcon; public class ExternalCallNode extends CallNode { - private static final Icon EXTERNAL_ICON = ResourceManager.loadImage("images/package.png"); + private static final Icon EXTERNAL_ICON = new GIcon("icon.plugin.calltree.node.external"); private final Icon EXTERNAL_FUNCTION_ICON; private final Icon baseIcon; @@ -77,7 +77,7 @@ public class ExternalCallNode extends CallNode { @Override public List generateChildren(TaskMonitor monitor) throws CancelledException { - return new ArrayList (); + return new ArrayList<>(); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/checksums/ComputeChecksumsProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/checksums/ComputeChecksumsProvider.java index fb6304edab..6b06ef4886 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/checksums/ComputeChecksumsProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/checksums/ComputeChecksumsProvider.java @@ -16,7 +16,6 @@ package ghidra.app.plugin.core.checksums; import java.awt.BorderLayout; -import java.awt.Color; import java.util.ArrayList; import java.util.List; @@ -25,14 +24,14 @@ import javax.swing.*; import docking.ActionContext; import docking.action.*; import docking.widgets.label.GDLabel; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.context.ProgramContextAction; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.util.HelpLocation; import ghidra.util.classfinder.ClassSearcher; import ghidra.util.table.GhidraTable; import ghidra.util.task.TaskLauncher; -import resources.Icons; -import resources.ResourceManager; /** * Provider to invoke computation of various checksums and display them in a table. @@ -97,7 +96,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { errorStatus = new GDLabel(" "); errorStatus.setName("message"); errorStatus.setHorizontalAlignment(SwingConstants.CENTER); - errorStatus.setForeground(Color.RED); + errorStatus.setForeground(Colors.ERROR); errorStatus.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5)); main.add(errorStatus, BorderLayout.SOUTH); @@ -233,7 +232,8 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { }; computeAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "compute")); computeAction.setEnabled(true); - computeAction.setToolBarData(new ToolBarData(Icons.REFRESH_ICON, null)); + computeAction + .setToolBarData(new ToolBarData(new GIcon("icon.plugin.checksum.compute"), null)); computeAction.setDescription("Refreshes checksums"); selectionAction = new ToggleDockingAction("On Selection", plugin.getName()) { @@ -251,7 +251,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { selectionAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "On_Selection")); selectionAction.setEnabled(plugin.hasSelection()); selectionAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/NextSelectionBlock16.gif"), null)); + new ToolBarData(new GIcon("icon.plugin.checksum.select"), null)); selectionAction.setDescription("When toggled, generates checksums on " + "selection. Otherwise checksums are generated over the entire program"); @@ -269,7 +269,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { showHexAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "As_Hex")); showHexAction.setEnabled(true); showHexAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/hexData.png"), null)); + new ToolBarData(new GIcon("icon.plugin.checksum.show.hex"), null)); showHexAction.setDescription("Toggle to show the hex values instead of decimal values."); xorAction = new ToggleDockingAction("XOR Checksum Values", plugin.getName()) { @@ -289,7 +289,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { xorAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "xor")); xorAction.setEnabled(true); xorAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/xor.png"), null)); + new ToolBarData(new GIcon("icon.plugin.checksum.xor"), null)); xorAction.setDescription("Toggle to recompute values with a xor operation."); carryAction = new ToggleDockingAction("Carry Checksum Values", plugin.getName()) { @@ -310,7 +310,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { carryAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "carry")); carryAction.setEnabled(true); carryAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/carry.png"), null)); + new ToolBarData(new GIcon("icon.plugin.checksum.carry"), null)); carryAction.setDescription("Toggle to recompute values with a carry operation."); onesCompAction = new ToggleDockingAction("Ones Complement", plugin.getName()) { @@ -330,7 +330,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { onesCompAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "ones_comp")); onesCompAction.setEnabled(true); onesCompAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/onesComplement.png"), null)); + new ToolBarData(new GIcon("icon.plugin.checksum.ones.complement"), null)); onesCompAction.setDescription("Toggle to recompute values with a one's complement."); twosCompAction = new ToggleDockingAction("Twos Complement", plugin.getName()) { @@ -350,7 +350,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter { twosCompAction.setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "twos_comp")); twosCompAction.setEnabled(true); twosCompAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/twosComplement.png"), null)); + new ToolBarData(new GIcon("icon.plugin.checksum.twos.complement"), null)); twosCompAction.setDescription("Toggle to recompute values with a two's complement."); tool.addLocalAction(this, onesCompAction); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/ClipboardPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/ClipboardPlugin.java index 31f5717463..8f37c8a0b0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/ClipboardPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/ClipboardPlugin.java @@ -29,6 +29,7 @@ import javax.swing.event.ChangeListener; import docking.*; import docking.action.*; import docking.dnd.GClipboard; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.context.ListingActionContext; import ghidra.app.plugin.PluginCategoryNames; @@ -43,7 +44,6 @@ import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.task.*; -import resources.ResourceManager; //@formatter:off @PluginInfo( @@ -361,7 +361,7 @@ public class ClipboardPlugin extends ProgramPlugin implements ClipboardOwner, Cl this.clipboardService = clipboardService; setPopupMenuData(new MenuData(new String[] { "Copy" }, "Clipboard")); - setToolBarData(new ToolBarData(ResourceManager.loadImage("images/page_white_copy.png"), + setToolBarData(new ToolBarData(new GIcon("icon.plugin.clipboard.copy"), "Clipboard")); setKeyBindingData(new KeyBindingData(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); setHelpLocation(new HelpLocation("ClipboardPlugin", "Copy")); @@ -395,7 +395,7 @@ public class ClipboardPlugin extends ProgramPlugin implements ClipboardOwner, Cl setPopupMenuData(new MenuData(new String[] { "Paste" }, "Clipboard")); setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/page_paste.png"), "Clipboard")); + new ToolBarData(new GIcon("icon.plugin.clipboard.paste"), "Clipboard")); setKeyBindingData(new KeyBindingData(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK)); setHelpLocation(new HelpLocation("ClipboardPlugin", "Paste")); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java index a2e47229dd..0f0ddb2889 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java @@ -20,7 +20,7 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -30,6 +30,8 @@ import docking.widgets.fieldpanel.*; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.FieldSelection; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.GhidraOptions; import ghidra.app.events.ProgramHighlightPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent; @@ -55,21 +57,27 @@ import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; import ghidra.util.*; -import resources.ResourceManager; public abstract class AbstractCodeBrowserPlugin extends Plugin implements CodeViewerService, CodeFormatService, OptionsChangeListener, FormatModelListener, DomainObjectListener, CodeBrowserPluginInterface { - private static final Color CURSOR_LINE_COLOR = GhidraOptions.DEFAULT_CURSOR_LINE_COLOR; - private static final String CURSOR_COLOR = "Cursor.Cursor Color - Focused"; - private static final String UNFOCUSED_CURSOR_COLOR = "Cursor.Cursor Color - Unfocused"; - private static final String BLINK_CURSOR = "Cursor.Blink Cursor"; - private static final String MOUSE_WHEEL_HORIZONTAL_SCROLLING = "Mouse.Horizontal Scrolling"; + private static final String CURSOR_COLOR_OPTIONS_NAME = "Cursor.Cursor Color - Focused"; + private static final String UNFOCUSED_CURSOR_COLOR_OPTIONS_NAME = + "Cursor.Cursor Color - Unfocused"; + private static final String BLINK_CURSOR_OPTIONS_NAME = "Cursor.Blink Cursor"; + private static final String MOUSE_WHEEL_HORIZONTAL_SCROLLING_OPTIONS_NAME = + "Mouse.Horizontal Scrolling"; + + //@formatter:off + private static final GColor FOCUSED_CURSOR_COLOR = new GColor("color.cursor.focused.listing"); + private static final GColor UNFOCUSED_CURSOR_COLOR = new GColor("color.cursor.unfocused.listing"); + private static final GColor CURRENT_LINE_HIGHLIGHT_COLOR = new GColor("color.bg.currentline.listing"); + //@formatter:on // - Icon - - private ImageIcon CURSOR_LOC_ICON = - ResourceManager.loadImage("images/cursor_arrow_flipped.gif"); + private static final Icon CURSOR_LOC_ICON = + new GIcon("icon.plugin.codebrowser.cursor.location"); protected final P connectedProvider; protected List
disconnectedProviders = new ArrayList<>(); protected FormatManager formatMgr; @@ -406,15 +414,15 @@ public abstract class AbstractCodeBrowserPlugin
ex highlightMarkers.setMarkerColor(color); } } - else if (optionName.equals(CURSOR_COLOR)) { + else if (optionName.equals(CURSOR_COLOR_OPTIONS_NAME)) { Color color = ((Color) newValue); fieldPanel.setFocusedCursorColor(color); } - else if (optionName.equals(UNFOCUSED_CURSOR_COLOR)) { + else if (optionName.equals(UNFOCUSED_CURSOR_COLOR_OPTIONS_NAME)) { Color color = ((Color) newValue); fieldPanel.setNonFocusCursorColor(color); } - else if (optionName.equals(BLINK_CURSOR)) { + else if (optionName.equals(BLINK_CURSOR_OPTIONS_NAME)) { Boolean isBlinkCursor = ((Boolean) newValue); fieldPanel.setBlinkCursor(isBlinkCursor); } @@ -430,7 +438,7 @@ public abstract class AbstractCodeBrowserPlugin
ex currentCursorMarkers.setColoringBackground(isHighlightCursorLine); } } - else if (optionName.equals(MOUSE_WHEEL_HORIZONTAL_SCROLLING)) { + else if (optionName.equals(MOUSE_WHEEL_HORIZONTAL_SCROLLING_OPTIONS_NAME)) { fieldPanel.setHorizontalScrollingEnabled((Boolean) newValue); } @@ -547,26 +555,32 @@ public abstract class AbstractCodeBrowserPlugin
ex HelpLocation helpLocation = new HelpLocation(getName(), "Selection Colors"); fieldOptions.getOptions("Selection Colors").setOptionsHelpLocation(helpLocation); - fieldOptions.registerOption(GhidraOptions.OPTION_SELECTION_COLOR, - GhidraOptions.DEFAULT_SELECTION_COLOR, helpLocation, + fieldOptions.registerThemeColorBinding(GhidraOptions.OPTION_SELECTION_COLOR, + GhidraOptions.DEFAULT_SELECTION_COLOR.getId(), helpLocation, "The selection color in the browser."); - fieldOptions.registerOption(GhidraOptions.OPTION_HIGHLIGHT_COLOR, - GhidraOptions.DEFAULT_HIGHLIGHT_COLOR, helpLocation, + fieldOptions.registerThemeColorBinding(GhidraOptions.OPTION_HIGHLIGHT_COLOR, + GhidraOptions.DEFAULT_HIGHLIGHT_COLOR.getId(), helpLocation, "The highlight color in the browser."); - fieldOptions.registerOption(CURSOR_COLOR, Color.RED, helpLocation, + fieldOptions.registerThemeColorBinding(CURSOR_COLOR_OPTIONS_NAME, + FOCUSED_CURSOR_COLOR.getId(), + helpLocation, "The color of the cursor in the browser."); - fieldOptions.registerOption(UNFOCUSED_CURSOR_COLOR, Color.PINK, helpLocation, + fieldOptions.registerThemeColorBinding(UNFOCUSED_CURSOR_COLOR_OPTIONS_NAME, + UNFOCUSED_CURSOR_COLOR.getId(), + helpLocation, "The color of the cursor in the browser when the browser does not have focus."); - fieldOptions.registerOption(BLINK_CURSOR, true, helpLocation, + fieldOptions.registerOption(BLINK_CURSOR_OPTIONS_NAME, true, helpLocation, "When selected, the cursor will blink when the containing window is focused."); - fieldOptions.registerOption(GhidraOptions.HIGHLIGHT_CURSOR_LINE_COLOR, CURSOR_LINE_COLOR, - helpLocation, "The background color of the line where the cursor is located"); + fieldOptions.registerThemeColorBinding(GhidraOptions.HIGHLIGHT_CURSOR_LINE_COLOR, + CURRENT_LINE_HIGHLIGHT_COLOR.getId(), helpLocation, + "The background color of the line where the cursor is located"); fieldOptions.registerOption(GhidraOptions.HIGHLIGHT_CURSOR_LINE, true, helpLocation, "Toggles highlighting background color of line containing the cursor"); helpLocation = new HelpLocation(getName(), "Keyboard_Controls_Shift"); - fieldOptions.registerOption(MOUSE_WHEEL_HORIZONTAL_SCROLLING, true, helpLocation, + fieldOptions.registerOption(MOUSE_WHEEL_HORIZONTAL_SCROLLING_OPTIONS_NAME, true, + helpLocation, "Enables horizontal scrolling by holding the Shift key while " + "using the mouse scroll wheel"); @@ -581,28 +595,29 @@ public abstract class AbstractCodeBrowserPlugin
ex } color = - fieldOptions.getColor(GhidraOptions.OPTION_HIGHLIGHT_COLOR, new Color(255, 255, 180)); + fieldOptions.getColor(GhidraOptions.OPTION_HIGHLIGHT_COLOR, + GhidraOptions.DEFAULT_HIGHLIGHT_COLOR); MarkerSet highlightMarkers = getHighlightMarkers(currentProgram); fieldPanel.setHighlightColor(color); if (highlightMarkers != null) { highlightMarkers.setMarkerColor(color); } - color = fieldOptions.getColor(CURSOR_COLOR, Color.RED); + color = fieldOptions.getColor(CURSOR_COLOR_OPTIONS_NAME, FOCUSED_CURSOR_COLOR); fieldPanel.setFocusedCursorColor(color); - color = fieldOptions.getColor(UNFOCUSED_CURSOR_COLOR, Color.PINK); + color = fieldOptions.getColor(UNFOCUSED_CURSOR_COLOR_OPTIONS_NAME, UNFOCUSED_CURSOR_COLOR); fieldPanel.setNonFocusCursorColor(color); - Boolean isBlinkCursor = fieldOptions.getBoolean(BLINK_CURSOR, true); + Boolean isBlinkCursor = fieldOptions.getBoolean(BLINK_CURSOR_OPTIONS_NAME, true); fieldPanel.setBlinkCursor(isBlinkCursor); boolean horizontalScrollingEnabled = - fieldOptions.getBoolean(MOUSE_WHEEL_HORIZONTAL_SCROLLING, true); + fieldOptions.getBoolean(MOUSE_WHEEL_HORIZONTAL_SCROLLING_OPTIONS_NAME, true); fieldPanel.setHorizontalScrollingEnabled(horizontalScrollingEnabled); - cursorHighlightColor = - fieldOptions.getColor(GhidraOptions.HIGHLIGHT_CURSOR_LINE_COLOR, CURSOR_LINE_COLOR); + cursorHighlightColor = fieldOptions.getColor(GhidraOptions.HIGHLIGHT_CURSOR_LINE_COLOR, + CURRENT_LINE_HIGHLIGHT_COLOR); isHighlightCursorLine = fieldOptions.getBoolean(GhidraOptions.HIGHLIGHT_CURSOR_LINE, true); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java index 50860c6f18..ed427d83e5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java @@ -15,10 +15,11 @@ */ package ghidra.app.plugin.core.codebrowser; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.action.builder.ActionBuilder; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; @@ -38,7 +39,6 @@ import ghidra.util.datastruct.Accumulator; import ghidra.util.exception.CancelledException; import ghidra.util.table.*; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * Plugin for adding some basic selection actions for Code Browser Listings. @@ -129,7 +129,7 @@ public class CodeBrowserSelectionPlugin extends Plugin { GhidraProgramTableModel
model = createTableModel(program, codeUnits, selection); String title = "Selection Table"; - ImageIcon markerIcon = ResourceManager.loadImage("images/searchm_obj.gif"); + Icon markerIcon = new GIcon("icon.plugin.codebrowser.cursor.marker"); TableComponentProvider tableProvider = tableService.showTableWithMarkers(title + " " + model.getName(), "Selection", model, PluginConstants.SEARCH_HIGHLIGHT_COLOR, markerIcon, title, null); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java index e506d03b6d..ec4036e92e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java @@ -37,6 +37,7 @@ import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.HoverHandler; import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import docking.widgets.fieldpanel.support.*; +import generic.theme.GIcon; import ghidra.app.nav.*; import ghidra.app.plugin.core.clipboard.CodeBrowserClipboardProvider; import ghidra.app.plugin.core.codebrowser.actions.*; @@ -47,6 +48,7 @@ import ghidra.app.util.viewer.field.FieldFactory; import ghidra.app.util.viewer.format.*; import ghidra.app.util.viewer.listingpanel.*; import ghidra.app.util.viewer.multilisting.MultiListingLayoutModel; +import ghidra.app.util.viewer.options.ListingDisplayOptionsEditor; import ghidra.app.util.viewer.util.FieldNavigator; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.NavigatableComponentProviderAdapter; @@ -56,7 +58,6 @@ import ghidra.program.model.listing.*; import ghidra.program.util.*; import ghidra.util.HelpLocation; import ghidra.util.Swing; -import resources.ResourceManager; public class CodeViewerProvider extends NavigatableComponentProviderAdapter implements ProgramLocationListener, ProgramSelectionListener, Draggable, Droppable, @@ -67,12 +68,12 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter private static final String TITLE = NAME + ": "; private static final Icon LISTING_FORMAT_EXPAND_ICON = - ResourceManager.loadImage("images/field.header.down.png"); + new GIcon("icon.plugin.codebrowser.format.expand"); private static final Icon LISTING_FORMAT_COLLAPSE_ICON = - ResourceManager.loadImage("images/field.header.up.png"); + new GIcon("icon.plugin.codebrowser.format.collapse"); - private static final Icon HOVER_ON_ICON = ResourceManager.loadImage("images/hoverOn.gif"); - private static final Icon HOVER_OFF_ICON = ResourceManager.loadImage("images/hoverOff.gif"); + private static final Icon HOVER_ON_ICON = new GIcon("icon.plugin.codebrowser.hover.on"); + private static final Icon HOVER_OFF_ICON = new GIcon("icon.plugin.codebrowser.hover.off"); private static final String HOVER_MODE = "Hover Mode"; private static final String DIVIDER_LOCATION = "DividerLocation"; @@ -128,9 +129,9 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter // note: the owner has not changed, just the name; remove sometime after version 10 String owner = plugin.getName(); ComponentProvider.registerProviderNameOwnerChange(OLD_NAME, owner, NAME, owner); - + registerAdjustableFontId(ListingDisplayOptionsEditor.DEFAULT_FONT_ID); setConnected(isConnected); - setIcon(ResourceManager.loadImage("images/Browser.gif")); + setIcon(new GIcon("icon.plugin.codebrowser.provider")); if (!isConnected) { setTransient(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/LayeredColorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/LayeredColorModel.java index 4f786ec39b..c9735ee369 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/LayeredColorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/LayeredColorModel.java @@ -20,6 +20,7 @@ import java.math.BigInteger; import ghidra.app.util.viewer.listingpanel.ListingBackgroundColorModel; import ghidra.app.util.viewer.listingpanel.ListingPanel; +import ghidra.util.ColorUtils; /** * Class for blending two {@link ListingBackgroundColorModel}s. If neither model has a color @@ -52,10 +53,7 @@ public class LayeredColorModel implements ListingBackgroundColorModel { } private Color blend(Color primary, Color secondary) { - int red = (primary.getRed() * 2 + secondary.getRed()) / 3; - int green = (primary.getGreen() * 2 + secondary.getGreen()) / 3; - int blue = (primary.getBlue() * 2 + secondary.getBlue()) / 3; - return new Color(red, green, blue); + return ColorUtils.blend(primary, secondary, 0.67); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/ListingHighlightProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/ListingHighlightProvider.java index ec521a8159..c1f758a93e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/ListingHighlightProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/ListingHighlightProvider.java @@ -29,6 +29,7 @@ import org.apache.commons.lang3.StringUtils; import docking.widgets.fieldpanel.field.FieldElement; import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.Highlight; +import generic.theme.GColor; import ghidra.GhidraOptions; import ghidra.GhidraOptions.CURSOR_MOUSE_BUTTON_NAMES; import ghidra.app.plugin.processors.generic.PcodeFieldFactory; @@ -51,18 +52,15 @@ import ghidra.util.datastruct.Stack; public class ListingHighlightProvider implements ButtonPressedListener, OptionsChangeListener, HighlightProvider { - - private static final String DISPLAY_HIGHLIGHT_NAME = - CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Enabled"; - - private static final String SCOPED_WRITE_HIGHLIGHT_COLOR = - CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Scoped Write Highlight Color"; - - private static final String SCOPED_READ_HIGHLIGHT_COLOR = - CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Scoped Read Highlight Color"; - - private static final String SCOPE_REGISTER_OPERAND = - CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Scope Register Operand"; + //@formatter:off + private static final GColor DEFAULT_HIGHLIGHT_COLOR = new GColor("color.fg.listing.highlighter.default"); + private static final GColor DEFAULT_SCOPED_READ_COLOR = new GColor("color.fg.listing.highlighter.scoped.read"); + private static final GColor DEFAULT_SCOPED_WRITE_COLOR = new GColor("color.fg.listing.highlighter.scoped.write"); + private static final String DISPLAY_HIGHLIGHT_NAME = CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Enabled"; + private static final String SCOPED_WRITE_HIGHLIGHT_COLOR = CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Scoped Write Highlight Color"; + private static final String SCOPED_READ_HIGHLIGHT_COLOR = CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Scoped Read Highlight Color"; + private static final String SCOPE_REGISTER_OPERAND = CURSOR_HIGHLIGHT_GROUP + DELIMITER + "Scope Register Operand"; + //@formatter:on private static char[] UNDERSCORE_AND_PERIOD_OK = new char[] { '.', '_' }; private static char[] UNDERSCORE_OK = new char[] { '_' }; @@ -146,7 +144,7 @@ public class ListingHighlightProvider Pattern highlightPattern = currentHighlightPattern; Matcher matcher = highlightPattern.matcher(text); - ListhighlightList = new ArrayList (); + List highlightList = new ArrayList<>(); while (matcher.find()) { int start = matcher.start(); int end = matcher.end() - 1; @@ -481,7 +479,7 @@ public class ListingHighlightProvider } private Set getRegisterSet(Register reg) { - Set regSet = new HashSet (); + Set regSet = new HashSet<>(); regSet.add(reg); Register r = reg.getParentRegister(); while (r != null) { @@ -560,7 +558,7 @@ public class ListingHighlightProvider // and set writeScope, all other instructions upto that point will be // added to read scope Program prog = instr.getProgram(); - Stack backStack = new Stack(); + Stack backStack = new Stack<>(); pushInstructionBackFlows(instr, backStack); while (!backStack.isEmpty()) { Address addr = backStack.pop(); @@ -589,7 +587,7 @@ public class ListingHighlightProvider // follow flow downwards until register is changed // add in each line that has register anywhere Program prog = instr.getProgram(); - Stack stack = new Stack(); + Stack stack = new Stack<>(); pushInstructionFlows(instr, stack); while (!stack.isEmpty()) { Address addr = stack.pop(); @@ -849,7 +847,7 @@ public class ListingHighlightProvider varnodeSize -= intOff; varnodeOffset += intOff; - List varnodes = new ArrayList (); + List varnodes = new ArrayList<>(); for (Varnode v : variableStorage.getVarnodes()) { if (varnodeOffset >= v.getSize()) { varnodeOffset -= v.getSize(); @@ -871,11 +869,14 @@ public class ListingHighlightProvider ToolOptions opt = tool.getOptions(CATEGORY_BROWSER_FIELDS); HelpLocation hl = new HelpLocation("CodeBrowserPlugin", "Cursor_Text_Highlight"); - opt.registerOption(HIGHLIGHT_COLOR_NAME, Color.YELLOW, hl, + opt.registerThemeColorBinding(HIGHLIGHT_COLOR_NAME, + DEFAULT_HIGHLIGHT_COLOR.getId(), hl, "The color to use to highlight text."); - opt.registerOption(SCOPED_WRITE_HIGHLIGHT_COLOR, new Color(204, 204, 0), hl, + opt.registerThemeColorBinding(SCOPED_WRITE_HIGHLIGHT_COLOR, + DEFAULT_SCOPED_WRITE_COLOR.getId(), hl, "The color to use for showing a register being written."); - opt.registerOption(SCOPED_READ_HIGHLIGHT_COLOR, new Color(0, 255, 0), hl, + opt.registerThemeColorBinding(SCOPED_READ_HIGHLIGHT_COLOR, + DEFAULT_SCOPED_READ_COLOR.getId(), hl, "The color to use for showing a register being read."); opt.registerOption(SCOPE_REGISTER_OPERAND, true, hl, @@ -895,11 +896,11 @@ public class ListingHighlightProvider setHighlightString(null, null); } - textMatchingHighlightColor = opt.getColor(HIGHLIGHT_COLOR_NAME, Color.YELLOW); - + textMatchingHighlightColor = opt.getColor(HIGHLIGHT_COLOR_NAME, DEFAULT_HIGHLIGHT_COLOR); scopeWriteHighlightColor = - opt.getColor(SCOPED_WRITE_HIGHLIGHT_COLOR, new Color(204, 204, 0)); - scopeReadHighlightColor = opt.getColor(SCOPED_READ_HIGHLIGHT_COLOR, new Color(0, 255, 0)); + opt.getColor(SCOPED_WRITE_HIGHLIGHT_COLOR, DEFAULT_SCOPED_WRITE_COLOR); + scopeReadHighlightColor = + opt.getColor(SCOPED_READ_HIGHLIGHT_COLOR, DEFAULT_SCOPED_READ_COLOR); ///////////////////////////////////////////////////// diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkAndSelectionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkAndSelectionAction.java index e16ec4d06c..edcfe3a23a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkAndSelectionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkAndSelectionAction.java @@ -16,11 +16,11 @@ package ghidra.app.plugin.core.codebrowser; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.context.NavigatableActionContext; import ghidra.app.nav.Navigatable; import ghidra.app.util.HelpTopics; @@ -28,8 +28,6 @@ import ghidra.program.model.address.Address; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; -import resources.MultiIconBuilder; -import resources.ResourceManager; /** * Actions for creating a selection using two distinct steps. The first time the action @@ -61,17 +59,8 @@ public class MarkAndSelectionAction extends ToggleDockingAction { } private void buildIcons() { - ImageIcon baseImage = ResourceManager.loadImage("images/MarkSelection.png"); - ImageIcon mediaStart = ResourceManager.loadImage("images/media-playback-start.png"); - ImageIcon mediaStop = ResourceManager.loadImage("images/media-playback-stop.png"); - - MultiIconBuilder builder = new MultiIconBuilder(baseImage); - builder.addLowerRightIcon(mediaStart, 12, 12); - unarmedIcon = builder.build(); - - builder = new MultiIconBuilder(baseImage); - builder.addLowerRightIcon(mediaStop, 12, 12); - armedIcon = builder.build(); + unarmedIcon = new GIcon("icon.plugin.codebrowser.mark.and.select.unarmed"); + armedIcon = new GIcon("icon.plugin.codebrowser.mark.and.select.armed"); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkerServiceBackgroundColorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkerServiceBackgroundColorModel.java index 3515975d23..d906d9293e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkerServiceBackgroundColorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/MarkerServiceBackgroundColorModel.java @@ -19,6 +19,7 @@ import java.awt.Color; import java.math.BigInteger; import docking.widgets.fieldpanel.support.BackgroundColorModel; +import generic.theme.GColor; import ghidra.app.services.MarkerService; import ghidra.app.util.viewer.listingpanel.ListingBackgroundColorModel; import ghidra.app.util.viewer.listingpanel.ListingPanel; @@ -33,7 +34,7 @@ public class MarkerServiceBackgroundColorModel implements ListingBackgroundColor private MarkerService markerService; private Program program; private AddressIndexMap indexMap; - private Color defaultBackgroundColor = Color.WHITE; + private Color defaultBackgroundColor = new GColor("color.bg.markerservice"); public MarkerServiceBackgroundColorModel(MarkerService markerService, Program program, AddressIndexMap indexMap) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CloneCodeViewerAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CloneCodeViewerAction.java index 968754cf06..ffec11468f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CloneCodeViewerAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CloneCodeViewerAction.java @@ -15,19 +15,17 @@ */ package ghidra.app.plugin.core.codebrowser.actions; - -import ghidra.app.context.ProgramActionContext; -import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; -import ghidra.util.HelpLocation; - import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; -import resources.ResourceManager; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; +import ghidra.app.context.ProgramActionContext; +import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; +import ghidra.util.HelpLocation; public class CloneCodeViewerAction extends DockingAction { @@ -36,27 +34,26 @@ public class CloneCodeViewerAction extends DockingAction { public CloneCodeViewerAction(String owner, CodeViewerProvider provider) { super("Code Viewer Clone", owner); this.provider = provider; - ImageIcon image = ResourceManager.loadImage("images/camera-photo.png"); - setToolBarData( new ToolBarData( image, "zzzz" ) ); + Icon image = new GIcon("icon.provider.clone"); + setToolBarData(new ToolBarData(image, "zzzz")); setDescription("Create a snapshot (disconnected) copy of this Listing window "); setHelpLocation(new HelpLocation("Snapshots", "Snapshots_Start")); - setKeyBindingData( new KeyBindingData( KeyEvent.VK_T, - InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK ) ); + setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, + InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); } - + @Override - public boolean isEnabledForContext( ActionContext context ) { + public boolean isEnabledForContext(ActionContext context) { if (context instanceof ProgramActionContext) { - ProgramActionContext programContext = (ProgramActionContext)context; + ProgramActionContext programContext = (ProgramActionContext) context; return programContext.getProgram() != null; } return false; } - + @Override public void actionPerformed(ActionContext context) { provider.cloneWindow(); } } - diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/DataTypeListingHover.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/DataTypeListingHover.java index 9705f14050..a8be3b9be8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/DataTypeListingHover.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/DataTypeListingHover.java @@ -19,6 +19,7 @@ import javax.swing.JComponent; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GThemeDefaults.Colors; import ghidra.GhidraOptions; import ghidra.app.plugin.core.hover.AbstractConfigurableHover; import ghidra.app.util.ToolTipUtils; @@ -111,7 +112,8 @@ public class DataTypeListingHover extends AbstractConfigurableHover implements L } if (warningMsg.length() != 0) { String errorText = - " " + warningMsg + "!
"; + "" + + warningMsg + "!
"; toolTipText = toolTipText.replace("", errorText); } return createTooltipComponent(toolTipText); @@ -149,7 +151,9 @@ public class DataTypeListingHover extends AbstractConfigurableHover implements L result += "
Missing NULL terminator."; } if (sdi.getStringLength() > dataInstance.getLength()) { - result += "
String exceeds data field."; + result += + "
String exceeds data field."; } } return result; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingPlugin.java index 04de35dbbd..6d893403e1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingPlugin.java @@ -24,6 +24,7 @@ import org.jdom.Element; import docking.ActionContext; import docking.action.DockingAction; import docking.action.MenuData; +import generic.theme.GColor; import ghidra.app.CorePluginPackage; import ghidra.app.context.ListingActionContext; import ghidra.app.plugin.PluginCategoryNames; @@ -41,6 +42,7 @@ import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.util.ChangeManager; import ghidra.program.util.ProgramSelection; +import ghidra.util.ColorUtils; import ghidra.util.HelpLocation; import ghidra.util.task.SwingUpdateManager; @@ -61,7 +63,7 @@ public class ColorizingPlugin extends ProgramPlugin implements DomainObjectListe private static final String MARKER_DESCRIPTION = "Shows the location of user-applied colors"; private static final int PRIORITY = MarkerService.CHANGE_PRIORITY - 1; // lowest priority - private static final Color MARKER_COLOR = Color.PINK; + private static final Color MARKER_COLOR = new GColor("color.bg.plugin.colorizer.marker"); private static final String COLOR_HISTORY_XML_NAME = "COLOR_HISTORY"; private static final String COLOR_HISTORY_LIST_XML_NAME = "COLOR_HISTORY"; @@ -80,12 +82,7 @@ public class ColorizingPlugin extends ProgramPlugin implements DomainObjectListe private NextColorRangeAction nextAction; private PreviousColorRangeAction previousAction; - private SwingUpdateManager updateManager = new SwingUpdateManager(1000, new Runnable() { - @Override - public void run() { - doUpdate(); - } - }); + private SwingUpdateManager updateManager = new SwingUpdateManager(1000, () -> doUpdate()); public ColorizingPlugin(PluginTool tool) { super(tool); @@ -108,12 +105,12 @@ public class ColorizingPlugin extends ProgramPlugin implements DomainObjectListe public void readConfigState(SaveState saveState) { Element xmlElement = saveState.getXmlElement(COLOR_HISTORY_XML_NAME); if (xmlElement != null) { - ListsavedColorHistory = new ArrayList (); + List savedColorHistory = new ArrayList<>(); List colorElements = xmlElement.getChildren("COLOR"); for (Element element : colorElements) { String rgbString = element.getAttributeValue("RGB"); - int rgb = Integer.parseInt(rgbString); - savedColorHistory.add(new Color(rgb, true)); + int rgba = Integer.parseInt(rgbString); + savedColorHistory.add(ColorUtils.getColor(rgba)); } service.setColorHistory(savedColorHistory); @@ -153,15 +150,15 @@ public class ColorizingPlugin extends ProgramPlugin implements DomainObjectListe } @Override - public void serviceAdded(Class> interfaceClass, Object service) { + public void serviceAdded(Class> interfaceClass, Object newService) { if (interfaceClass.equals(MarkerService.class)) { - markerService = (MarkerService) service; + markerService = (MarkerService) newService; } } @Override - public void serviceRemoved(Class> interfaceClass, Object service) { + public void serviceRemoved(Class> interfaceClass, Object removedService) { if (interfaceClass.equals(MarkerService.class)) { markerService = null; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingServiceProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingServiceProvider.java index 0b7b06eb48..6aab9f2753 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingServiceProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/colorizer/ColorizingServiceProvider.java @@ -20,16 +20,19 @@ import java.util.Collections; import java.util.List; import docking.options.editor.GhidraColorChooser; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.viewer.listingpanel.PropertyBasedBackgroundColorModel; import ghidra.framework.plugintool.PluginTool; import ghidra.program.database.IntRangeMap; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; +import ghidra.util.ColorUtils; import ghidra.util.exception.DuplicateNameException; class ColorizingServiceProvider implements ColorizingService { - private static final Color DEFAULT_COLOR = new Color(0x84AFD3); + private static final Color DEFAULT_COLOR = new GColor("color.bg.plugin.colorizer.default"); static final String COLOR_CHOOSER_TITLE = "Please Select Background Color"; private final PluginTool tool; @@ -86,7 +89,7 @@ class ColorizingServiceProvider implements ColorizingService { public Color getColorFromUser(Color suggestedColor) { if (colorChooser == null) { colorChooser = - new GhidraColorChooser(suggestedColor == null ? Color.WHITE : suggestedColor); + new GhidraColorChooser(suggestedColor == null ? Palette.WHITE : suggestedColor); colorChooser.setTitle(COLOR_CHOOSER_TITLE); if (savedColorHistory != null) { colorChooser.setColorHistory(savedColorHistory); @@ -133,9 +136,9 @@ class ColorizingServiceProvider implements ColorizingService { public Color getBackgroundColor(Address address) { IntRangeMap map = getColorRangeMap(false); if (map != null) { - Integer value = map.getValue(address); - if (value != null) { - return new Color(value, true); + Integer rgba = map.getValue(address); + if (rgba != null) { + return ColorUtils.getColor(rgba); } } return null; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/comments/CommentHistoryPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/comments/CommentHistoryPanel.java index 22b7668490..1d7f017456 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/comments/CommentHistoryPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/comments/CommentHistoryPanel.java @@ -16,12 +16,12 @@ package ghidra.app.plugin.core.comments; import java.awt.BorderLayout; -import java.awt.Color; import javax.swing.JPanel; import javax.swing.JTextPane; import javax.swing.text.*; +import generic.theme.GColor; import ghidra.program.model.address.Address; import ghidra.program.model.listing.CommentHistory; import ghidra.program.model.listing.Program; @@ -115,18 +115,22 @@ class CommentHistoryPanel extends JPanel { textAttrSet = new SimpleAttributeSet(); textAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); textAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - textAttrSet.addAttribute(StyleConstants.Foreground, Color.BLUE); + textAttrSet.addAttribute(StyleConstants.Foreground, + new GColor("color.fg.plugin.comments.history.text")); userAttrSet = new SimpleAttributeSet(); userAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); userAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); userAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); + userAttrSet.addAttribute(StyleConstants.Foreground, + new GColor("color.fg.plugin.comments.history.user")); dateAttrSet = new SimpleAttributeSet(); dateAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); dateAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); dateAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - dateAttrSet.addAttribute(StyleConstants.Foreground, new Color(124, 37, 18)); + dateAttrSet.addAttribute(StyleConstants.Foreground, + new GColor("color.fg.plugin.comments.history.date")); tabAttrSet = new SimpleAttributeSet(); TabStop tabs = new TabStop(100, StyleConstants.ALIGN_LEFT, TabStop.LEAD_NONE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentWindowProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentWindowProvider.java index e427c082ac..6f22a7618a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentWindowProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/commentwindow/CommentWindowProvider.java @@ -88,7 +88,9 @@ class CommentWindowProvider extends ComponentProviderAdapter { } void programClosed() { - commentModel.reload(null); + if (isVisible()) { + commentModel.reload(null); + } } void dispose() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ApplyAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ApplyAction.java index cbae61492c..0f4f4fcefb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ApplyAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ApplyAction.java @@ -15,12 +15,12 @@ */ package ghidra.app.plugin.core.compositeeditor; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.ActionContext; +import generic.theme.GIcon; import ghidra.app.util.datatype.EmptyCompositeException; import ghidra.program.model.data.InvalidDataTypeException; -import resources.ResourceManager; /** * ApplyAction is an action for applying editor changes. @@ -29,7 +29,7 @@ public class ApplyAction extends CompositeEditorTableAction { public final static String ACTION_NAME = "Apply Editor Changes"; private final static String GROUP_NAME = BASIC_ACTION_GROUP; - private final static ImageIcon ICON = ResourceManager.loadImage("images/disk.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.apply"); private final static String[] POPUP_PATH = new String[] { "Apply Edits" }; public ApplyAction(CompositeEditorProvider provider) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ArrayAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ArrayAction.java index 2f94329ad0..124f21eb65 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ArrayAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ArrayAction.java @@ -17,13 +17,13 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; +import generic.theme.GIcon; import ghidra.util.exception.UsrException; -import resources.ResourceManager; /** * Action for use in the composite data type editor. @@ -31,7 +31,7 @@ import resources.ResourceManager; */ public class ArrayAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = ResourceManager.loadImage("images/Array.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.array"); public final static String ACTION_NAME = "Create Array"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Create an array"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java index adf37c72ae..e0db5a1d77 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java @@ -23,16 +23,18 @@ import docking.*; import docking.action.*; import docking.menu.DockingCheckboxMenuItemUI; import docking.widgets.OptionDialog; +import generic.theme.GIcon; import ghidra.app.services.DataTypeManagerService; import ghidra.program.model.data.*; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class BitFieldEditorDialog extends DialogComponentProvider { - private static final Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private static final Icon EDIT_ICON = ResourceManager.loadImage("images/move.png"); - private static final Icon DELETE_ICON = ResourceManager.loadImage("images/edit-delete.png"); + //@formatter:off + private static final Icon ADD_ICON = new GIcon("icon.plugin.composite.editor.bit.field.dialog.add"); + private static final Icon EDIT_ICON = new GIcon("icon.plugin.composite.editor.bit.field.dialog.edit"); + private static final Icon DELETE_ICON = new GIcon("icon.plugin.composite.editor.bit.field.dialog.delete"); + //@formatter:on private DataTypeManagerService dtmService; private Composite composite; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java index a70cec5916..00fe100de6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java @@ -28,6 +28,8 @@ import docking.ActionContext; import docking.widgets.DropDownSelectionTextField; import docking.widgets.OptionDialog; import docking.widgets.label.GDLabel; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitAttributes; import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitFieldAllocation; import ghidra.app.services.DataTypeManagerService; @@ -37,7 +39,6 @@ import ghidra.program.model.data.*; import ghidra.program.model.data.Composite; import ghidra.util.data.DataTypeParser.AllowedDataTypes; import ghidra.util.layout.*; -import resources.ResourceManager; /** * BitFieldEditorPanelprovides the ability to add or modify bitfields @@ -45,8 +46,10 @@ import resources.ResourceManager; */ public class BitFieldEditorPanel extends JPanel { - private static final Icon DECREMENT_ICON = ResourceManager.loadImage("images/Minus.png"); - private static final Icon INCREMENT_ICON = ResourceManager.loadImage("images/Plus.png"); + //@formatter:off + private static final Icon DECREMENT_ICON = new GIcon("icon.plugin.composite.editor.bit.field.editor.decrement"); + private static final Icon INCREMENT_ICON = new GIcon("icon.plugin.composite.editor.bit.field.editor.increment"); + //@formatter:on private DataTypeManagerService dtmService; private Composite composite; @@ -73,7 +76,6 @@ public class BitFieldEditorPanel extends JPanel { private BitSelectionHandler bitSelectionHandler; - private boolean updating = false; BitFieldEditorPanel(Composite composite, DataTypeManagerService dtmService, @@ -179,7 +181,7 @@ public class BitFieldEditorPanel extends JPanel { statusTextField = new GDLabel(" "); statusTextField.setHorizontalAlignment(SwingConstants.CENTER); - statusTextField.setForeground(Color.red); + statusTextField.setForeground(Colors.ERROR); // use a strut panel so the size of the message area does not change if we make // the message label not visible diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java index 6d17bacfa2..2a42f9f853 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java @@ -22,6 +22,7 @@ import java.util.*; import javax.help.UnsupportedOperationException; import javax.swing.*; +import generic.theme.GColor; import ghidra.program.model.data.*; import ghidra.program.model.data.Composite; import ghidra.util.HTMLUtilities; @@ -42,15 +43,25 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable { private static final int LENEND_BOX_SIZE = 16; - private static final Color TEXT_COLOR = Color.black; - private static final Color LINE_COLOR = Color.black; - private static final Color BYTE_HEADER_COLOR = new Color(0xdfdfdf); - private static final Color UNDEFINED_BIT_COLOR = new Color(0xf8f8f8); - private static final Color ACTIVE_BITFIELD_BITS_COLOR = Color.green; - private static final Color CONFLICT_BITS_COLOR = Color.yellow; - private static final Color BITFIELD_COMPONENT_COLOR = new Color(0xbfbfff); - private static final Color NON_BITFIELD_COMPONENT_COLOR = new Color(0xa0a0ff); - private static final Color INTERIOR_LINE_COLOR = new Color(0xd4d4d4); + private static final Color TEXT_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.text"); + private static final Color LINE_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.line"); + private static final Color BYTE_HEADER_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.byte.header"); + + private static final Color UNDEFINED_BIT_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.bit.undefined"); + private static final Color BITFIELD_COMPONENT_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.bit.component"); + private static final Color ACTIVE_BITFIELD_BITS_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.bit.active"); + private static final Color CONFLICT_BITS_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.bit.conflict"); + private static final Color NON_BITFIELD_COMPONENT_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.non.bit"); + private static final Color INTERIOR_LINE_COLOR = + new GColor("color.bg.plugin.editors.compositeeditor.line.interior"); private int bitWidth = 10; private int byteWidth = getByteWidth(bitWidth); @@ -211,7 +222,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable { return; } if (e.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) { - // TODO: should we handle other modes? + // should we handle other modes? return; } e.consume(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ClearAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ClearAction.java index f7ac6bf4c6..a75a0af547 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ClearAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ClearAction.java @@ -17,20 +17,19 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; -import ghidra.util.Msg; +import generic.theme.GIcon; import ghidra.util.exception.UsrException; -import resources.ResourceManager; public class ClearAction extends CompositeEditorTableAction { public final static String ACTION_NAME = "Clear Components"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; - private final static ImageIcon ICON = ResourceManager.loadImage("images/erase16.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.clear"); private final static String[] POPUP_PATH = new String[] { "Clear" }; private final static KeyStroke KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_C, 0); @@ -47,10 +46,6 @@ public class ClearAction extends CompositeEditorTableAction { try { model.clearSelectedComponents(); } - catch (OutOfMemoryError memExc) { - String errMsg = "Couldn't clear components. Out of memory."; - Msg.showError(this, null, "Out of Memory", errMsg, memExc); - } catch (UsrException ue) { model.setStatus(ue.getMessage()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java index 3021dafa68..d2ddcbd9dc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java @@ -30,6 +30,7 @@ import docking.widgets.OptionDialog; import docking.widgets.button.GRadioButton; import docking.widgets.fieldpanel.support.FieldSelection; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitAttributes; import ghidra.program.model.data.*; import ghidra.program.model.data.Composite; @@ -394,7 +395,9 @@ public class CompEditorPanel extends CompositeEditorPanel { String alignmentToolTip = "The align control allows the overall minimum alignment of this
" + "data type to be specified. The actual computed alignment
" + - "may be any multiple of this value. (<F1> for help)"; + "may be any multiple of this value. " + + "(<F1> for help)"; alignPanel.setToolTipText(alignmentToolTip); addMinimumAlignmentComponents(); @@ -570,7 +573,8 @@ public class CompEditorPanel extends CompositeEditorPanel { infoPanel.add(actualAlignmentPanel, gridBagConstraints); actualAlignmentValueTextField = new JTextField(8); - actualAlignmentValueTextField.setText("" + ((CompEditorModel) model).getActualAlignment()); + actualAlignmentValueTextField + .setText(Integer.toString(((CompEditorModel) model).getActualAlignment())); actualAlignmentValueTextField.setToolTipText(actualAlignmentToolTip); actualAlignmentValueTextField.setEditable(false); if (helpManager != null) { @@ -586,7 +590,7 @@ public class CompEditorPanel extends CompositeEditorPanel { gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 3; infoPanel.add(actualAlignmentValueTextField, gridBagConstraints); - actualAlignmentValueTextField.setBackground(new Color(getBackground().getRGB())); + actualAlignmentValueTextField.setBackground(getBackground()); } private void setupPacking() { @@ -669,8 +673,11 @@ public class CompEditorPanel extends CompositeEditorPanel { private void setupPackingEnablementButton() { packingEnablementButton.setName("Packing Enablement"); String packingToolTipText = - "Enable packing when details of all components are known (including sizing and alignment).
" + - "Disable packing when Reverse Engineering composite. (<F1> for help)"; + "Enable packing when details of all components are known (including sizing and" + + " alignment).
" + + "Disable packing when Reverse Engineering composite. " + + "(<F1> for help)"; packingEnablementButton.addActionListener(e -> { ((CompEditorModel) model).setPackingType( packingEnablementButton.isSelected() ? PackingType.DEFAULT : PackingType.DISABLED, @@ -708,8 +715,9 @@ public class CompEditorPanel extends CompositeEditorPanel { explicitPackingButton.addActionListener(e -> chooseByValuePacking()); explicitPackingButton.setToolTipText(packingToolTipText); if (helpManager != null) { - helpManager.registerHelp(explicitPackingButton, new HelpLocation(provider.getHelpTopic(), - provider.getHelpName() + "_" + "Pack")); + helpManager.registerHelp(explicitPackingButton, + new HelpLocation(provider.getHelpTopic(), + provider.getHelpName() + "_" + "Pack")); } explicitPackingTextField.setName("Packing Value"); @@ -831,7 +839,7 @@ public class CompEditorPanel extends CompositeEditorPanel { } else { // not editable - use same background as panel - sizeTextField.setBackground(new Color(getBackground().getRGB())); + sizeTextField.setBackground(getBackground()); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java index 4bd980b492..450ab47ec1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java @@ -43,6 +43,7 @@ import docking.widgets.label.GDLabel; import docking.widgets.label.GLabel; import docking.widgets.table.*; import docking.widgets.textfield.GValidatedTextField; +import generic.theme.GColor; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.datatype.DataTypeSelectionEditor; import ghidra.app.util.datatype.NavigationDirection; @@ -70,8 +71,6 @@ public abstract class CompositeEditorPanel extends JPanel implements CompositeEditorModelListener, ComponentCellEditorListener, Draggable, Droppable { // Normal color for selecting components in the table. - // TODO: Why do we choose a different selection color? - //private static final Color SELECTION_COLOR = Color.YELLOW.brighter().brighter(); //protected static final Insets TEXTFIELD_INSETS = new JTextField().getInsets(); protected static final Border BEVELED_BORDER = BorderFactory.createLoweredBevelBorder(); @@ -605,8 +604,6 @@ public abstract class CompositeEditorPanel extends JPanel JScrollPane sp = new JScrollPane(table); table.setPreferredScrollableViewportSize(new Dimension(model.getWidth(), 250)); table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - //table.setSelectionBackground(SELECTION_COLOR); - //table.setSelectionForeground(Color.black); tablePanel.add(sp, BorderLayout.CENTER); SearchControlPanel searchPanel = new SearchControlPanel(this); @@ -636,7 +633,7 @@ public abstract class CompositeEditorPanel extends JPanel // This can happen on the Mac and is usually white. This is a simple solution for // that scenario. If this fails on other platforms, then do something more advanced // at that point. - table.setGridColor(Color.GRAY); + table.setGridColor(new GColor("color.bg.table.grid")); } } @@ -668,7 +665,7 @@ public abstract class CompositeEditorPanel extends JPanel JPanel panel = new JPanel(new BorderLayout()); statusLabel = new GDLabel(" "); statusLabel.setHorizontalAlignment(SwingConstants.CENTER); - statusLabel.setForeground(Color.blue); + statusLabel.setForeground(new GColor("color.fg.dialog.status.normal")); statusLabel.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorProvider.java index ca55101824..9fe4c4e392 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorProvider.java @@ -22,6 +22,7 @@ import javax.swing.*; import docking.ActionContext; import docking.ComponentProvider; import docking.widgets.OptionDialog; +import generic.theme.GIcon; import ghidra.app.context.ProgramActionContext; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.datatype.EmptyCompositeException; @@ -33,7 +34,6 @@ import ghidra.util.HelpLocation; import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; import ghidra.util.exception.AssertException; -import resources.ResourceManager; /** * Editor provider for a Composite Data Type. @@ -41,8 +41,7 @@ import resources.ResourceManager; public abstract class CompositeEditorProvider extends ComponentProviderAdapter implements EditorProvider, EditorActionListener { - protected static final ImageIcon EDITOR_ICON = - ResourceManager.loadImage("images/accessories-text-editor.png"); + protected static final Icon EDITOR_ICON = new GIcon("icon.plugin.composite.editor.provider"); protected Plugin plugin; protected Category category; @@ -56,9 +55,6 @@ public abstract class CompositeEditorProvider extends ComponentProviderAdapter /** * Construct a new stack editor provider. * @param plugin owner of this provider - * @param program program for data type; may be null if data type - * is part of an archive - * @param stack the stack frame to be edited */ protected CompositeEditorProvider(Plugin plugin) { super(plugin.getTool(), "Composite Editor", plugin.getName()); @@ -283,6 +279,7 @@ public abstract class CompositeEditorProvider extends ComponentProviderAdapter /** * Prompts the user if the editor has unsaved changes. Saves the changes if * the user indicates to do so. + * @param allowCancel true if allowed to cancel * @return 0 if the user canceled; 1 if the user saved changes; * 2 if the user did not to save changes; 3 if there was an error when * the changes were applied. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CreateInternalStructureAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CreateInternalStructureAction.java index f845f33353..163ee85ac8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CreateInternalStructureAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CreateInternalStructureAction.java @@ -17,15 +17,15 @@ package ghidra.app.plugin.core.compositeeditor; import java.util.Arrays; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.ActionContext; +import generic.theme.GIcon; import ghidra.util.Swing; import ghidra.util.exception.CancelledException; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * Action for use in the structure data type editor. @@ -33,8 +33,7 @@ import resources.ResourceManager; */ public class CreateInternalStructureAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = - ResourceManager.loadImage("images/cstruct.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.create"); public final static String ACTION_NAME = "Create Structure From Selection"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DataTypeCellRenderer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DataTypeCellRenderer.java index 59dfe9478b..358c42b509 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DataTypeCellRenderer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DataTypeCellRenderer.java @@ -15,13 +15,13 @@ */ package ghidra.app.plugin.core.compositeeditor; -import java.awt.Color; import java.awt.Component; import javax.swing.JLabel; import docking.widgets.table.GTableCellRenderer; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.util.ToolTipUtils; import ghidra.program.model.data.*; import ghidra.util.HTMLUtilities; @@ -43,7 +43,7 @@ public class DataTypeCellRenderer extends GTableCellRenderer { String dtString = ""; String tooltipText = null; - boolean useRed = false; + boolean showError = false; DataType dt = null; if (value instanceof DataTypeInstance) { @@ -51,7 +51,7 @@ public class DataTypeCellRenderer extends GTableCellRenderer { tooltipText = getDataTypeToolTip(dt); dtString = dt.getDisplayName(); if (dt.isNotYetDefined()) { - useRed = true; + showError = true; } } @@ -61,8 +61,8 @@ public class DataTypeCellRenderer extends GTableCellRenderer { c.setToolTipText(tooltipText); - if (useRed) { - c.setForeground(Color.RED); + if (showError) { + c.setForeground(Colors.ERROR); } return c; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java index cd236c29df..f8c5062b8b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java @@ -17,22 +17,22 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; +import generic.theme.GIcon; import ghidra.util.exception.CancelledException; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class DeleteAction extends CompositeEditorTableAction { public final static String ACTION_NAME = "Delete Components"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; - private final static ImageIcon ICON = ResourceManager.loadImage("images/edit-delete.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.delete"); private final static String[] popupPath = new String[] { "Delete" }; private final static KeyStroke KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateAction.java index 9fdfe0393b..fc06774ae9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateAction.java @@ -18,21 +18,21 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; +import generic.theme.GIcon; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * Action to duplicate the selected row */ public class DuplicateAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = ResourceManager.loadImage("images/DuplicateData.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.duplicate"); public final static String ACTION_NAME = "Duplicate Component"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Duplicate the selected component"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateMultipleAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateMultipleAction.java index 4ae608dd00..86a5d5e9ca 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateMultipleAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DuplicateMultipleAction.java @@ -18,26 +18,26 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; import docking.widgets.dialogs.NumberInputDialog; +import generic.theme.GIcon; import ghidra.util.HelpLocation; import ghidra.util.exception.CancelledException; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * Action that allows the user to make multiple duplicates of the selected item */ public class DuplicateMultipleAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = - ResourceManager.loadImage("images/MultiDuplicateData.png"); + private final static Icon ICON = + new GIcon("icon.plugin.composite.editor.duplicate.multiple"); public final static String ACTION_NAME = "Duplicate Multiple of Component"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Duplicate multiple of the selected component"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java index 72a8e6e557..abafcab546 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java @@ -18,14 +18,14 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; +import generic.theme.GIcon; import ghidra.program.model.data.*; import ghidra.util.exception.UsrException; -import resources.ResourceManager; /** * Action for use in the structure data type editor. @@ -33,8 +33,7 @@ import resources.ResourceManager; */ public class InsertUndefinedAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = - ResourceManager.loadImage("images/Plus.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.insert.undefined"); public final static String ACTION_NAME = "Insert Undefined Byte"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Insert an undefined byte before the selection"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveDownAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveDownAction.java index 8758059816..615e7fca54 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveDownAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveDownAction.java @@ -18,13 +18,13 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; +import generic.theme.GIcon; import ghidra.util.exception.UsrException; -import resources.ResourceManager; /** * Action for use in the composite data type editor. @@ -32,7 +32,7 @@ import resources.ResourceManager; */ public class MoveDownAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = ResourceManager.loadImage("images/down.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.move.down"); public final static String ACTION_NAME = "Move Components Down"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Move the selected components down"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveUpAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveUpAction.java index 928b6e2e76..bf6a913b53 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveUpAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/MoveUpAction.java @@ -18,13 +18,13 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; +import generic.theme.GIcon; import ghidra.util.exception.UsrException; -import resources.ResourceManager; /** * Action for use in the composite data type editor. @@ -32,7 +32,7 @@ import resources.ResourceManager; */ public class MoveUpAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = ResourceManager.loadImage("images/up.png"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.move.up"); public final static String ACTION_NAME = "Move Components Up"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Move selected components up"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/SearchControlPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/SearchControlPanel.java index 8e526522d2..eadb8d9e84 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/SearchControlPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/SearchControlPanel.java @@ -25,14 +25,12 @@ import javax.swing.event.DocumentListener; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GLabel; -import resources.ResourceManager; +import generic.theme.GIcon; public class SearchControlPanel extends JPanel { - private static final Icon NEXT_ICON = ResourceManager.getScaledIcon( - ResourceManager.loadImage("images/go-down.tango.16.png"), 16, 16); - private static final Icon PREV_ICON = ResourceManager.getScaledIcon( - ResourceManager.loadImage("images/go-up.tango.16.png"), 16, 16); + private static final Icon NEXT_ICON = new GIcon("icon.plugin.composite.editor.search.next"); + private static final Icon PREV_ICON = new GIcon("icon.plugin.composite.editor.search.previous"); private CompositeEditorPanel editorPanel; private JTextField textField; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ShowDataTypeInTreeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ShowDataTypeInTreeAction.java index 4fe4b8b260..6c16f9beba 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ShowDataTypeInTreeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/ShowDataTypeInTreeAction.java @@ -19,9 +19,9 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.app.services.DataTypeManagerService; import ghidra.program.model.data.*; -import resources.ResourceManager; /** * Shows the editor's data type in the UI using the {@link DataTypeManagerService}. @@ -31,14 +31,13 @@ public class ShowDataTypeInTreeAction extends CompositeEditorTableAction { // This action should go after the row-based actions, which have this group: // 3_COMPONENT_EDITOR_ACTION private static final String TOOLBAR_GROUP = "4_COMPONENT_EDITOR_ACTION"; - private static final Icon ICON = ResourceManager.loadImage("images/go-home.png"); + private static final Icon ICON = new GIcon("icon.plugin.composite.editor.show.type"); public ShowDataTypeInTreeAction(CompositeEditorProvider provider) { super(provider, "Show In Data Type Manager", TOOLBAR_GROUP, null /*popupPath*/, null /*menuPath*/, ICON); - setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/go-home.png"), TOOLBAR_GROUP)); + setToolBarData(new ToolBarData(ICON, TOOLBAR_GROUP)); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorProvider.java index 43b2e35865..05723a839d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorProvider.java @@ -15,19 +15,19 @@ */ package ghidra.app.plugin.core.compositeeditor; -import javax.swing.ImageIcon; +import javax.swing.Icon; +import generic.theme.GIcon; import ghidra.framework.plugintool.Plugin; import ghidra.program.model.data.Structure; -import resources.ResourceManager; /** * Editor for a Structure Data Type. */ public class StructureEditorProvider extends CompositeEditorProvider { - protected static final ImageIcon STRUCTURE_EDITOR_ICON = - ResourceManager.loadImage("images/cstruct.png"); + protected static final Icon STRUCTURE_EDITOR_ICON = + new GIcon("icon.plugin.composite.editor.provider.structure"); public StructureEditorProvider(Plugin plugin, Structure structureDataType, boolean showHexNumbers) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorProvider.java index 3ac09cc3c9..9a17a3086e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorProvider.java @@ -15,19 +15,19 @@ */ package ghidra.app.plugin.core.compositeeditor; -import javax.swing.ImageIcon; +import javax.swing.Icon; +import generic.theme.GIcon; import ghidra.framework.plugintool.Plugin; import ghidra.program.model.data.Union; -import resources.ResourceManager; /** * Editor for a Union Data Type. */ public class UnionEditorProvider extends CompositeEditorProvider { - protected static final ImageIcon UNION_EDITOR_ICON = - ResourceManager.loadImage("images/cUnion.png"); + protected static final Icon UNION_EDITOR_ICON = + new GIcon("icon.plugin.composite.editor.provider.union"); public UnionEditorProvider(Plugin plugin, Union unionDataType, boolean showInHex) { super(plugin); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnpackageAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnpackageAction.java index eeaed26cde..64b4fb04db 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnpackageAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnpackageAction.java @@ -17,17 +17,17 @@ package ghidra.app.plugin.core.compositeeditor; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.KeyBindingData; import docking.widgets.OptionDialog; +import generic.theme.GIcon; import ghidra.util.exception.CancelledException; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * Action for use in the composite data type editor. @@ -35,7 +35,7 @@ import resources.ResourceManager; */ public class UnpackageAction extends CompositeEditorTableAction { - private final static ImageIcon ICON = ResourceManager.loadImage("images/Unpackage.gif"); + private final static Icon ICON = new GIcon("icon.plugin.composite.editor.unpackage"); public final static String ACTION_NAME = "Unpackage Component"; private final static String GROUP_NAME = COMPONENT_ACTION_GROUP; private final static String DESCRIPTION = "Replace the selected composite with its components"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java index f5ee090cff..3be30d4367 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java @@ -25,9 +25,10 @@ import javax.swing.text.Document; import docking.*; import docking.action.*; +import generic.theme.GIcon; +import generic.theme.Gui; import ghidra.app.services.*; import ghidra.framework.main.ConsoleTextPane; -import ghidra.framework.options.OptionsChangeListener; import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.PluginTool; @@ -35,26 +36,21 @@ import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.SymbolIterator; import ghidra.program.model.symbol.SymbolTable; -import ghidra.util.*; -import resources.ResourceManager; +import ghidra.util.HelpLocation; +import ghidra.util.Msg; public class ConsoleComponentProvider extends ComponentProviderAdapter - implements ConsoleService, OptionsChangeListener { + implements ConsoleService { private static final String OLD_NAME = "ConsolePlugin"; private static final String NAME = "Console"; - private static final String CONSOLE_GIF = "images/monitor.png"; - private static final String CLEAR_GIF = "images/erase16.png"; - private static final String SCROLL_LOCK_GIF = "images/lock.png"; - - private static final Font DEFAULT_FONT = new Font("monospaced", Font.PLAIN, 12); + private static final String DEFAULT_FONT_ID = "font.plugin.console"; private static final String FONT_OPTION_LABEL = "Font"; private static final String FONT_DESCRIPTION = "This is the font that will be used in the Console. " + "Double-click the font example to change it."; - private Font font; private ConsoleTextPane textPane; private JScrollPane scroller; private JComponent component; @@ -74,7 +70,7 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter setDefaultWindowPosition(WindowPosition.BOTTOM); setHelpLocation(new HelpLocation(owner, owner)); - setIcon(ResourceManager.loadImage(CONSOLE_GIF)); + setIcon(new GIcon("icon.plugin.console.provider")); setWindowMenuGroup("Console"); setSubTitle("Scripting"); setTitle("Console"); @@ -107,27 +103,16 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter private void createOptions() { ToolOptions options = tool.getOptions("Console"); HelpLocation help = new HelpLocation(getOwner(), getOwner()); - options.registerOption(FONT_OPTION_LABEL, DEFAULT_FONT, help, FONT_DESCRIPTION); + options.registerThemeFontBinding(FONT_OPTION_LABEL, DEFAULT_FONT_ID, help, + FONT_DESCRIPTION); options.setOptionsHelpLocation(help); - font = options.getFont(FONT_OPTION_LABEL, DEFAULT_FONT); - font = SystemUtilities.adjustForFontSizeOverride(font); - options.addOptionsChangeListener(this); - } - - @Override - public void optionsChanged(ToolOptions options, String optionName, Object oldValue, - Object newValue) { - if (optionName.equals(FONT_OPTION_LABEL)) { - font = SystemUtilities.adjustForFontSizeOverride((Font) newValue); - textPane.setFont(font); - } } private void build() { textPane = new ConsoleTextPane(tool); textPane.setName("CONSOLE"); - textPane.setFont(font); + Gui.registerFont(textPane, DEFAULT_FONT_ID); textPane.setEditable(false); textPane.addMouseMotionListener(new MouseMotionAdapter() { @Override @@ -281,7 +266,7 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter }; clearAction.setDescription("Clear Console"); // ACTIONS - auto generated - clearAction.setToolBarData(new ToolBarData(ResourceManager.loadImage(CLEAR_GIF), null)); + clearAction.setToolBarData(new ToolBarData(new GIcon("icon.plugin.console.clear"), null)); clearAction.setEnabled(true); @@ -293,7 +278,8 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter }; scrollAction.setDescription("Scroll Lock"); scrollAction - .setToolBarData(new ToolBarData(ResourceManager.loadImage(SCROLL_LOCK_GIF), null)); + .setToolBarData( + new ToolBarData(new GIcon("icon.plugin.console.scroll.lock"), null)); scrollAction.setEnabled(true); scrollAction.setSelected(scrollLock); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java index 61a8977002..3aad90b9ee 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java @@ -44,7 +44,6 @@ import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.filechooser.ExtensionFileFilter; import resources.Icons; -import resources.ResourceManager; /** * Dialog that shows files used for parsing C header files. The profile has a list of @@ -341,7 +340,7 @@ class ParseDialog extends DialogComponentProvider { } }; saveAction.setEnabled(false); - ImageIcon icon = ResourceManager.loadImage("images/disk.png"); + Icon icon = Icons.SAVE_ICON; String saveGroup = "save"; saveAction.setMenuBarData(new MenuData(new String[] { "Save" }, icon, saveGroup)); saveAction.setToolBarData(new ToolBarData(icon, saveGroup)); @@ -355,7 +354,7 @@ class ParseDialog extends DialogComponentProvider { } }; saveAsAction.setEnabled(true); - icon = ResourceManager.loadImage("images/disk_save_as.png"); + icon = Icons.SAVE_AS_ICON; saveAsAction.setMenuBarData(new MenuData(new String[] { "Save As..." }, icon, saveGroup)); saveAsAction.setToolBarData(new ToolBarData(icon, saveGroup)); saveAsAction.setDescription("Save profile to new name"); @@ -369,10 +368,10 @@ class ParseDialog extends DialogComponentProvider { }; clearAction.setEnabled(true); - icon = ResourceManager.loadImage("images/erase16.png"); + icon = Icons.CLEAR_ICON; String clearGroup = "clear"; - clearAction.setMenuBarData( - new MenuData(new String[] { "Clear Profile" }, icon, clearGroup)); + clearAction + .setMenuBarData(new MenuData(new String[] { "Clear Profile" }, icon, clearGroup)); clearAction.setToolBarData(new ToolBarData(icon, clearGroup)); clearAction.setDescription("Clear profile"); addAction(clearAction); @@ -399,7 +398,7 @@ class ParseDialog extends DialogComponentProvider { } }; deleteAction.setEnabled(false); - icon = ResourceManager.loadImage("images/edit-delete.png"); + icon = Icons.DELETE_ICON; String deleteGroup = "Xdelete"; deleteAction.setMenuBarData(new MenuData(new String[] { "Delete" }, icon, deleteGroup)); deleteAction.setToolBarData(new ToolBarData(icon, deleteGroup)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/CreateStructureDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/CreateStructureDialog.java index 83c88dcb5d..5d3d6c9eda 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/CreateStructureDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/CreateStructureDialog.java @@ -15,10 +15,10 @@ */ package ghidra.app.plugin.core.data; -import java.awt.*; +import java.awt.Component; +import java.awt.Dimension; import java.awt.event.*; import java.util.*; -import java.util.List; import javax.swing.*; import javax.swing.border.TitledBorder; @@ -31,6 +31,7 @@ import javax.swing.text.Document; import docking.DialogComponentProvider; import docking.widgets.button.GRadioButton; import docking.widgets.table.*; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.ToolTipUtils; import ghidra.framework.plugintool.PluginTool; @@ -272,18 +273,17 @@ public class CreateStructureDialog extends DialogComponentProvider { return matchingStylePanel; } - // toggles whether the structure being created is new, based upon the - // name field, or a current structure, based upon a structure in the - // table. This method updates the GUI to reflect the current creation - // state. + // toggles whether the structure being created is new, based upon the name field, or a current + // structure, based upon a structure in the table. This method updates the GUI to reflect the + // current creation state. private void setCreateStructureByName(boolean createStructureByName) { if (createStructureByName) { - nameBorder.setTitleColor(Color.BLACK); - structureBorder.setTitleColor(Color.GRAY); + nameBorder.setTitleColor(Colors.FOREGROUND); + structureBorder.setTitleColor(Colors.FOREGROUND_DISABLED); } else { - nameBorder.setTitleColor(Color.GRAY); - structureBorder.setTitleColor(Color.BLACK); + nameBorder.setTitleColor(Colors.FOREGROUND_DISABLED); + structureBorder.setTitleColor(Colors.FOREGROUND); } nameTextField.setEnabled(createStructureByName); @@ -299,7 +299,7 @@ public class CreateStructureDialog extends DialogComponentProvider { // this class in terms of data contained private void searchForMatchingStructures(final Program program, final Structure structure) { - SwingUtilities.invokeLater(() -> { + Swing.runLater(() -> { // Get the structures from the DataTypeManagers of the // DataTypeManagerService DataTypeManagerService service = pluginTool.getService(DataTypeManagerService.class); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java index 670762ce09..368eeb90d7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java @@ -18,10 +18,9 @@ package ghidra.app.plugin.core.datamgr; import java.awt.*; import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import docking.widgets.label.GDHtmlLabel; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.util.ToolTipUtils; import ghidra.app.util.html.HTMLDataTypeRepresentation; import ghidra.program.model.data.DataType; @@ -41,13 +40,6 @@ class DataTypeComparePanel extends JPanel { private String clientName; private String sourceName; - /** - * Creates a panel for viewing two data types side by side. - * @param dataType1 the first data type to display. - * @param dataType2 the second data type to display. - * @param one_to_two true if this panel should display an arrow from data type 1 to data type 2. - * false if the should be from 2 to 1. - */ DataTypeComparePanel(String clientName, String sourceName) { super(new GridLayout(0, 2)); this.clientName = clientName; @@ -72,12 +64,12 @@ class DataTypeComparePanel extends JPanel { add(rightPanel); dtLabel1 = new GDHtmlLabel(); dtLabel1.setOpaque(true); - dtLabel1.setBackground(Color.WHITE); + dtLabel1.setBackground(Colors.BACKGROUND); dtLabel1.setBorder(BorderFactory.createEmptyBorder(2, 8, 0, 0)); dtLabel1.setVerticalAlignment(SwingConstants.TOP); dtLabel2 = new GDHtmlLabel(); dtLabel2.setOpaque(true); - dtLabel2.setBackground(Color.WHITE); + dtLabel2.setBackground(Colors.BACKGROUND); dtLabel2.setBorder(BorderFactory.createEmptyBorder(2, 8, 0, 0)); dtLabel2.setVerticalAlignment(SwingConstants.TOP); @@ -96,19 +88,13 @@ class DataTypeComparePanel extends JPanel { private void syncScrollers(JScrollPane leftScrollPane, JScrollPane rightScrollPane) { final JViewport viewport1 = leftScrollPane.getViewport(); final JViewport viewport2 = rightScrollPane.getViewport(); - viewport1.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - int y = viewport1.getViewPosition().y; - viewport2.setViewPosition(new Point(0, y)); - } + viewport1.addChangeListener(e -> { + int y = viewport1.getViewPosition().y; + viewport2.setViewPosition(new Point(0, y)); }); - viewport2.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - int y = viewport2.getViewPosition().y; - viewport1.setViewPosition(new Point(0, y)); - } + viewport2.addChangeListener(e -> { + int y = viewport2.getViewPosition().y; + viewport1.setViewPosition(new Point(0, y)); }); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index 8d6445e231..ff576efdc3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -37,6 +37,7 @@ import docking.widgets.PopupWindow; import docking.widgets.textpane.GHtmlTextPane; import docking.widgets.tree.*; import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.actions.*; import ghidra.app.plugin.core.datamgr.actions.associate.*; import ghidra.app.plugin.core.datamgr.archive.*; @@ -55,12 +56,10 @@ import ghidra.program.model.listing.DataTypeArchive; import ghidra.program.model.listing.Program; import ghidra.util.*; import ghidra.util.task.SwingUpdateManager; -import resources.ResourceManager; import util.HistoryList; public class DataTypesProvider extends ComponentProviderAdapter { - private static final String DATA_TYPES_ICON = "images/dataTypes.png"; private static final String TITLE = "Data Type Manager"; private static final String POINTER_FILTER_STATE = "PointerFilterState"; private static final String ARRAY_FILTER_STATE = "ArrayFilterState"; @@ -103,7 +102,7 @@ public class DataTypesProvider extends ComponentProviderAdapter { this.plugin = plugin; setTitle(TITLE); - setIcon(ResourceManager.loadImage(DATA_TYPES_ICON)); + setIcon(new GIcon("icon.plugin.datatypes.provider")); addToToolbar(); navigationHistory.setAllowDuplicates(true); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CollapseAllArchivesAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CollapseAllArchivesAction.java index da37e16902..a84f5a96cb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CollapseAllArchivesAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CollapseAllArchivesAction.java @@ -19,7 +19,7 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.List; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.tree.TreePath; import docking.ActionContext; @@ -40,7 +40,7 @@ import resources.Icons; */ public class CollapseAllArchivesAction extends DockingAction { - private ImageIcon collapseIcon = Icons.COLLAPSE_ALL_ICON; + private Icon collapseIcon = Icons.COLLAPSE_ALL_ICON; private final DataTypeManagerPlugin plugin; public CollapseAllArchivesAction(DataTypeManagerPlugin plugin) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/ConflictHandlerModesAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/ConflictHandlerModesAction.java index 872813e847..33eed2e402 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/ConflictHandlerModesAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/ConflictHandlerModesAction.java @@ -20,11 +20,11 @@ import javax.swing.Icon; import docking.menu.ActionState; import docking.menu.MultiStateDockingAction; import docking.widgets.EventTrigger; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.program.model.data.DataTypeConflictHandler; import ghidra.program.model.data.DataTypeConflictHandler.ConflictResolutionPolicy; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class ConflictHandlerModesAction extends MultiStateDockingAction{ @@ -41,10 +41,12 @@ public class ConflictHandlerModesAction extends new HelpLocation(plugin.getName(), "conflict_mode"); setHelpLocation(conflictModesHelpLocation); - Icon renameAndAddIcon = ResourceManager.loadImage("images/conflictRename.png"); - Icon useExistingIcon = ResourceManager.loadImage("images/conflictKeep.png"); - Icon replaceExistingIcon = ResourceManager.loadImage("images/conflictReplace.png"); - Icon replaceDefaultIcon = ResourceManager.loadImage("images/conflictReplaceOrRename.png"); + //@formatter:off + Icon renameAndAddIcon = new GIcon("icon.plugin.datatypes.conflict.mode.rename.and.add"); + Icon useExistingIcon = new GIcon("icon.plugin.datatypes.conflict.mode.use.existing"); + Icon replaceExistingIcon = new GIcon("icon.plugin.datatypes.conflict.mode.replace.existing"); + Icon replaceDefaultIcon = new GIcon("icon.plugin.datatypes.conflict.mode.replace.or.rename"); + //@formatter:on ActionState renameAndAddState = new ActionState<>( diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/DeleteArchiveAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/DeleteArchiveAction.java index ee790a84b3..7e2343a725 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/DeleteArchiveAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/DeleteArchiveAction.java @@ -24,6 +24,7 @@ import docking.ActionContext; import docking.action.*; import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.DataTypesActionContext; import ghidra.app.plugin.core.datamgr.archive.FileArchive; @@ -95,7 +96,8 @@ public class DeleteArchiveAction extends DockingAction { "Confirm Delete Operation", "Are you sure you want to delete archive: " + HTMLUtilities.escapeHTML(node.getName()) + "?
" + - "(WARNING: This action will permanently " + + "(WARNING: This action will permanently " + "delete the file from disk.)", "Yes", OptionDialog.QUESTION_MESSAGE) != OptionDialog.OPTION_ONE) { return; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterArraysAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterArraysAction.java index 1f405edfa9..95253ccff3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterArraysAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterArraysAction.java @@ -23,22 +23,23 @@ import javax.swing.tree.TreePath; import docking.ActionContext; import docking.action.ToggleDockingAction; import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.DataTypesActionContext; import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree; import ghidra.util.HTMLUtilities; -import resources.ResourceManager; public class FilterArraysAction extends ToggleDockingAction { - private static final Icon FILTER_ARRAYS_ICON = - ResourceManager.loadImage("images/FilterArrays.png"); - private static final Icon ARRAY_ICON = ResourceManager.loadImage("images/Array.png"); + //@formatter:off + private static final Icon FILTER_ON_ICON = new GIcon("icon.plugin.datatypes.filter.arrays.on"); + private static final Icon FILTER_OFF_ICON = new GIcon("icon.plugin.datatypes.filter.arrays.off"); + //@formatter:on public FilterArraysAction(DataTypeManagerPlugin plugin) { super("Filter Arrays", plugin.getName()); - this.setToolBarData(new ToolBarData(FILTER_ARRAYS_ICON, "filters")); + this.setToolBarData(new ToolBarData(FILTER_ON_ICON, "filters")); setDescription(HTMLUtilities.toHTML( "Toggle whether or not Arrays are\n" + "displayed in the Data Type Manager tree.")); @@ -66,7 +67,7 @@ public class FilterArraysAction extends ToggleDockingAction { @Override public void setSelected(boolean selected) { - getToolBarData().setIcon(selected ? FILTER_ARRAYS_ICON : ARRAY_ICON); + getToolBarData().setIcon(selected ? FILTER_ON_ICON : FILTER_OFF_ICON); super.setSelected(selected); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterPointersAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterPointersAction.java index d1b3cfb29a..e3f587aa77 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterPointersAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/FilterPointersAction.java @@ -23,21 +23,23 @@ import javax.swing.tree.TreePath; import docking.ActionContext; import docking.action.ToggleDockingAction; import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.DataTypesActionContext; import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree; import ghidra.util.HTMLUtilities; -import resources.ResourceManager; public class FilterPointersAction extends ToggleDockingAction { - private static final Icon FILTER_POINTERS_ICON = - ResourceManager.loadImage("images/FilterPointers.png"); - private static final Icon POINTER_ICON = ResourceManager.loadImage("images/fingerPointer.png"); + + //@formatter:off + private static final Icon FILTER_ON_ICON = new GIcon("icon.plugin.datatypes.filter.pointers.on"); + private static final Icon FILTER_OFF_ICON = new GIcon("icon.plugin.datatypes.filter.pointers.off"); + //@formatter:on public FilterPointersAction(DataTypeManagerPlugin plugin) { super("Filter Pointers", plugin.getName()); - this.setToolBarData(new ToolBarData(FILTER_POINTERS_ICON, "filters")); + this.setToolBarData(new ToolBarData(FILTER_ON_ICON, "filters")); setDescription(HTMLUtilities.toHTML( "Toggle whether or not Pointers are\n" + "displayed in the Data Type Manager tree.")); @@ -67,7 +69,7 @@ public class FilterPointersAction extends ToggleDockingAction { @Override public void setSelected(boolean selected) { - getToolBarData().setIcon(selected ? FILTER_POINTERS_ICON : POINTER_ICON); + getToolBarData().setIcon(selected ? FILTER_ON_ICON : FILTER_OFF_ICON); super.setSelected(selected); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RemoveInvalidArchiveFromProgramAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RemoveInvalidArchiveFromProgramAction.java index 2b8b847c18..43895edceb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RemoveInvalidArchiveFromProgramAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RemoveInvalidArchiveFromProgramAction.java @@ -23,6 +23,7 @@ import docking.action.MenuData; import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.DataTypesActionContext; import ghidra.app.plugin.core.datamgr.archive.*; @@ -79,7 +80,8 @@ public class RemoveInvalidArchiveFromProgramAction extends DockingAction { "Are you sure you want to delete archive: " + HTMLUtilities.escapeHTML(invalidArchiveNode.getName()) + " from the program?
" + - "(WARNING: This action will disassociate " + + "(WARNING: This action will disassociate " + "all datatypes in the program from this archive.)", "Yes", OptionDialog.QUESTION_MESSAGE) != OptionDialog.OPTION_ONE) { return; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/TypeGraphTask.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/TypeGraphTask.java index 2f82ea310d..ee9ed3929b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/TypeGraphTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/TypeGraphTask.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.datamgr.actions; import java.awt.Color; +import generic.theme.GColor; import ghidra.app.util.ToolTipUtils; import ghidra.program.model.data.*; import ghidra.service.graph.*; @@ -33,6 +34,13 @@ import ghidra.util.task.TaskMonitor; */ public class TypeGraphTask extends Task { + private static final Color BG_COLOR_DEFAULT = + new GColor("color.bg.plugin.datamgr.edge.default"); + private static final Color BG_COLOR_COMPOSITE = + new GColor("color.bg.plugin.datamgr.edge.composite"); + private static final Color BG_COLOR_REFERERNCE = + new GColor("color.bg.plugin.datamgr.edge.reference"); + private DataType type; private String graphTitle; private GraphDisplayProvider graphService; @@ -64,9 +72,9 @@ public class TypeGraphTask extends Task { .build(); GraphDisplayOptions options = new GraphDisplayOptionsBuilder(graphType) - .defaultVertexColor(Color.BLUE) - .edge(COMPOSITE, Color.MAGENTA) - .edge(REFERENCE, Color.BLUE) + .defaultVertexColor(BG_COLOR_DEFAULT) + .edge(COMPOSITE, BG_COLOR_COMPOSITE) + .edge(REFERENCE, BG_COLOR_REFERERNCE) .build(); AttributedGraph graph = new AttributedGraph(graphTitle, graphType); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/CommitSingleDataTypeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/CommitSingleDataTypeAction.java index 63b169a023..4fe152dbc8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/CommitSingleDataTypeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/CommitSingleDataTypeAction.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.datamgr.actions.associate; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.tree.TreePath; import docking.ActionContext; @@ -24,6 +24,7 @@ import docking.action.MenuData; import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.*; import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler; import ghidra.app.plugin.core.datamgr.tree.DataTypeNode; @@ -31,13 +32,12 @@ import ghidra.app.plugin.core.datamgr.util.DataTypeUtils; import ghidra.program.model.data.*; import ghidra.util.Msg; import resources.MultiIcon; -import resources.ResourceManager; import resources.icons.EmptyIcon; import resources.icons.TranslateIcon; public class CommitSingleDataTypeAction extends DockingAction { - private static ImageIcon COMMIT_ICON = ResourceManager.loadImage("images/smallRightArrow.png"); + private static Icon COMMIT_ICON = new GIcon("icon.plugin.datatypes.commit.single.type"); private final DataTypeManagerPlugin plugin; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/UpdateSingleDataTypeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/UpdateSingleDataTypeAction.java index a604a2e470..e0cb3d5a7c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/UpdateSingleDataTypeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/UpdateSingleDataTypeAction.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.datamgr.actions.associate; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.tree.TreePath; import docking.ActionContext; @@ -24,19 +24,19 @@ import docking.action.MenuData; import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.*; import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler; import ghidra.app.plugin.core.datamgr.tree.DataTypeNode; import ghidra.app.plugin.core.datamgr.util.DataTypeUtils; import ghidra.program.model.data.*; import resources.MultiIcon; -import resources.ResourceManager; import resources.icons.EmptyIcon; import resources.icons.TranslateIcon; public class UpdateSingleDataTypeAction extends DockingAction { - private static ImageIcon UPDATE_ICON = ResourceManager.loadImage("images/smallLeftArrow.png"); + private static Icon UPDATE_ICON = new GIcon("icon.plugin.datatypes.associate.single.type"); private final DataTypeManagerPlugin plugin; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/Archive.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/Archive.java index d7f44f016f..77a349dbba 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/Archive.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/Archive.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +15,13 @@ */ package ghidra.app.plugin.core.datamgr.archive; -import ghidra.app.merge.DataTypeManagerOwner; -import ghidra.util.exception.DuplicateFileException; - import java.awt.Component; import java.io.IOException; -import javax.swing.ImageIcon; +import javax.swing.Icon; + +import ghidra.app.merge.DataTypeManagerOwner; +import ghidra.util.exception.DuplicateFileException; /** * This is an interface for data type archives. @@ -63,13 +62,15 @@ public interface Archive extends DataTypeManagerOwner, Comparable{ /** * Saves this archive. Some archives cannot be saved. + * @throws DuplicateFileException if there is an exception saving + * @throws IOException if there is an exception saving */ public void save() throws DuplicateFileException, IOException; /** * Saves this archive to a newly named file. - * @param component - * @throws IOException + * @param component the parent component the any dialogs shown + * @throws IOException if there is an exception saving */ public void saveAs(Component component) throws IOException; @@ -79,5 +80,5 @@ public interface Archive extends DataTypeManagerOwner, Comparable { * false indicates the node is closed. * @return the archive's icon. */ - public ImageIcon getIcon(boolean expanded); + public Icon getIcon(boolean expanded); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/BuiltInArchive.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/BuiltInArchive.java index d8eff7bcd7..9a874a75aa 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/BuiltInArchive.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/BuiltInArchive.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,21 +15,20 @@ */ package ghidra.app.plugin.core.datamgr.archive; +import java.awt.Component; +import java.io.IOException; + +import javax.swing.Icon; + +import generic.theme.GIcon; import ghidra.program.model.data.BuiltInDataTypeManager; import ghidra.program.model.data.DataTypeManager; import ghidra.util.exception.DuplicateFileException; -import java.awt.Component; -import java.io.IOException; - -import javax.swing.ImageIcon; - -import resources.ResourceManager; - public class BuiltInArchive implements Archive { - private static ImageIcon CLOSED_ICON = ResourceManager.loadImage("images/closedBookBrown.png"); - private static ImageIcon OPEN_ICON = ResourceManager.loadImage("images/openBookBrown.png"); + private static Icon CLOSED_ICON = new GIcon("icon.plugin.datatypes.archive.built.in.closed"); + private static Icon OPEN_ICON = new GIcon("icon.plugin.datatypes.archive.built.in.open"); private DataTypeManagerHandler archiveManager; private BuiltInDataTypeManager dataTypeManager; @@ -39,43 +37,53 @@ public class BuiltInArchive implements Archive { this.dataTypeManager = dataTypeManager; } + @Override public DataTypeManager getDataTypeManager() { return dataTypeManager; } + @Override public String getName() { return dataTypeManager.getName(); } + @Override public int compareTo(Archive archive) { return -1; // Built-ins are always at the top } + @Override public boolean isModifiable() { return false; // Can't change the data types that are in Built-Ins. } + @Override public void close() { // Not allowed to close the Built In Data Type Manager. } + @Override public boolean isChanged() { return false; // Can't change. } + @Override public boolean isSavable() { return false; // Can't save. } + @Override public void save() throws DuplicateFileException, IOException { // Can't "Save" so do nothing. } + @Override public void saveAs(Component component) throws IOException { // Can't "Save As" so do nothing. } - public ImageIcon getIcon(boolean expanded) { + @Override + public Icon getIcon(boolean expanded) { return expanded ? OPEN_ICON : CLOSED_ICON; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/FileArchive.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/FileArchive.java index e231a4d2bd..2bd2685b94 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/FileArchive.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/FileArchive.java @@ -19,13 +19,13 @@ import java.awt.Component; import java.io.File; import java.io.IOException; -import javax.swing.ImageIcon; +import javax.swing.Icon; import generic.jar.ResourceFile; +import generic.theme.GIcon; import ghidra.framework.store.LockException; import ghidra.program.model.data.*; import ghidra.util.exception.DuplicateFileException; -import resources.ResourceManager; /** * Manages a DataTypeFileManager and relative state. For example, whether the manager is writable @@ -33,8 +33,8 @@ import resources.ResourceManager; */ public class FileArchive implements Archive { - private static ImageIcon CLOSED_ICON = ResourceManager.loadImage("images/closedBookGreen.png"); - private static ImageIcon OPEN_ICON = ResourceManager.loadImage("images/openBookGreen.png"); + private static Icon CLOSED_ICON = new GIcon("icon.plugin.datatypes.archive.file.closed"); + private static Icon OPEN_ICON = new GIcon("icon.plugin.datatypes.archive.file.open"); private ResourceFile archiveFile; private boolean hasWriteLock; private boolean changed; @@ -292,7 +292,7 @@ public class FileArchive implements Archive { } @Override - public ImageIcon getIcon(boolean expanded) { + public Icon getIcon(boolean expanded) { return expanded ? OPEN_ICON : CLOSED_ICON; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/InvalidFileArchive.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/InvalidFileArchive.java index e62ebb58d9..526fc35932 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/InvalidFileArchive.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/InvalidFileArchive.java @@ -18,17 +18,17 @@ package ghidra.app.plugin.core.datamgr.archive; import java.awt.Component; import java.io.IOException; -import javax.swing.ImageIcon; +import javax.swing.Icon; +import generic.theme.GIcon; import ghidra.program.model.data.*; import ghidra.util.UniversalID; import ghidra.util.exception.DuplicateFileException; -import resources.ResourceManager; public class InvalidFileArchive implements Archive { - private static final ImageIcon INVALID_ARCHIVE_ICON = - ResourceManager.loadImage("images/closedFolderInvalid.png"); + private static final Icon INVALID_ARCHIVE_ICON = + new GIcon("icon.plugin.datatypes.archive.invalid"); private DataTypeManagerHandler archiveManager; private UniversalID universalID; private ArchiveType archiveType; @@ -104,7 +104,7 @@ public class InvalidFileArchive implements Archive { } @Override - public ImageIcon getIcon(boolean expanded) { + public Icon getIcon(boolean expanded) { return INVALID_ARCHIVE_ICON; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProgramArchive.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProgramArchive.java index 386a59c45a..b07baf6cea 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProgramArchive.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProgramArchive.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +15,22 @@ */ package ghidra.app.plugin.core.datamgr.archive; +import java.awt.Component; +import java.io.IOException; + +import javax.swing.Icon; + +import generic.theme.GIcon; import ghidra.framework.model.DomainFile; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.data.DataTypeManagerChangeListener; import ghidra.program.model.listing.Program; import ghidra.util.exception.DuplicateFileException; -import java.awt.Component; -import java.io.IOException; - -import javax.swing.ImageIcon; - -import resources.ResourceManager; - public class ProgramArchive implements DomainFileArchive { - private static ImageIcon CLOSED_ICON = ResourceManager.loadImage("images/closedBookRed.png"); - private static ImageIcon OPEN_ICON = ResourceManager.loadImage("images/openBookRed.png"); + private static Icon CLOSED_ICON = new GIcon("icon.plugin.datatypes.archive.program.closed"); + private static Icon OPEN_ICON = new GIcon("icon.plugin.datatypes.archive.program.open"); private final Program program; DataTypeManagerChangeListener categoryListener; // hold on to since it is stored in a weak set private DataTypeManager dataTypeManager; @@ -105,7 +103,7 @@ public class ProgramArchive implements DomainFileArchive { } @Override - public ImageIcon getIcon(boolean expanded) { + public Icon getIcon(boolean expanded) { return expanded ? OPEN_ICON : CLOSED_ICON; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProjectArchive.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProjectArchive.java index ddea7e1858..8dd3531961 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProjectArchive.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/ProjectArchive.java @@ -15,21 +15,20 @@ */ package ghidra.app.plugin.core.datamgr.archive; +import java.awt.Component; +import java.io.IOException; + +import javax.swing.Icon; + +import generic.theme.GIcon; import ghidra.framework.model.DomainFile; import ghidra.program.model.data.*; import ghidra.program.model.listing.DataTypeArchive; -import java.awt.Component; -import java.io.IOException; - -import javax.swing.ImageIcon; - -import resources.ResourceManager; - public class ProjectArchive implements DomainFileArchive { - private static ImageIcon CLOSED_ICON = ResourceManager.loadImage("images/closedBookBlue.png"); - private static ImageIcon OPEN_ICON = ResourceManager.loadImage("images/openBookBlue.png"); + private static Icon CLOSED_ICON = new GIcon("icon.plugin.datatypes.archive.project.closed"); + private static Icon OPEN_ICON = new GIcon("icon.plugin.datatypes.archive.project.open"); private DataTypeArchive dataTypeArchive; private DomainFile originalDomainFile; DataTypeManagerChangeListener categoryListener; // hold on to since it is stored in a weak set @@ -115,7 +114,7 @@ public class ProjectArchive implements DomainFileArchive { } @Override - public ImageIcon getIcon(boolean expanded) { + public Icon getIcon(boolean expanded) { return expanded ? OPEN_ICON : CLOSED_ICON; } @@ -140,7 +139,8 @@ public class ProjectArchive implements DomainFileArchive { } @Override - public void categoryRenamed(DataTypeManager dtm, CategoryPath oldPath, CategoryPath newPath) { + public void categoryRenamed(DataTypeManager dtm, CategoryPath oldPath, + CategoryPath newPath) { if (!oldPath.equals(newPath)) { fireStateChanged(); } @@ -167,7 +167,8 @@ public class ProjectArchive implements DomainFileArchive { } @Override - public void dataTypeRenamed(DataTypeManager dtm, DataTypePath oldPath, DataTypePath newPath) { + public void dataTypeRenamed(DataTypeManager dtm, DataTypePath oldPath, + DataTypePath newPath) { fireStateChanged(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorProvider.java index e82d4a6388..e9672e30ac 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/EnumEditorProvider.java @@ -19,7 +19,7 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.util.*; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -31,6 +31,8 @@ import docking.ActionContext; import docking.ComponentProvider; import docking.action.*; import docking.widgets.OptionDialog; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.compositeeditor.EditorListener; import ghidra.app.plugin.core.compositeeditor.EditorProvider; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; @@ -45,7 +47,6 @@ import ghidra.util.*; import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; import ghidra.util.exception.DuplicateNameException; -import resources.ResourceManager; import util.CollectionUtils; /** @@ -54,11 +55,10 @@ import util.CollectionUtils; public class EnumEditorProvider extends ComponentProviderAdapter implements ChangeListener, EditorProvider { - static final ImageIcon EDITOR_ICON = ResourceManager.loadImage("images/enum.png"); - private final static ImageIcon APPLY_ICON = ResourceManager.loadImage("images/disk.png"); - private final static ImageIcon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private final static ImageIcon DELETE_ICON = - ResourceManager.loadImage("images/edit-delete.png"); + static final Icon EDITOR_ICON = new GIcon("icon.plugin.enum.editor.provider"); + private final static Icon APPLY_ICON = new GIcon("icon.plugin.enum.editor.apply"); + private final static Icon ADD_ICON = new GIcon("icon.plugin.enum.editor.add"); + private final static Icon DELETE_ICON = new GIcon("icon.plugin.enum.editor.delete"); private final static String HELP_TOPIC = "DataTypeEditors"; private final static int CANCEL = 0; @@ -302,7 +302,7 @@ public class EnumEditorProvider extends ComponentProviderAdapter showEnumAction.setEnabled(true); String thirdGroup = "FThirdGroup"; showEnumAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/go-home.png"), thirdGroup)); + new ToolBarData(new GIcon("icon.plugin.enum.editor.home"), thirdGroup)); tool.addLocalAction(this, applyAction); tool.addLocalAction(this, addAction); @@ -400,8 +400,9 @@ public class EnumEditorProvider extends ComponentProviderAdapter private int showOptionDialog(Enum editedEnoom, Set oldNameFields) { StringBuilder msg = new StringBuilder( - "If you save this Enum with the new value(s)" + - " listed below,
it will invalidate equates created with the old value(s).
"); + "If you save this Enum with the new value(s) listed below,
" + + " it will invalidate equates created with the old value(s).
"); msg.append(""); for (String field : oldNameFields) { String newVal; @@ -412,13 +413,16 @@ public class EnumEditorProvider extends ComponentProviderAdapter // Happens if a field is deleted or there is a name AND value change. newVal = "Missing"; } - msg.append(String.format("
"); msg.append( - "Invalidated equates can be automatically removed now or- %s: 0x%s \u2192 %s
", + msg.append(String.format( + "- %s: 0x%s \u2192 %s
", HTMLUtilities.escapeHTML(field), Long.toHexString(originalEnum.getValue(field)), newVal)); } msg.append("
managed later from the Equates Table
managed later from the" + + " Equates Table window."); msg.append(""); int choice = OptionDialog.showOptionDialog(editorPanel, "Equate Conflicts", msg.toString(), "Save and remove", "Save", OptionDialog.ERROR_MESSAGE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/BackgroundIcon.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/BackgroundIcon.java index 623bf08c0f..bc14480e9d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/BackgroundIcon.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/BackgroundIcon.java @@ -19,10 +19,15 @@ import java.awt.*; import javax.swing.Icon; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Palette; + class BackgroundIcon implements Icon { - private static Color VERSION_ICON_COLOR_DARK = new Color(0x82, 0x82, 0xff); - private static Color VERSION_ICON_COLOR_LIGHT = new Color(0x9f, 0x9f, 0xff); + private static Color VERSION_ICON_COLOR_LINE = new GColor("color.bg.tree.renderer.icon.line"); + private static Color VERSION_ICON_COLOR_LIGHT = new GColor("color.bg.tree.renderer.icon.fill"); + + private static Color ALPHA = Palette.NO_COLOR; private int width; private int height; @@ -49,14 +54,14 @@ class BackgroundIcon implements Icon { if (isVersioned) { g.setColor(VERSION_ICON_COLOR_LIGHT); g.fillRect(x + 1, y + 1, width - 2, height - 2); - g.setColor(VERSION_ICON_COLOR_DARK); + g.setColor(VERSION_ICON_COLOR_LINE); g.drawLine(x + 1, y, x + width - 2, y); g.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2); g.drawLine(x + 1, y + height - 1, x + width - 2, y + height - 1); g.drawLine(x, y + 1, x, y + height - 2); } else { - g.setColor(c.getBackground()); + g.setColor(ALPHA); g.fillRect(x, y, width, height); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java index 7e40136a78..0957e3e537 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java @@ -27,6 +27,7 @@ import javax.swing.tree.TreePath; import docking.widgets.tree.*; import docking.widgets.tree.internal.DefaultGTreeDataTransformer; import docking.widgets.tree.support.GTreeRenderer; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.*; import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler; import ghidra.app.plugin.core.datamgr.archive.FileArchive; @@ -39,16 +40,13 @@ import ghidra.program.model.listing.Program; import ghidra.util.UniversalID; import ghidra.util.task.TaskMonitor; import resources.MultiIcon; -import resources.ResourceManager; import resources.icons.TranslateIcon; public class DataTypeArchiveGTree extends GTree { - private static ImageIcon LOCAL_DELTA_ICON = - ResourceManager.loadImage("images/smallRightArrow.png"); - private static ImageIcon SOURCE_DELTA_ICON = - ResourceManager.loadImage("images/smallLeftArrow.png"); - private static ImageIcon CONFLICT_ICON = ResourceManager.loadImage("images/doubleArrow.png"); - private static ImageIcon MISSING_ICON = ResourceManager.loadImage("images/redQuestionMark.png"); + private static Icon LOCAL_DELTA_ICON = new GIcon("icon.plugin.datatypes.tree.change.local"); + private static Icon SOURCE_DELTA_ICON = new GIcon("icon.plugin.datatypes.tree.change.source"); + private static Icon CONFLICT_ICON = new GIcon("icon.plugin.datatypes.tree.conflict"); + private static Icon MISSING_ICON = new GIcon("icon.plugin.datatypes.tree.missing"); private DataTypeManagerPlugin plugin; private GTreeNode armedNode; @@ -335,7 +333,7 @@ public class DataTypeArchiveGTree extends GTree { // work around an issue on some platforms where the label is painting a color that // does not match the tree label.setBackground( - isSelected ? getBackgroundSelectionColor() : tree.getBackground()); + isSelected ? getBackgroundSelectionColor() : getBackgroundNonSelectionColor()); } MultiIcon multiIcon = new MultiIcon( @@ -362,7 +360,6 @@ public class DataTypeArchiveGTree extends GTree { } setIcon(multiIcon); - return label; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DomainFileArchiveNode.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DomainFileArchiveNode.java index fdc506ec51..d795484be3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DomainFileArchiveNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DomainFileArchiveNode.java @@ -16,27 +16,25 @@ package ghidra.app.plugin.core.datamgr.tree; import javax.swing.Icon; -import javax.swing.ImageIcon; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.archive.DomainFileArchive; import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainObject; import ghidra.program.model.listing.Program; import ghidra.util.HTMLUtilities; import resources.MultiIcon; -import resources.ResourceManager; import resources.icons.TranslateIcon; public class DomainFileArchiveNode extends ArchiveNode { - private static ImageIcon CHECKED_OUT_ICON = ResourceManager.loadImage("images/check.png"); - private static ImageIcon CHECKED_OUT_EXCLUSIVE_ICON = - ResourceManager.loadImage("images/checkex.png"); - private static ImageIcon HIJACKED_ICON = ResourceManager.loadImage("images/small_hijack.gif"); - private static ImageIcon READ_ONLY_ICON = - ResourceManager.loadImage("images/user-busy.png", 10, 10); - private static ImageIcon NOT_LATEST_CHECKED_OUT_ICON = - ResourceManager.loadImage("images/checkNotLatest.gif"); + //@formatter:off + private static Icon CHECKED_OUT_ICON = new GIcon("icon.plugin.datatypes.tree.node.archive.file.checked.out"); + private static Icon CHECKED_OUT_EXCLUSIVE_ICON = new GIcon("icon.plugin.datatypes.tree.node.archive.file.checked.out.exclusive"); + private static Icon HIJACKED_ICON = new GIcon("icon.plugin.datatypes.tree.node.archive.file.hijacked"); + private static Icon READ_ONLY_ICON = new GIcon("icon.plugin.datatypes.tree.node.archive.file.read.only"); + private static Icon NOT_LATEST_CHECKED_OUT_ICON = new GIcon("icon.plugin.datatypes.tree.node.archive.file.checked.out.not.latest"); + //@formatter:on private boolean isChanged; private boolean isReadOnly; @@ -116,7 +114,7 @@ public class DomainFileArchiveNode extends ArchiveNode { @Override public Icon getIcon(boolean expanded) { - ImageIcon baseIcon = archive.getIcon(expanded); + Icon baseIcon = archive.getIcon(expanded); BackgroundIcon bgIcon = new BackgroundIcon(24, 16, isVersioned); MultiIcon multiIcon = new MultiIcon(bgIcon); multiIcon.addIcon(baseIcon); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/FileArchiveNode.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/FileArchiveNode.java index 4d12f658f8..1eb46bc540 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/FileArchiveNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/FileArchiveNode.java @@ -16,19 +16,18 @@ package ghidra.app.plugin.core.datamgr.tree; import javax.swing.Icon; -import javax.swing.ImageIcon; import generic.jar.ResourceFile; +import generic.theme.GIcon; import ghidra.app.plugin.core.datamgr.archive.FileArchive; import ghidra.util.HTMLUtilities; import resources.MultiIcon; -import resources.ResourceManager; import resources.icons.TranslateIcon; public class FileArchiveNode extends ArchiveNode { - private static ImageIcon CHECKED_OUT_EXCLUSIVE_ICON = - ResourceManager.loadImage("images/checkex.png"); + private static Icon CHECKED_OUT_EXCLUSIVE_ICON = + new GIcon("icon.plugin.datatypes.tree.node.archive.file.checked.out.exclusive"); FileArchive fileArchive; // casted reference for easy access @@ -42,7 +41,7 @@ public class FileArchiveNode extends ArchiveNode { BackgroundIcon bgIcon = new BackgroundIcon(24, 16, false); MultiIcon multiIcon = new MultiIcon(bgIcon); boolean hasWriteLock = fileArchive.hasWriteLock(); - ImageIcon baseIcon = fileArchive.getIcon(expanded); + Icon baseIcon = fileArchive.getIcon(expanded); multiIcon.addIcon(baseIcon); if (hasWriteLock) { multiIcon.addIcon(new TranslateIcon(CHECKED_OUT_EXCLUSIVE_ICON, 8, -4)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/ConflictDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/ConflictDialog.java index 6a80ab4935..2b7cfb779e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/ConflictDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/ConflictDialog.java @@ -16,7 +16,8 @@ package ghidra.app.plugin.core.datamgr.util; import java.awt.BorderLayout; -import java.awt.event.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import javax.swing.*; @@ -24,8 +25,8 @@ import docking.DialogComponentProvider; import docking.widgets.button.GRadioButton; import docking.widgets.label.GIconLabel; import docking.widgets.label.GLabel; +import generic.theme.GIcon; import ghidra.util.HelpLocation; -import resources.ResourceManager; /** * Dialog to get user input on how to handle data type conflicts. @@ -43,12 +44,12 @@ public class ConflictDialog extends DialogComponentProvider { private JButton applyToAllButton; private int selectedOption = RENAME; - private ImageIcon INFORM_ICON = ResourceManager.loadImage("images/warning.png"); + private Icon INFORM_ICON = new GIcon("icon.warning"); /** * Constructor * @param dtName data type name - * @param categoryName category path + * @param categoryPath category path * @param newDTName new name to resolve conflict */ public ConflictDialog(String dtName, String categoryPath, String newDTName) { @@ -58,27 +59,18 @@ public class ConflictDialog extends DialogComponentProvider { addOKButton(); applyToAllButton = new JButton("Apply to All"); - applyToAllButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - applyToAll = true; - close(); - } + applyToAllButton.addActionListener(e -> { + applyToAll = true; + close(); }); addButton(applyToAllButton); } - /* (non-Javadoc) - * @see ghidra.util.bean.GhidraDialog#okCallback() - */ @Override protected void okCallback() { close(); } - /* (non-Javadoc) - * @see ghidra.util.bean.GhidraDialog#cancelCallback() - */ @Override protected void cancelCallback() { close(); @@ -101,20 +93,17 @@ public class ConflictDialog extends DialogComponentProvider { mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - ItemListener listener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - Object source = e.getSource(); - if (source == replaceRB) { - selectedOption = REPLACE; - } - else if (source == useExistingRB) { - selectedOption = USE_EXISTING; - } - else { - selectedOption = RENAME; - } + ItemListener listener = e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + Object source = e.getSource(); + if (source == replaceRB) { + selectedOption = REPLACE; + } + else if (source == useExistingRB) { + selectedOption = USE_EXISTING; + } + else { + selectedOption = RENAME; } } }; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeUtils.java index 69a6462812..f637ed089e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeUtils.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeUtils.java @@ -20,8 +20,9 @@ import java.util.*; import java.util.List; import javax.swing.Icon; -import javax.swing.ImageIcon; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.app.services.DataTypeQueryService; import ghidra.program.model.data.*; import ghidra.program.model.data.Enum; @@ -37,28 +38,10 @@ public class DataTypeUtils { private static final char END_CHAR = '\uffff'; private static final char BEGIN_CHAR = '\u0000'; - private static MaphighlightIconMap = new HashMap<>(); + private static final Color COLOR_ICON_HIGHLIGHT = + new GColor("color.bg.plugin.datamgr.icon.highlight"); - private static String OPEN_FOLDER = "images/openFolder.png"; - private static String CLOSED_FOLDER = "images/closedFolder.png"; - private static String DISABLED_OPEN_FOLDER = "images/disabledOpenFolder.png"; - private static String DISABLED_CLOSED_FOLDER = "images/disabledClosedFolder.png"; - private static String DEFAULT_ICON = "images/defaultDt.gif"; - private static String DISABLED_DEFAULT_ICON = "images/disabledCode.gif"; - private static String LOCKED_OPEN_FOLDER = "images/openFolderCheckedOut.png"; - private static String LOCKED_CLOSED_FOLDER = "images/closedFolderCheckedOut.png"; - private static String OPEN_ARCHIVE_FOLDER = "images/openFolderArchive.png"; - private static String CLOSED_ARCHIVE_FOLDER = "images/closedFolderArchive.png"; - private static String ROOT_ICON = "images/BookShelf.png"; - private static String OPEN_ROOT_ICON = "images/BookShelfOpen.png"; - private static String FAVORITE_ICON = "images/emblem-favorite.png"; - private static String BUILT_IN_ICON = "images/package_development.png"; - private static String STRUCTURE_ICON = "images/cstruct.png"; - private static String UNION_ICON = "images/cUnion.png"; - private static String TYPEDEF_ICON = "images/typedef.png"; - private static String FUNCTION_ICON = "images/functionDef.png"; - private static String ENUM_ICON = "images/enum.png"; - private static String POINTER_ICON = "images/fingerPointer.png"; + private static Map highlightIconMap = new HashMap<>(); private static Icon defaultIcon; private static Icon disabledIcon; @@ -89,29 +72,29 @@ public class DataTypeUtils { return; } imagesLoaded = true; - defaultIcon = ResourceManager.loadImage(DEFAULT_ICON); - disabledIcon = ResourceManager.loadImage(DISABLED_DEFAULT_ICON); + defaultIcon = new GIcon("icon.plugin.datatypes.default"); + disabledIcon = new GIcon("icon.plugin.datatypes.default.disabled"); - favoriteIcon = ResourceManager.loadImage(FAVORITE_ICON); - disabledFavoriteIcon = ResourceManager.getDisabledIcon((ImageIcon) favoriteIcon); + favoriteIcon = new GIcon("icon.plugin.datatypes.util.favorite"); + disabledFavoriteIcon = new GIcon("icon.plugin.datatypes.util.favorite.disabled"); - builtInIcon = ResourceManager.loadImage(BUILT_IN_ICON); - disabledBuiltInIcon = ResourceManager.getDisabledIcon((ImageIcon) builtInIcon); + builtInIcon = new GIcon("icon.plugin.datatypes.built.in"); + disabledBuiltInIcon = new GIcon("icon.plugin.datatypes.built.in.disabled"); - rootIcon = ResourceManager.loadImage(ROOT_ICON); - openRootIcon = ResourceManager.loadImage(OPEN_ROOT_ICON); + rootIcon = new GIcon("icon.plugin.datatypes.util.root"); + openRootIcon = new GIcon("icon.plugin.datatypes.util.open.root"); - openFolderIcon = ResourceManager.loadImage(OPEN_FOLDER); - disabledOpenFolderIcon = ResourceManager.loadImage(DISABLED_OPEN_FOLDER); + openFolderIcon = new GIcon("icon.plugin.datatypes.util.open.folder"); + disabledOpenFolderIcon = new GIcon("icon.plugin.datatypes.util.open.folder.disabled"); - closedFolderIcon = ResourceManager.loadImage(CLOSED_FOLDER); - disabledClosedFolderIcon = ResourceManager.loadImage(DISABLED_CLOSED_FOLDER); + closedFolderIcon = new GIcon("icon.plugin.datatypes.util.closed.folder"); + disabledClosedFolderIcon = new GIcon("icon.plugin.datatypes.util.closed.folder.disabled"); - lockedOpenFolderIcon = ResourceManager.loadImage(LOCKED_OPEN_FOLDER); - lockedClosedFolderIcon = ResourceManager.loadImage(LOCKED_CLOSED_FOLDER); + lockedOpenFolderIcon = new GIcon("icon.plugin.datatypes.util.open.folder.locked"); + lockedClosedFolderIcon = new GIcon("icon.plugin.datatypes.util.closed.folder.locked"); - openArchiveFolderIcon = ResourceManager.loadImage(OPEN_ARCHIVE_FOLDER); - closedArchiveFolderIcon = ResourceManager.loadImage(CLOSED_ARCHIVE_FOLDER); + openArchiveFolderIcon = new GIcon("icon.plugin.datatypes.util.open.archive"); + closedArchiveFolderIcon = new GIcon("icon.plugin.datatypes.util.closed.archive"); createDataTypeIcons(); @@ -120,29 +103,29 @@ public class DataTypeUtils { private static void createDataTypeIcons() { List list = new ArrayList<>(); - Icon enumIcon = ResourceManager.loadImage(ENUM_ICON); + Icon enumIcon = new GIcon("icon.plugin.datatypes.enum"); list.add(new DataTypeIconWrapper(Enum.class, enumIcon, - ResourceManager.getDisabledIcon((ImageIcon) enumIcon))); + ResourceManager.getDisabledIcon(enumIcon))); - Icon functionIcon = ResourceManager.loadImage(FUNCTION_ICON); + Icon functionIcon = new GIcon("icon.plugin.datatypes.function"); list.add(new DataTypeIconWrapper(FunctionDefinition.class, functionIcon, - ResourceManager.getDisabledIcon((ImageIcon) functionIcon))); + ResourceManager.getDisabledIcon(functionIcon))); - Icon pointerIcon = ResourceManager.loadImage(POINTER_ICON); + Icon pointerIcon = new GIcon("icon.plugin.datatypes.pointer"); list.add(new DataTypeIconWrapper(Pointer.class, pointerIcon, - ResourceManager.getDisabledIcon((ImageIcon) pointerIcon))); + ResourceManager.getDisabledIcon(pointerIcon))); - Icon typedefIcon = ResourceManager.loadImage(TYPEDEF_ICON); + Icon typedefIcon = new GIcon("icon.plugin.datatypes.typedef"); list.add(new DataTypeIconWrapper(TypeDef.class, typedefIcon, - ResourceManager.getDisabledIcon((ImageIcon) typedefIcon))); + ResourceManager.getDisabledIcon(typedefIcon))); - Icon unionIcon = ResourceManager.loadImage(UNION_ICON); + Icon unionIcon = new GIcon("icon.plugin.datatypes.union"); list.add(new DataTypeIconWrapper(Union.class, unionIcon, - ResourceManager.getDisabledIcon((ImageIcon) unionIcon))); + ResourceManager.getDisabledIcon(unionIcon))); - Icon structureIcon = ResourceManager.loadImage(STRUCTURE_ICON); + Icon structureIcon = new GIcon("icon.plugin.datatypes.structure"); list.add(new DataTypeIconWrapper(Structure.class, structureIcon, - ResourceManager.getDisabledIcon((ImageIcon) structureIcon))); + ResourceManager.getDisabledIcon(structureIcon))); dataTypeIconWrappers = list.toArray(new DataTypeIconWrapper[list.size()]); } @@ -281,7 +264,7 @@ public class DataTypeUtils { MultiIcon highlightIcon = highlightIconMap.get(baseIcon); if (highlightIcon == null) { - highlightIcon = new MultiIcon(new HighlightIcon(new Color(204, 204, 255))); + highlightIcon = new MultiIcon(new HighlightIcon(COLOR_ICON_HIGHLIGHT)); highlightIcon.addIcon(baseIcon); highlightIconMap.put(baseIcon, highlightIcon); } @@ -461,7 +444,6 @@ public class DataTypeUtils { } Msg.showInfo(DataTypeUtils.class, parent, title, msg); } - } //================================================================================================== @@ -533,45 +515,3 @@ class HighlightIcon implements Icon { g.drawRect(x, y, WIDTH + 1, HEIGHT - 1); } } - -class VersionIcon implements Icon { - - private static Color VERSION_ICON_COLOR_DARK = new Color(0x82, 0x82, 0xff); - private static Color VERSION_ICON_COLOR_LIGHT = new Color(0x9f, 0x9f, 0xff); - - private static final int WIDTH = 18; - private static final int HEIGHT = 17; - - int width; - int height; - - VersionIcon() { - this(WIDTH, HEIGHT); - } - - VersionIcon(int width, int height) { - this.width = width; - this.height = height; - } - - @Override - public int getIconHeight() { - return height; - } - - @Override - public int getIconWidth() { - return width; - } - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - g.setColor(VERSION_ICON_COLOR_LIGHT); - g.fillRect(x + 1, y + 1, width - 2, height - 2); - g.setColor(VERSION_ICON_COLOR_DARK); - g.drawLine(x + 1, y, x + width - 2, y); - g.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2); - g.drawLine(x + 1, y + height - 1, x + width - 2, y + height - 1); - g.drawLine(x, y + 1, x, y + height - 2); - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java index 4bee7cfac9..df59a8d79e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java @@ -48,7 +48,7 @@ import ghidra.util.data.DataTypeParser.AllowedDataTypes; import ghidra.util.table.GhidraTable; import ghidra.util.task.SwingUpdateManager; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; +import resources.Icons; import util.CollectionUtils; //@formatter:off @@ -301,7 +301,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin { } }; addAction.setPopupMenuData(new MenuData(new String[] { "Add" })); - addAction.setToolBarData(new ToolBarData(ResourceManager.loadImage("images/Plus.png"))); + addAction.setToolBarData(new ToolBarData(Icons.ADD_ICON)); addAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_PLUS, 0)); addAction.setDescription("Add Datatypes"); @@ -316,8 +316,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin { } }; deleteAction.setPopupMenuData(new MenuData(new String[] { "Delete" })); - deleteAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/edit-delete.png"))); + deleteAction.setToolBarData(new ToolBarData(Icons.DELETE_ICON)); deleteAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0)); deleteAction.setDescription("Delete Selected Datatypes"); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/DataWindowProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/DataWindowProvider.java index 2569ea574d..c909a3934a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/DataWindowProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/DataWindowProvider.java @@ -23,6 +23,7 @@ import javax.swing.*; import javax.swing.table.JTableHeader; import docking.ActionContext; +import generic.theme.GIcon; import ghidra.app.services.GoToService; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.program.model.address.Address; @@ -30,14 +31,13 @@ import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; import ghidra.util.table.*; -import resources.ResourceManager; /** * Provider for the equates table. */ class DataWindowProvider extends ComponentProviderAdapter { - public static final ImageIcon ICON = ResourceManager.loadImage("images/dataW.gif"); + public static final Icon ICON = new GIcon("icon.plugin.datawindow.provider"); private DataWindowPlugin plugin; @@ -93,7 +93,9 @@ class DataWindowProvider extends ComponentProviderAdapter { } void programClosed() { - dataModel.reload(null); + if (isVisible()) { + dataModel.reload(null); + } } void dispose() { @@ -156,10 +158,14 @@ class DataWindowProvider extends ComponentProviderAdapter { } private void setDataTableRenderer() { - dataTable.getColumnModel().getColumn(DataTableModel.LOCATION_COL).setPreferredWidth( - DataTableModel.ADDRESS_COL_WIDTH); - dataTable.getColumnModel().getColumn(DataTableModel.SIZE_COL).setPreferredWidth( - DataTableModel.SIZE_COL_WIDTH); + dataTable.getColumnModel() + .getColumn(DataTableModel.LOCATION_COL) + .setPreferredWidth( + DataTableModel.ADDRESS_COL_WIDTH); + dataTable.getColumnModel() + .getColumn(DataTableModel.SIZE_COL) + .setPreferredWidth( + DataTableModel.SIZE_COL_WIDTH); } void reload() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/FilterAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/FilterAction.java index bbe236ccdb..64c2d52027 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/FilterAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datawindow/FilterAction.java @@ -34,6 +34,7 @@ import docking.widgets.combobox.GhidraComboBox; import docking.widgets.filter.FilterListener; import docking.widgets.filter.FilterTextField; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors; import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; import ghidra.util.task.SwingUpdateManager; @@ -133,8 +134,8 @@ class FilterAction extends ToggleDockingAction { } synchronized void selectTypes(ArrayList list) { - for (int i = 0; i < list.size(); i++) { - typeEnabledMap.put(list.get(i), Boolean.TRUE); + for (String element : list) { + typeEnabledMap.put(element, Boolean.TRUE); } if (dialog != null) { dialog.selectTypes(list); @@ -222,15 +223,13 @@ class FilterAction extends ToggleDockingAction { } void selectTypes(ArrayList list) { - for (int i = 0; i < list.size(); i++) { - String type = list.get(i); + for (String type : list) { selectCheckBox(type); } } private void selectCheckBox(String typeName) { - for (int i = 0; i < checkboxes.size(); i++) { - JCheckBox cb = checkboxes.get(i); + for (JCheckBox cb : checkboxes) { if (cb.getText().equals(typeName)) { cb.setSelected(true); return; @@ -302,7 +301,7 @@ class FilterAction extends ToggleDockingAction { typeButtonPanel.add(selectNoneButton); checkboxPanel = new JPanel(); - checkboxPanel.setBackground(Color.WHITE); + checkboxPanel.setBackground(Colors.BACKGROUND); checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.Y_AXIS)); buildCheckBoxList(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassembledViewPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassembledViewPlugin.java index 81eef78479..b8eaf1cd15 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassembledViewPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassembledViewPlugin.java @@ -24,6 +24,7 @@ import javax.swing.event.ChangeListener; import docking.WindowPosition; import docking.widgets.list.GListCellRenderer; +import generic.theme.Gui; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; @@ -449,8 +450,8 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec Color background = selectedAddressColor; if (isSelected) { - foreground = foreground.brighter(); - background = background.darker(); + foreground = Gui.brighter(foreground); + background = Gui.darker(background); } setForeground(foreground); @@ -490,7 +491,7 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec OptionsGui.BACKGROUND.getDefaultColor()); // font - font = opt.getFont(ADDRESS_FONT_OPTION, FieldFactory.DEFAULT_FIELD_FONT); + font = Gui.getFont(FieldFactory.BASE_LISTING_FONT_ID); contentList.setForeground(addressForegroundColor); contentList.setBackground(backgroundColor); @@ -509,22 +510,6 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec opt.removeOptionsChangeListener(optionsChangeListener); } - /** - * Adds the given listener to be notified when the user selects list - * items in the view. - * - * @param listener The listener to add. - */ -// void addListSelectionListener( ListSelectionListener listener ) -// { -// contentList.addListSelectionListener( listener ); -// } - - /** - * Sets the contents to the provided value. - * - * @param displayContents The value that the view should display. - */ void setContents(DisassembledAddressInfo[] addressInfos) { contentList.setListData(addressInfos); } @@ -595,7 +580,7 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec contentList.setBackground(backgroundColor); } else if (optionName.equals(ADDRESS_FONT_OPTION)) { - font = (Font) newValue; + font = Gui.getFont(FieldFactory.BASE_LISTING_FONT_ID); } } @@ -606,9 +591,8 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec } /** - * An object that provides information about the address that it wraps. - * The info knows how to locate a {@link CodeInfo} object for the address - * and can generate a string preview of the address. + * An object that provides information about the address that it wraps. The info knows how to + * locate an info object for the address and can generate a string preview of the address. */ private class DisassembledAddressInfo { /** @@ -683,8 +667,8 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec /** * Get the code unit from the program location. * - * @param The address from which we want the CodeUnit. - * @return CodeUnit null if there is no location. + * @param address the address from which we want the CodeUnit. + * @return null if there is no location. */ private CodeUnit getCodeUnitForAddress(Address address) { CodeUnit codeUnit = null; @@ -693,8 +677,8 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec Listing listing = currentProgram.getListing(); codeUnit = listing.getCodeUnitAt(address); - // if the CodeUnit is Data and is not defined, then we - // need to try to virutally disassemble it + // if the CodeUnit is Data and is not defined, then we need to try to virtually + // disassemble it if (codeUnit instanceof Data) { if (!((Data) codeUnit).isDefined()) { CodeUnit virtualCodeUnit = virtuallyDisassembleAddress(address); @@ -727,18 +711,15 @@ public class DisassembledViewPlugin extends ProgramPlugin implements DomainObjec codeUnit = disassembler.disassemble(address); } catch (UsrException ue) { - // these exceptions happen if there is insufficient data - // from the program: InsufficientBytesException, - // UnknownInstructionException, UnknownContextException + // these exceptions happen if there is insufficient data from the program: + // InsufficientBytesException, UnknownInstructionException, + // UnknownContextException } } return codeUnit; } - /** - * Gets the preview String for the provided code unit. - */ public String getAddressPreview(CodeUnitFormat format) { return getAddress().toString() + " " + format.getRepresentationString(addressCodeUnit); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/editor/TextEditorComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/editor/TextEditorComponentProvider.java index 39c204ae3e..28597cca52 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/editor/TextEditorComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/editor/TextEditorComponentProvider.java @@ -19,8 +19,6 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.event.KeyEvent; import java.io.*; -import java.util.Iterator; -import java.util.List; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -32,36 +30,21 @@ import docking.ActionContext; import docking.ComponentProvider; import docking.action.*; import docking.actions.KeyBindingUtils; -import docking.options.editor.FontPropertyEditor; +import docking.options.editor.FontEditor; import docking.widgets.OptionDialog; import docking.widgets.filechooser.GhidraFileChooser; -import ghidra.framework.options.SaveState; +import generic.theme.*; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.datastruct.FixedSizeStack; -import resources.ResourceManager; +import resources.Icons; public class TextEditorComponentProvider extends ComponentProviderAdapter { private static final String TITLE = "Text Editor"; - + private static final String FONT_ID = "font.plugin.service.text.editor"; private static final int MAX_UNDO_REDO_SIZE = 50; - static Font defaultFont = new Font("monospaced", Font.PLAIN, 12); - - static void restoreState(SaveState saveState) { - String name = saveState.getString("DEFAULT_FONT_NAME", "Monospaced"); - int style = saveState.getInt("DEFAULT_FONT_STYLE", Font.PLAIN); - int size = saveState.getInt("DEFAULT_FONT_SIZE", 12); - defaultFont = new Font(name, style, size); - } - - static void saveState(SaveState saveState) { - saveState.putString("DEFAULT_FONT_NAME", defaultFont.getName()); - saveState.putInt("DEFAULT_FONT_STYLE", defaultFont.getStyle()); - saveState.putInt("DEFAULT_FONT_SIZE", defaultFont.getSize()); - } - private TextEditorManagerPlugin plugin; private GhidraFileChooser chooser; private File textFile; @@ -200,7 +183,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { }; undoAction.setDescription("Undo"); undoAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/undo.png"), "UndoRedo")); + new ToolBarData(new GIcon("icon.undo"), "UndoRedo")); undoAction.setEnabled(false); plugin.getTool().addLocalAction(this, undoAction); @@ -218,7 +201,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { }; redoAction.setDescription("Redo"); redoAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/redo.png"), "UndoRedo")); + new ToolBarData(new GIcon("icon.redo"), "UndoRedo")); redoAction.setEnabled(false); plugin.getTool().addLocalAction(this, redoAction); @@ -236,7 +219,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { }; saveAction.setDescription("Save"); saveAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/disk.png"), "Save")); + new ToolBarData(Icons.SAVE_ICON, "Save")); saveAction.setEnabled(false); plugin.getTool().addLocalAction(this, saveAction); @@ -254,7 +237,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { }; saveAsAction.setDescription("Save As..."); saveAsAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/disk_save_as.png"), "Save")); + new ToolBarData(Icons.SAVE_AS_ICON, "Save")); saveAsAction.setEnabled(true); plugin.getTool().addLocalAction(this, saveAsAction); @@ -265,7 +248,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { } }; fontAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/text_lowercase.png"), "ZZFont")); + new ToolBarData(new GIcon("icon.font"), "ZZFont")); fontAction.setDescription("Select Font"); fontAction.setEnabled(true); plugin.getTool().addLocalAction(this, fontAction); @@ -287,17 +270,10 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { } protected void doSelectFont() { - FontPropertyEditor editor = new FontPropertyEditor(); - editor.setValue(defaultFont); + FontEditor editor = new FontEditor(); + editor.setValue(Gui.getFont(FONT_ID)); editor.showDialog(); - defaultFont = (Font) editor.getValue(); - - List values = plugin.getEditors(); - Iterator iterator = values.iterator(); - while (iterator.hasNext()) { - TextEditorComponentProvider editorComponent = iterator.next(); - editorComponent.textarea.setFont(defaultFont); - } + ThemeManager.getInstance().setFont(FONT_ID, (Font) editor.getValue()); } private void save() { @@ -390,8 +366,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter { private KeyMasterTextArea(String text) { super(text); - - setFont(defaultFont); + Gui.registerFont(this, FONT_ID); setName("EDITOR"); setWrapStyleWord(false); Document document = getDocument(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableModel.java index 7da1cab34f..95fc54972a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableModel.java @@ -4,9 +4,9 @@ * 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. @@ -21,8 +21,11 @@ import java.util.ArrayList; import java.util.List; import javax.swing.JLabel; +import javax.swing.JTable; import docking.widgets.table.*; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Tables; import ghidra.app.util.ToolTipUtils; import ghidra.docking.settings.FormatSettingsDefinition; import ghidra.docking.settings.Settings; @@ -40,6 +43,8 @@ import util.CollectionUtils; class EquateTableModel extends GDynamicColumnTableModel { + private static final Color FG_ENUM_BASED = new GColor("color.fg.plugin.equate.enum"); + private EquateTablePlugin plugin; private List equateList = new ArrayList<>(); @@ -149,10 +154,14 @@ class EquateTableModel extends GDynamicColumnTableModel { return label; } + JTable table = data.getTable(); if (!eq.isValidUUID()) { // Error equate - label.setForeground((isSelected) ? Color.WHITE : Color.RED); - } else if (!eq.isEnumBased()) { // User label - label.setForeground((isSelected) ? Color.WHITE : Color.BLUE.brighter()); + label.setForeground( + (isSelected) ? table.getSelectionForeground() : Tables.FG_ERROR_UNSELECTED); + } + else if (!eq.isEnumBased()) { // User label + label.setForeground( + (isSelected) ? table.getSelectionForeground() : FG_ENUM_BASED); } String tooltip = getEquateToolTip(eq); @@ -192,7 +201,7 @@ class EquateTableModel extends GDynamicColumnTableModel { @Override public String getValue(Equate rowObject, Settings settings, Object data, - ServiceProvider serviceProvider) throws IllegalArgumentException { + ServiceProvider sp) throws IllegalArgumentException { return rowObject.getDisplayName(); } @@ -243,7 +252,7 @@ class EquateTableModel extends GDynamicColumnTableModel { @Override public Long getValue(Equate rowObject, Settings settings, Object data, - ServiceProvider serviceProvider) throws IllegalArgumentException { + ServiceProvider sp) throws IllegalArgumentException { FormatSettingsDefinition formatDef = FormatSettingsDefinition.DEF; @@ -263,7 +272,7 @@ class EquateTableModel extends GDynamicColumnTableModel { } private class EquateReferenceCountColumn - extends AbstractDynamicTableColumn { + extends AbstractDynamicTableColumn { public static final String NAME = "# Refs"; @@ -274,14 +283,14 @@ class EquateTableModel extends GDynamicColumnTableModel { @Override public Integer getValue(Equate rowObject, Settings settings, Object data, - ServiceProvider serviceProvider) throws IllegalArgumentException { + ServiceProvider sp) throws IllegalArgumentException { return rowObject.getReferenceCount(); } } private class IsEnumBasedEquateColumn - extends AbstractDynamicTableColumn { + extends AbstractDynamicTableColumn { public static final String NAME = "Is Enum-Based"; @@ -292,7 +301,7 @@ class EquateTableModel extends GDynamicColumnTableModel { @Override public Boolean getValue(Equate rowObject, Settings settings, Object data, - ServiceProvider serviceProvider) throws IllegalArgumentException { + ServiceProvider sp) throws IllegalArgumentException { return rowObject.isEnumBased(); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java index 793a3bd759..56f30a71fe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java @@ -40,12 +40,10 @@ import ghidra.program.model.symbol.Equate; import ghidra.util.HelpLocation; import ghidra.util.UniversalID; import ghidra.util.table.*; -import resources.ResourceManager; +import resources.Icons; public class EquateTableProvider extends ComponentProviderAdapter { - private final static String DELETE_IMAGE = "images/edit-delete.png"; - private EquateTablePlugin plugin; private GhidraTable equatesTable; private EquateTableModel equatesModel; @@ -160,8 +158,8 @@ public class EquateTableProvider extends ComponentProviderAdapter { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN || - e.getKeyCode() == KeyEvent.VK_PAGE_UP || - e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) { + e.getKeyCode() == KeyEvent.VK_PAGE_UP || + e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) { handleEquateTableSelection(); } } @@ -191,7 +189,7 @@ public class EquateTableProvider extends ComponentProviderAdapter { Equate equate = (Equate) table.getValueAt(row, column); UniversalID id = - new UniversalID(Long.parseLong(equate.getName().split(":")[1])); + new UniversalID(Long.parseLong(equate.getName().split(":")[1])); Enum enoom = (Enum) dtm.findDataTypeForID(id); if (enoom != null) { dtms.edit(enoom); @@ -254,7 +252,7 @@ public class EquateTableProvider extends ComponentProviderAdapter { JPanel workPanel = new JPanel(new BorderLayout()); JSplitPane splitPane = - new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, equatesPanel, referencesPanel); + new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, equatesPanel, referencesPanel); splitPane.setResizeWeight(0.5); workPanel.add(splitPane, BorderLayout.CENTER); @@ -269,7 +267,7 @@ public class EquateTableProvider extends ComponentProviderAdapter { private void createAction() { - ImageIcon deleteImage = ResourceManager.loadImage(DELETE_IMAGE); + Icon deleteImage = Icons.DELETE_ICON; deleteAction = new DockingAction("Delete Equate", plugin.getName()) { @Override public void actionPerformed(ActionContext context) { @@ -291,7 +289,7 @@ public class EquateTableProvider extends ComponentProviderAdapter { deleteAction.setHelpLocation(new HelpLocation("EquatePlugin", "Delete Equate")); SelectionNavigationAction selectionNavigationAction = - new SelectionNavigationAction(plugin, referencesTable); + new SelectionNavigationAction(plugin, referencesTable); selectionNavigationAction.setHelpLocation( new HelpLocation(HelpTopics.SEARCH, "Selection_Navigation")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/fallthrough/FallThroughDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/fallthrough/FallThroughDialog.java index 74d62df7c1..3d58ff0476 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/fallthrough/FallThroughDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/fallthrough/FallThroughDialog.java @@ -16,9 +16,6 @@ package ghidra.app.plugin.core.fallthrough; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.net.URL; import javax.swing.*; import javax.swing.border.TitledBorder; @@ -28,17 +25,14 @@ import javax.swing.event.ChangeListener; import docking.DialogComponentProvider; import docking.widgets.button.GRadioButton; import docking.widgets.label.GDLabel; +import generic.theme.Gui; import ghidra.app.util.AddressInput; import ghidra.program.model.address.Address; import ghidra.util.HelpLocation; -import resources.ResourceManager; +import resources.Icons; /** - * Dialog to prompt for overriding a fallthrough address on an - * instruction. - * - * - * + * Dialog to prompt for overriding a fallthrough address on an instruction. */ class FallThroughDialog extends DialogComponentProvider implements ChangeListener { @@ -65,25 +59,16 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene model.setChangeListener(this); } - /** - * @see ghidra.util.bean.GhidraDialog#applyCallback() - */ @Override protected void applyCallback() { model.execute(); } - /** - * @see ghidra.util.bean.GhidraDialog#cancelCallback() - */ @Override protected void cancelCallback() { close(); } - /** - * @see ghidra.util.bean.GhidraDialog#okCallback() - */ @Override protected void okCallback() { if (model.execute()) { @@ -91,9 +76,6 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene } } - /** - * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) - */ public void updateState() { Address addr = model.getAddress(); if (addr == null) { @@ -140,18 +122,15 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene return; } - Runnable r = new Runnable() { - @Override - public void run() { - Address addr = addrField.getAddress(); - if (addr != null || addrField.getValue().length() == 0) { - model.setCurrentFallthrough(addr); - } - else { - setStatusText("Invalid Address"); - setOkEnabled(false); - setApplyEnabled(false); - } + Runnable r = () -> { + Address addr = addrField.getAddress(); + if (addr != null || addrField.getValue().length() == 0) { + model.setCurrentFallthrough(addr); + } + else { + setStatusText("Invalid Address"); + setOkEnabled(false); + setApplyEnabled(false); } }; SwingUtilities.invokeLater(r); @@ -162,18 +141,8 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); addrField = new AddressInput(); addrField.setAddressFactory(model.getProgram().getAddressFactory()); - addrField.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - addressChanged(); - } - }); - addrField.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - model.setCurrentFallthrough(addrField.getAddress()); - } - }); + addrField.addChangeListener(e -> addressChanged()); + addrField.addActionListener(e -> model.setCurrentFallthrough(addrField.getAddress())); panel.add(createHomePanel(), BorderLayout.NORTH); panel.add(createAddressPanel(), BorderLayout.CENTER); return panel; @@ -194,20 +163,14 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene addressLabel = new GDLabel("01001000"); - Font font = addressLabel.getFont(); - Font monoFont = new Font("monospaced", font.getStyle(), font.getSize()); + Font monoFont = Gui.getFont("font.monospaced"); addressLabel.setFont(monoFont); instLabel = new GDLabel("jmp DAT_01001000"); instLabel.setFont(monoFont); - homeButton = createButton("images/go-home.png", "Home"); - homeButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - plugin.goTo(model.getAddress()); - } - }); + homeButton = createButton("Home"); + homeButton.addActionListener(e -> plugin.goTo(model.getAddress())); JPanel innerPanel = new JPanel(); BoxLayout bl = new BoxLayout(innerPanel, BoxLayout.X_AXIS); @@ -232,21 +195,11 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene ButtonGroup group = new ButtonGroup(); defaultRB = new GRadioButton("Default", true); - defaultRB.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ev) { - model.defaultSelected(); - } - }); + defaultRB.addActionListener(ev -> model.defaultSelected()); defaultRB.setToolTipText("Use default fallthrough address"); userRB = new GRadioButton("User", false); - userRB.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ev) { - model.userSelected(); - } - }); + userRB.addActionListener(ev -> model.userSelected()); userRB.setToolTipText("Override default fallthrough address"); group.add(defaultRB); @@ -260,18 +213,13 @@ class FallThroughDialog extends DialogComponentProvider implements ChangeListene return outerPanel; } - private JButton createButton(String filename, String altText) { + private JButton createButton(String altText) { JButton button = new JButton(); - URL imageURL = ResourceManager.getResource(filename); - if (imageURL != null) { - ImageIcon icon = new ImageIcon(imageURL); - button = new JButton(icon); - Insets noInsets = new Insets(0, 0, 0, 0); - button.setMargin(noInsets); - } - else { - button = new JButton(altText); - } + Icon icon = Icons.HOME_ICON; + button = new JButton(icon); + Insets noInsets = new Insets(0, 0, 0, 0); + button.setMargin(noInsets); + button.setToolTipText("Go back to home address"); return button; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java index 4a87ad48e8..e99c3ddf73 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java @@ -642,14 +642,14 @@ public class FlowArrowPlugin extends Plugin implements MarginProvider, OptionsCh private void getOptions() { ToolOptions opt = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY); - opt.registerOption(OptionsGui.FLOW_ARROW_NON_ACTIVE.getColorOptionName(), - OptionsGui.FLOW_ARROW_NON_ACTIVE.getDefaultColor(), null, + opt.registerThemeColorBinding(OptionsGui.FLOW_ARROW_NON_ACTIVE.getColorOptionName(), + OptionsGui.FLOW_ARROW_NON_ACTIVE.getThemeColorId(), null, "The color for an arrow with no endpoint at the current address"); - opt.registerOption(OptionsGui.FLOW_ARROW_ACTIVE.getColorOptionName(), - OptionsGui.FLOW_ARROW_ACTIVE.getDefaultColor(), null, + opt.registerThemeColorBinding(OptionsGui.FLOW_ARROW_ACTIVE.getColorOptionName(), + OptionsGui.FLOW_ARROW_ACTIVE.getThemeColorId(), null, "The color for an arrow with an endpoint at the current address"); - opt.registerOption(OptionsGui.FLOW_ARROW_SELECTED.getColorOptionName(), - OptionsGui.FLOW_ARROW_SELECTED.getDefaultColor(), null, + opt.registerThemeColorBinding(OptionsGui.FLOW_ARROW_SELECTED.getColorOptionName(), + OptionsGui.FLOW_ARROW_SELECTED.getThemeColorId(), null, "The color for an arrow that has been selected by the user"); Color c = opt.getColor(OptionsGui.BACKGROUND.getColorOptionName(), diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java index a55b564afd..05d80a593b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/StackDepthFieldFactory.java @@ -15,11 +15,12 @@ */ package ghidra.app.plugin.core.function; -import java.awt.Color; import java.math.BigInteger; import docking.widgets.fieldpanel.field.*; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.cmd.function.CallDepthChangeInfo; import ghidra.app.util.HighlightProvider; import ghidra.app.util.viewer.field.*; @@ -39,12 +40,8 @@ public class StackDepthFieldFactory extends FieldFactory { private CallDepthChangeInfo depth = null; private long lastModNumber = -1; - /** - * - */ public StackDepthFieldFactory() { super(FIELD_NAME); - // TODO Auto-generated constructor stub } private StackDepthFieldFactory(FieldFormatModel model, HighlightProvider hsProvider, @@ -57,14 +54,11 @@ public class StackDepthFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel newModel, HighlightProvider highlightProvider, - ToolOptions displayOptions, ToolOptions fieldOptions) { - return new StackDepthFieldFactory(newModel, highlightProvider, displayOptions, + ToolOptions toolDisplayOptions, ToolOptions fieldOptions) { + return new StackDepthFieldFactory(newModel, highlightProvider, toolDisplayOptions, fieldOptions); } - /** - * @see ghidra.app.util.viewer.field.FieldFactory#getField(ProxyObj, int) - */ @Override public ListingField getField(ProxyObj> proxy, int varWidth) { Object obj = proxy.getObject(); @@ -94,14 +88,14 @@ public class StackDepthFieldFactory extends FieldFactory { // This can be used to display the value of any register symbolically flowing over the program. // depthString = depth.getRegValueRepresentation(cu.getMinAddress(), cu.getProgram().getRegister("ESP")); - AttributedString as = new AttributedString(depthString, Color.BLUE, getMetrics()); + AttributedString as = new AttributedString(depthString, Palette.BLUE, getMetrics()); Integer overrideDepth = CallDepthChangeInfo.getStackDepthChange(cu.getProgram(), cu.getMinAddress()); if (overrideDepth != null) { String grows = (func.getStackFrame().growsNegative() ? " - " : " + "); depthString = depthString + grows + Integer.toString(overrideDepth, 16); - as = new AttributedString(depthString, Color.RED, getMetrics()); + as = new AttributedString(depthString, Colors.ERROR, getMetrics()); } FieldElement text = new TextFieldElement(as, 0, 0); @@ -109,15 +103,11 @@ public class StackDepthFieldFactory extends FieldFactory { width, hlProvider); } - /** - * @param depthChange - * @return - */ private String getDepthString(int depthChange, boolean isInDelaySlot) { if (isInDelaySlot) { - return ""; // if in delayslot, stack changes will be on main instruction + return ""; // if in delay slot, stack changes will be on main instruction } - + String stringDepth = "- ? -"; if (depthChange != Function.UNKNOWN_STACK_DEPTH_CHANGE && @@ -134,7 +124,7 @@ public class StackDepthFieldFactory extends FieldFactory { stringDepth = filler.substring(len) + stringDepth; } } - + return stringDepth; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java index 79e622a132..1f70f889e4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java @@ -35,6 +35,10 @@ import docking.widgets.checkbox.GCheckBox; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GLabel; import docking.widgets.table.*; +import generic.theme.GColor; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.*; import generic.util.WindowUtilities; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.ToolTipUtils; @@ -47,13 +51,12 @@ import ghidra.program.model.symbol.ExternalLocation; import ghidra.util.*; import ghidra.util.layout.PairLayout; import ghidra.util.layout.VerticalLayout; -import resources.ResourceManager; +import resources.Icons; public class FunctionEditorDialog extends DialogComponentProvider implements ModelChangeListener { - private static Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private static Icon REMOVE_ICON = ResourceManager.loadImage("images/edit-delete.png"); - private static Icon UP_ICON = ResourceManager.loadImage("images/up.png"); - private static Icon DOWN_ICON = ResourceManager.loadImage("images/down.png"); + private static final Color FG_COLOR_THUNK = + new GColor("color.fg.plugin.function.editor.dialog.thunk"); + private FunctionEditorModel model; private DocumentListener nameFieldDocumentListener; private GTable parameterTable; @@ -209,10 +212,10 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod thunkedText.setEditable(false); DockingUtils.setTransparent(thunkedText); CompoundBorder border = - BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.GRAY), + BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Java.BORDER), BorderFactory.createEmptyBorder(0, 5, 0, 5)); thunkedText.setBorder(border); - thunkedText.setForeground(Color.BLUE); + thunkedText.setForeground(FG_COLOR_THUNK); thunkedPanel.add(thunkedText); return thunkedPanel; } @@ -224,9 +227,9 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod scroll = new JScrollPane(verticalScrollPanel); scroll.setBorder(null); scroll.setOpaque(true); - scroll.setBackground(Color.WHITE); - scroll.getViewport().setBackground(new Color(0, 0, 0, 0)); // transparent - scroll.getViewport().setBackground(Color.WHITE); + scroll.setBackground(Colors.BACKGROUND); + scroll.getViewport().setBackground(Palette.NO_COLOR); // transparent + scroll.getViewport().setBackground(Colors.BACKGROUND); previewPanel.add(scroll, BorderLayout.CENTER); previewPanel.setBorder(BorderFactory.createLoweredBevelBorder()); scroll.getViewport().addMouseListener(new MouseAdapter() { @@ -440,10 +443,10 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod private Component buildButtonPanel() { JPanel panel = new JPanel(new VerticalLayout(5)); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - addButton = new JButton(ADD_ICON); - removeButton = new JButton(REMOVE_ICON); - upButton = new JButton(UP_ICON); - downButton = new JButton(DOWN_ICON); + addButton = new JButton(Icons.ADD_ICON); + removeButton = new JButton(Icons.DELETE_ICON); + upButton = new JButton(new GIcon("icon.up")); + downButton = new JButton(new GIcon("icon.down")); addButton.setToolTipText("Add parameter"); removeButton.setToolTipText("Delete selected parameters"); upButton.setToolTipText("Move selected parameter up"); @@ -657,12 +660,13 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod DataType dataType = (DataType) value; Color color = isSelected ? table.getSelectionForeground() : table.getForeground(); if (!tableModel.isCellEditable(row, column)) { - color = isSelected ? Color.yellow : Color.gray; + color = + isSelected ? Tables.FG_UNEDITABLE_SELECTED : Tables.FG_UNEDITABLE_UNSELECTED; } if (dataType != null) { setText(dataType.getName()); if (dataType.isNotYetDefined()) { - color = Color.red; + color = isSelected ? Tables.FG_ERROR_SELECTED : Tables.FG_ERROR_UNSELECTED; } String toolTipText = ToolTipUtils.getToolTipText(dataType); String headerText = "" + @@ -751,17 +755,20 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod boolean isInvalidStorage = !storage.isValid() || rowData.getFormalDataType().getLength() != storage.size(); if (isInvalidStorage) { - setForeground(Color.RED); + setForeground( + isSelected ? Tables.FG_ERROR_SELECTED : Tables.FG_ERROR_UNSELECTED); setToolTipText("Invalid Parameter Storage"); } else { - setForeground(isSelected ? Color.WHITE : Color.BLACK); + setForeground( + isSelected ? table.getSelectionForeground() : Colors.FOREGROUND); setToolTipText(""); } setText(storage.toString()); } else { - setForeground(isSelected ? Color.WHITE : Color.BLACK); + setForeground( + isSelected ? table.getSelectionForeground() : Colors.FOREGROUND); setText(""); setToolTipText(null); } @@ -770,6 +777,7 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod } private class VariableStringCellRenderer extends GTableCellRenderer { + @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { @@ -785,7 +793,8 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod ParameterTableModel tableModel = (ParameterTableModel) table.getModel(); if (!tableModel.isCellEditable(row, column)) { - setForeground(isSelected ? Color.yellow : Color.gray); + setForeground( + isSelected ? Tables.FG_UNEDITABLE_SELECTED : Tables.FG_UNEDITABLE_UNSELECTED); } else { if (isSelected) { @@ -853,7 +862,7 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod Composite originalComposite = g2d.getComposite(); g2d.setComposite(alphaComposite); - g.setColor(Color.white); + g.setColor(Colors.BACKGROUND); g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); g2d.setComposite(originalComposite); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java index d42c139764..2d256a9eda 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java @@ -15,9 +15,6 @@ */ package ghidra.app.plugin.core.function.editor; -import static java.awt.Color.blue; -import static java.awt.Color.red; - import java.awt.*; import java.awt.event.*; import java.util.ArrayList; @@ -28,16 +25,21 @@ import javax.swing.event.*; import javax.swing.text.*; import docking.actions.KeyBindingUtils; +import generic.theme.GColor; import ghidra.util.Swing; class FunctionSignatureTextField extends JTextPane { private static final String ENTER_ACTION_NAME = "ENTER"; private static final String ESCAPE_ACTION_NAME = "ESCAPE"; private static final String TAB_ACTION_NAME = "TAB"; - public static Color DEFAULT_COLOR = Color.black; - public static Color PARAMETER_NAME_COLOR = new Color(155, 50, 155); - public static Color FUNCTION_NAME_COLOR = blue; - public static Color ERROR_NAME_COLOR = red; + public static Color DEFAULT_COLOR = + new GColor("color.fg.plugin.function.editor.dialog.textfield.default"); + public static Color PARAMETER_NAME_COLOR = + new GColor("color.fg.plugin.function.editor.dialog.textfield.parameter"); + public static Color FUNCTION_NAME_COLOR = + new GColor("color.fg.plugin.function.editor.dialog.textfield.function.name"); + public static Color ERROR_NAME_COLOR = + new GColor("color.fg.plugin.function.editor.dialog.textfield.error"); private StyledDocument doc; private SimpleAttributeSet paramNameAttributes; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/StorageTableCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/StorageTableCellEditor.java index 7f3d19138c..cd89ebe0fe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/StorageTableCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/StorageTableCellEditor.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.Color; import java.awt.Component; import java.awt.event.MouseEvent; import java.util.EventObject; @@ -24,6 +23,7 @@ import javax.swing.*; import javax.swing.table.TableCellEditor; import docking.DockingWindowManager; +import generic.theme.GThemeDefaults.Colors.Tables; import ghidra.program.model.listing.VariableStorage; class StorageTableCellEditor extends AbstractCellEditor implements TableCellEditor { @@ -53,30 +53,27 @@ class StorageTableCellEditor extends AbstractCellEditor implements TableCellEdit boolean isSelected, int row, int column) { String stringValue = value == null ? "" : value.toString(); JTextField field = new JTextField(stringValue); - field.setBackground(Color.yellow); + field.setBackground( + isSelected ? Tables.FG_UNEDITABLE_SELECTED : Tables.FG_UNEDITABLE_UNSELECTED); field.setEditable(false); ParameterTableModel tableModel = (ParameterTableModel) table.getModel(); FunctionVariableData rowData = tableModel.getRowObject(row); final StorageAddressEditorDialog dialog = new StorageAddressEditorDialog(model.getProgram(), model.getDataTypeManagerService(), (VariableStorage) value, rowData); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - DockingWindowManager.showDialog(table, dialog); - if (!dialog.wasCancelled()) { - storage = dialog.getStorage(); - } - TableCellEditor cellEditor = table.getCellEditor(); - if (cellEditor == null) { - return; - } - if (storage == null) { - cellEditor.cancelCellEditing(); - } - else { - cellEditor.stopCellEditing(); - } + SwingUtilities.invokeLater(() -> { + DockingWindowManager.showDialog(table, dialog); + if (!dialog.wasCancelled()) { + storage = dialog.getStorage(); + } + TableCellEditor cellEditor = table.getCellEditor(); + if (cellEditor == null) { + return; + } + if (storage == null) { + cellEditor.cancelCellEditing(); + } + else { + cellEditor.stopCellEditing(); } }); return field; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java index 293f5f88f4..a93be40e57 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.Color; import java.awt.Component; import java.awt.event.*; import java.math.BigInteger; @@ -28,6 +27,7 @@ import javax.swing.table.TableCellEditor; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.textfield.IntegerTextField; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.AddressInput; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressOutOfBoundsException; @@ -44,12 +44,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE private AddressInput addressInput; private IntegerTextField offsetInput; - private Comparator registerWrapperComparator = new Comparator () { - @Override - public int compare(Register r1, Register r2) { - return r1.toString().compareToIgnoreCase(r2.toString()); - } - }; + private Comparator registerWrapperComparator = (r1, r2) -> r1.toString().compareToIgnoreCase(r2.toString()); private VarnodeInfo currentVarnode; private int maxRegisterSize; @@ -146,12 +141,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE if (address != null) { addressInput.setAddress(address); } - addressInput.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + addressInput.addActionListener(e -> stopCellEditing()); return addressInput; } @@ -162,14 +152,9 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE if (address != null) { offsetInput.setValue(address.getOffset()); } - offsetInput.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + offsetInput.addActionListener(e -> stopCellEditing()); JComponent component = offsetInput.getComponent(); - component.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); + component.setBorder(BorderFactory.createLineBorder(Palette.GRAY, 1)); return component; } @@ -215,12 +200,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE } }); - combo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + combo.addActionListener(e -> stopCellEditing()); return combo; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java index 0d6dabeaba..cf52210291 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.Color; import java.awt.Component; import java.awt.event.*; import java.math.BigInteger; @@ -25,6 +24,7 @@ import javax.swing.*; import javax.swing.table.TableCellEditor; import docking.widgets.textfield.IntegerTextField; +import generic.theme.GThemeDefaults.Colors.Palette; class VarnodeSizeCellEditor extends AbstractCellEditor implements TableCellEditor { @@ -70,14 +70,9 @@ class VarnodeSizeCellEditor extends AbstractCellEditor implements TableCellEdito }; input.getComponent().addFocusListener(focusListener); } - input.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + input.addActionListener(e -> stopCellEditing()); JComponent component = input.getComponent(); - component.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); + component.setBorder(BorderFactory.createLineBorder(Palette.GRAY, 1)); return component; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagButtonPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagButtonPanel.java index a0e17897cc..fae3c7d2c7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagButtonPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagButtonPanel.java @@ -20,8 +20,8 @@ import java.awt.event.ActionListener; import javax.swing.*; +import generic.theme.GIcon; import resources.Icons; -import resources.ResourceManager; /** * Provides buttons to be used with the {@link FunctionTagProvider}. @@ -35,9 +35,6 @@ import resources.ResourceManager; */ public class FunctionTagButtonPanel extends JPanel { - private Icon ADD_IMG = ResourceManager.loadImage("images/2rightarrow.png"); - private Icon REMOVE_IMG = ResourceManager.loadImage("images/2leftarrow.png"); - private SourceTagsPanel sourcePanel; private TargetTagsPanel targetPanel; private JButton addBtn; @@ -101,25 +98,24 @@ public class FunctionTagButtonPanel extends JPanel { deleteBtn.setEnabled(hasSelection && !isImmutable); } - /****************************************************************************** - * PRIVATE METHODS - ******************************************************************************/ - private void createButtonPanel() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; - addBtn = createButton("addBtn", ADD_IMG, "Add selected tags to the function", + addBtn = createButton("addBtn", new GIcon("icon.plugin.functiontags.add"), + "Add selected tags to the function", e -> { sourcePanel.addSelectedTags(); }); add(addBtn, gbc); gbc.gridy = 1; - removeBtn = createButton("removeBtn", REMOVE_IMG, "Remove selected tags from the function", - e -> targetPanel.removeSelectedTags()); + removeBtn = + createButton("removeBtn", new GIcon("icon.plugin.functiontags.remove"), + "Remove selected tags from the function", + e -> targetPanel.removeSelectedTags()); add(removeBtn, gbc); gbc.gridy = 2; @@ -147,7 +143,6 @@ public class FunctionTagButtonPanel extends JPanel { JButton button = new JButton(name); button.setName(name); button.setToolTipText(tooltip); - icon = ResourceManager.getScaledIcon(icon, 16, 16); button.setIcon(icon); button.setText(""); button.addActionListener(action); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagProvider.java index 943268563b..7c5ed34091 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/tags/FunctionTagProvider.java @@ -15,9 +15,9 @@ */ package ghidra.app.plugin.core.function.tags; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.util.*; -import java.util.List; import javax.swing.*; import javax.swing.border.BevelBorder; @@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils; import docking.widgets.label.GLabel; import docking.widgets.textfield.HintTextField; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.app.cmd.function.CreateFunctionTagCmd; import ghidra.app.context.ProgramActionContext; import ghidra.framework.cmd.Command; @@ -58,8 +59,6 @@ import resources.ResourceManager; public class FunctionTagProvider extends ComponentProviderAdapter implements DomainObjectListener { - private Color BORDER_COLOR = Color.GRAY; - private SourceTagsPanel sourcePanel; private TargetTagsPanel targetPanel; private FunctionTagButtonPanel buttonPanel; @@ -240,9 +239,9 @@ public class FunctionTagProvider extends ComponentProviderAdapter targetPanel = new TargetTagsPanel(this, tool, "Assigned To Function"); allFunctionsPanel = new AllFunctionsPanel(program, this, "Functions with Selected Tag"); buttonPanel = new FunctionTagButtonPanel(sourcePanel, targetPanel); - sourcePanel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); - targetPanel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); - allFunctionsPanel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + sourcePanel.setBorder(BorderFactory.createLineBorder(Java.BORDER)); + targetPanel.setBorder(BorderFactory.createLineBorder(Java.BORDER)); + allFunctionsPanel.setBorder(BorderFactory.createLineBorder(Java.BORDER)); // If we don't set this, then the splitter won't be able to shrink the // target panels below the size required by its header, which can be large diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonPanel.java index 8ca6920578..5dd2e8cc3e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonPanel.java @@ -31,6 +31,7 @@ import docking.ComponentProvider; import docking.action.*; import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import docking.widgets.tabbedpane.DockingTabRenderer; +import generic.theme.GIcon; import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel; import ghidra.app.util.viewer.util.CodeComparisonPanel; import ghidra.framework.options.SaveState; @@ -44,7 +45,6 @@ import ghidra.util.Msg; import ghidra.util.classfinder.ClassSearcher; import help.Help; import help.HelpService; -import resources.ResourceManager; /** * A panel for displaying {@link Function functions}, {@link Data data}, or @@ -66,9 +66,10 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener { private static final HelpService help = Help.getHelpService(); private static final String HELP_TOPIC = "FunctionComparison"; - private static final Icon SYNC_SCROLLING_ICON = ResourceManager.loadImage("images/lock.gif"); + private static final Icon SYNC_SCROLLING_ICON = + new GIcon("icon.plugin.functioncompare.scroll.lock"); private static final Icon UNSYNC_SCROLLING_ICON = - ResourceManager.loadImage("images/unlock.gif"); + new GIcon("icon.plugin.functioncompare.scroll.unlock"); private static final String SCROLLING_GROUP = "A9_SCROLLING"; private static final String DUAL_SCROLLING_ACTION_GROUP = "DualScrolling"; private static final String DUAL_SCROLLING_HELP_TOPIC = "FunctionComparison"; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/CompareFunctionsAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/CompareFunctionsAction.java index 3bab2121d1..79063dce92 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/CompareFunctionsAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/CompareFunctionsAction.java @@ -19,18 +19,14 @@ import java.awt.event.InputEvent; import java.util.Set; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.app.services.FunctionComparisonService; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.listing.Function; import ghidra.util.HelpLocation; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.ScaledImageIcon; -import resources.icons.TranslateIcon; /** * Creates a new comparison between a set of functions, launching a new @@ -45,13 +41,7 @@ public abstract class CompareFunctionsAction extends DockingAction { protected FunctionComparisonService comparisonService; - private static final ImageIcon COMPARISON_ICON = - ResourceManager.loadImage("images/page_white_c.png"); - private static final Icon NEW_ICON = ResourceManager.loadImage("images/bullet_star.png"); - private static final Icon SCALED_NEW_ICON = new ScaledImageIcon(NEW_ICON, 16, 16); - private static final Icon TRANSLATED_NEW_ICON = new TranslateIcon(SCALED_NEW_ICON, 4, -4); - private static final Icon CREATE_NEW_COMPARISON_ICON = - new MultiIcon(COMPARISON_ICON, TRANSLATED_NEW_ICON); + private static final Icon COMPARISON_ICON = new GIcon("icon.plugin.functioncompare.new"); private static final String CREATE_COMPARISON_GROUP = "A9_CreateComparison"; static final String POPUP_MENU_NAME = "Compare Selected Functions"; @@ -85,7 +75,7 @@ public abstract class CompareFunctionsAction extends DockingAction { * @return the icon */ protected Icon getToolBarIcon() { - return CREATE_NEW_COMPARISON_ICON; + return COMPARISON_ICON; } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NavigateToFunctionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NavigateToFunctionAction.java index ad6b0b4491..6b2b3168d0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NavigateToFunctionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NavigateToFunctionAction.java @@ -18,7 +18,7 @@ package ghidra.app.plugin.core.functioncompare.actions; import java.awt.event.*; import java.util.List; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.action.ToggleDockingAction; import docking.action.ToolBarData; @@ -48,7 +48,7 @@ public class NavigateToFunctionAction extends ToggleDockingAction { private GoToService goToService; - private static final ImageIcon NAV_FUNCTION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON; + private static final Icon NAV_FUNCTION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON; /** * Constructor @@ -64,10 +64,9 @@ public class NavigateToFunctionAction extends ToggleDockingAction { setSelected(false); ToolBarData newToolBarData = new ToolBarData(NAV_FUNCTION_ICON); setToolBarData(newToolBarData); - setDescription( - HTMLUtilities.toHTML("Toggle On means to navigate to whatever " + - "function is selected in the comparison panel, when focus changes or" + - "a new function is selected.")); + setDescription(HTMLUtilities.toHTML("Toggle On means to navigate to whatever " + + "function is selected in the comparison panel, when focus changes or" + + "a new function is selected.")); setHelpLocation( new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC, "Navigate_To_Function")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NextFunctionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NextFunctionAction.java index 2c7afcbe4d..915724a1ec 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NextFunctionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/NextFunctionAction.java @@ -24,13 +24,11 @@ import javax.swing.JComboBox; import docking.ActionContext; import docking.ComponentProvider; import docking.action.*; +import generic.theme.GIcon; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonPanel; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonProvider; import ghidra.program.model.listing.Function; import ghidra.util.HelpLocation; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.TranslateIcon; /** * Displays the next available function in the function comparison panel. If @@ -39,11 +37,8 @@ import resources.icons.TranslateIcon; public class NextFunctionAction extends DockingAction { private static final String FUNCTION_NAVIGATE_GROUP = "A9_FunctionNavigate"; - private static final Icon NEXT_ICON = - new TranslateIcon(ResourceManager.loadImage("images/arrow_down.png"), 3, 1); - private static final Icon FUNCTION_ICON = - new TranslateIcon(ResourceManager.loadImage("images/FunctionScope.gif"), -5, -2); - private static final Icon NEXT_FUNCTION_ICON = new MultiIcon(NEXT_ICON, FUNCTION_ICON); + private static final Icon NEXT_FUNCTION_ICON = + new GIcon("icon.plugin.functioncompare.function.next"); /** * Constructor diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java index b4f3e5cffa..77f42d7063 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java @@ -20,11 +20,11 @@ import java.util.*; import java.util.stream.Collectors; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.ActionContext; import docking.action.*; import docking.widgets.dialogs.TableSelectionDialog; +import generic.theme.GIcon; import ghidra.app.plugin.core.functioncompare.FunctionComparisonProvider; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonPanel; import ghidra.app.plugin.core.functionwindow.FunctionRowObject; @@ -35,10 +35,6 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.ScaledImageIcon; -import resources.icons.TranslateIcon; import util.CollectionUtils; /** @@ -49,14 +45,9 @@ import util.CollectionUtils; */ public class OpenFunctionTableAction extends DockingAction { - private static final Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private static final Icon SCALED_ADD_ICON = new ScaledImageIcon(ADD_ICON, 10, 10); - private static final ImageIcon COMPARISON_ICON = - ResourceManager.loadImage("images/page_white_c.png"); - private static final Icon TRANSLATED_ADD_ICON = new TranslateIcon(SCALED_ADD_ICON, 8, 1); private static final String ADD_COMPARISON_GROUP = "A9_AddToComparison"; private static final Icon ADD_TO_COMPARISON_ICON = - new MultiIcon(COMPARISON_ICON, TRANSLATED_ADD_ICON); + new GIcon("icon.plugin.functioncompare.open.function.table"); protected PluginTool tool; protected ProgramManager programManagerService; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/PreviousFunctionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/PreviousFunctionAction.java index 01be55d06e..ece250013a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/PreviousFunctionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/PreviousFunctionAction.java @@ -24,13 +24,11 @@ import javax.swing.JComboBox; import docking.ActionContext; import docking.ComponentProvider; import docking.action.*; +import generic.theme.GIcon; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonPanel; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonProvider; import ghidra.program.model.listing.Function; import ghidra.util.HelpLocation; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.TranslateIcon; /** * Displays the previous function in the function comparison panel. If @@ -39,11 +37,8 @@ import resources.icons.TranslateIcon; public class PreviousFunctionAction extends DockingAction { private static final String FUNCTION_NAVIGATE_GROUP = "A9_FunctionNavigate"; - private static final Icon PREVIOUS_ICON = - new TranslateIcon(ResourceManager.loadImage("images/arrow_up.png"), 3, 1); - private static final Icon FUNCTION_ICON = - new TranslateIcon(ResourceManager.loadImage("images/FunctionScope.gif"), -5, -2); - private static final Icon PREVIOUS_FUNCTION_ICON = new MultiIcon(PREVIOUS_ICON, FUNCTION_ICON); + private static final Icon PREVIOUS_FUNCTION_ICON = + new GIcon("icon.plugin.functioncompare.function.previous"); /** * Constructor diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/RemoveFunctionsAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/RemoveFunctionsAction.java index f1cead3ba8..cf390a5fef 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/RemoveFunctionsAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/RemoveFunctionsAction.java @@ -25,13 +25,11 @@ import javax.swing.JComboBox; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonPanel; import ghidra.app.plugin.core.functioncompare.MultiFunctionComparisonProvider; import ghidra.program.model.listing.Function; import ghidra.util.HelpLocation; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.TranslateIcon; /** * Removes the currently-selected function from the comparison panel. If no @@ -39,12 +37,9 @@ import resources.icons.TranslateIcon; */ public class RemoveFunctionsAction extends DockingAction { - private static final Icon FUNCTION_ICON = - new TranslateIcon(ResourceManager.loadImage("images/FunctionScope.gif"), -5, -2); - private static final Icon REMOVE_ICON = - new TranslateIcon(ResourceManager.loadImage("images/edit-delete.png"), 3, 3); private static final String REMOVE_FUNCTION_GROUP = "A9_RemoveFunctions"; - private static final Icon REMOVE_FUNCTION_ICON = new MultiIcon(REMOVE_ICON, FUNCTION_ICON); + private static final Icon REMOVE_FUNCTION_ICON = + new GIcon("icon.plugin.functioncompare.function.remove"); /** * Constructor diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java index 274d48bc47..67395fa17f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java @@ -25,6 +25,7 @@ import javax.swing.*; import javax.swing.table.*; import docking.ActionContext; +import generic.theme.GIcon; import ghidra.app.services.GoToService; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.program.model.address.Address; @@ -32,14 +33,13 @@ import ghidra.program.model.listing.*; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; import ghidra.util.table.*; -import resources.ResourceManager; /** * Provider that displays all functions in the selected program */ public class FunctionWindowProvider extends ComponentProviderAdapter { - public static final ImageIcon icon = ResourceManager.loadImage("images/functions.gif"); + public static final Icon ICON = new GIcon("icon.plugin.functionwindow.provider"); private FunctionWindowPlugin plugin; private GhidraTable functionTable; @@ -58,7 +58,7 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { super(plugin.getTool(), "Functions Window", plugin.getName()); setTitle("Functions"); this.plugin = plugin; - setIcon(icon); + setIcon(ICON); setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName())); tool = plugin.getTool(); mainPanel = createWorkPanel(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractReferenceHover.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractReferenceHover.java index c69538acc8..a7b641bd93 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractReferenceHover.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractReferenceHover.java @@ -24,6 +24,8 @@ import javax.swing.JToolTip; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.gotoquery.GoToHelper; import ghidra.app.services.CodeFormatService; import ghidra.app.util.*; @@ -44,7 +46,8 @@ import ghidra.util.bean.opteditor.OptionsVetoException; public abstract class AbstractReferenceHover extends AbstractConfigurableHover { private static final int WINDOW_OFFSET = 50; - private static final Color BACKGROUND_COLOR = new Color(255, 255, 230); + private static final Color BACKGROUND_COLOR = Colors.BACKGROUND_TOOLTIP; + private static final Color FG_COLOR_NOT_IN_MEMORY = new GColor("color.fg.hint"); private CodeFormatService codeFormatService; private ListingPanel panel; @@ -283,7 +286,7 @@ public abstract class AbstractReferenceHover extends AbstractConfigurableHover { String message = "Address not in memory"; message = HTMLUtilities.italic(message); - message = HTMLUtilities.colorString(Color.GRAY, message); + message = HTMLUtilities.colorString(FG_COLOR_NOT_IN_MEMORY, message); buffy.append(message); toolTip.setTipText(buffy.toString()); return toolTip; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java index aa6f1c81f9..123bd91d8e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java @@ -15,13 +15,13 @@ */ package ghidra.app.plugin.core.instructionsearch; -import java.awt.Color; import java.util.HashSet; import java.util.Set; import docking.action.DockingAction; import docking.action.MenuData; import docking.tool.ToolConstants; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.CorePluginPackage; import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableContextAction; @@ -135,12 +135,12 @@ public class InstructionSearchPlugin extends ProgramPlugin { if (selection.getNumAddresses() == 0) { dialog.displayMessage( "Select instructions from the listing (and hit reload) to populate the table.", - Color.BLUE); + Messages.NORMAL); return false; } if (!isSelectionSizeValid(selection)) { dialog.displayMessage("Invalid selection. Cannot select more than " + - MAX_SELECTION_SIZE + " instructions and/or data items.", Color.RED); + MAX_SELECTION_SIZE + " instructions and/or data items.", Messages.ERROR); return false; } @@ -150,7 +150,7 @@ public class InstructionSearchPlugin extends ProgramPlugin { } } catch (InvalidInputException e) { - dialog.displayMessage(e.getMessage(), Color.RED); + dialog.displayMessage(e.getMessage(), Messages.ERROR); return false; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/model/InstructionTableDataObject.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/model/InstructionTableDataObject.java index 126cb6aa62..f81ed99f13 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/model/InstructionTableDataObject.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/model/InstructionTableDataObject.java @@ -22,6 +22,8 @@ import java.util.Set; import javax.swing.BorderFactory; import javax.swing.border.Border; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.instructionsearch.ui.AbstractInstructionTable.OperandState; import ghidra.app.plugin.core.instructionsearch.ui.InstructionTable; @@ -42,37 +44,41 @@ public class InstructionTableDataObject { * This is static since all data objects will have the same list of * observers */ - private Set observers = new HashSet (); + private Set observers = new HashSet<>(); // The text displayed in the cell. private String data; // Some cell attributes. private Color backgroundColor; - private Color foregroundColor; + private Color foregroundColor = Colors.FOREGROUND; private int fontStyle; - // The border style of the cell. This is used to facilitate the 3D look of the - // cells (bevel-styling). + // The border style of the cell. This is used to facilitate the 3D look of the cells + // (bevel-styling). private Border border; - // The state of the object; this describes whether the cell is in a masked or - // unmasked state, or neither (NA). + // The state of the object; this describes whether the cell is in a masked or unmasked state, + // or neither (NA). private OperandState state; - // True if this data object represents an instruction (and not an undefined data item or - // string). + // True if this data object represents an instruction (and not an undefined data). private boolean isInstruction; // Stores information about the operand for this cell (if it's an operand); if the // cell represents a mnemonic then this does not apply. private OperandMetadata operandCase; - private static final Color BACKGROUND_COLOR = new Color(237, 243, 254); - private static final Color BACKGROUND_COLOR_DARKER = new Color(188, 212, 254); - private static final Color BACKGROUND_COLOR_NON_INSTRUCTION = new Color(255, 242, 214); - private static final Color BACKGROUND_COLOR_DARKER_NON_INSTRUCTION = new Color(203, 186, 150); - private static final Color PANEL_COLOR = new Color(214, 217, 223); + private static final Color BG_COLOR_MASKED_INSTRUCTION = + new GColor("color.bg.plugin.instructionsearch.table.masked.instruction"); + private static final Color BG_COLOR_NOT_MASKED_INSTRUCTION = + new GColor("color.bg.plugin.instructionsearch.table.not.masked.instruction"); + private static final Color BG_COLOR_MASKED_NON_INSTRUCTION = + new GColor("color.bg.plugin.instructionsearch.table.masked.non.instruction"); + private static final Color BG_COLOR_NOT_MASKED_NON_INSTRUCTION = + new GColor("color.bg.plugin.instructionsearch.table.not.masked.non.instruction"); + private static final Color BG_COLOR_DEFAULT = + new GColor("color.bg.plugin.instructionsearch.table.default"); /** * Constructor. @@ -124,22 +130,20 @@ public class InstructionTableDataObject { switch (state) { case MASKED: backgroundColor = - isInstruction ? BACKGROUND_COLOR : BACKGROUND_COLOR_NON_INSTRUCTION; - foregroundColor = Color.BLACK; + isInstruction ? BG_COLOR_MASKED_INSTRUCTION : BG_COLOR_MASKED_NON_INSTRUCTION; border = BorderFactory.createLoweredSoftBevelBorder(); break; case NOT_MASKED: - backgroundColor = isInstruction ? BACKGROUND_COLOR_DARKER - : BACKGROUND_COLOR_DARKER_NON_INSTRUCTION; - foregroundColor = Color.BLACK; + backgroundColor = isInstruction ? BG_COLOR_NOT_MASKED_INSTRUCTION + : BG_COLOR_NOT_MASKED_NON_INSTRUCTION; border = BorderFactory.createRaisedSoftBevelBorder(); break; case NA: - backgroundColor = PANEL_COLOR; + backgroundColor = BG_COLOR_DEFAULT; break; case PREVIEW: backgroundColor = - isInstruction ? BACKGROUND_COLOR : BACKGROUND_COLOR_NON_INSTRUCTION; + isInstruction ? BG_COLOR_MASKED_INSTRUCTION : BG_COLOR_MASKED_NON_INSTRUCTION; break; } @@ -148,9 +152,6 @@ public class InstructionTableDataObject { } } - /** - * Subscribes the given observer to be notified of changes to this object. - */ public void register(InstructionTableObserver observer) { observers.add(observer); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java index 270620a717..e70bc184b9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java @@ -15,8 +15,6 @@ */ package ghidra.app.plugin.core.instructionsearch.ui; -import java.awt.Font; - import javax.swing.JToolBar; import javax.swing.table.TableCellRenderer; @@ -58,8 +56,7 @@ public abstract class AbstractInstructionTable extends GhidraTable { protected JToolBar toolbar; - protected InstructionTableCellRenderer renderer = - new InstructionTableCellRenderer(new Font("Courier", Font.PLAIN, 14)); + protected InstructionTableCellRenderer renderer = new InstructionTableCellRenderer(); protected InstructionSearchData searchData; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/ControlPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/ControlPanel.java index b8f207572e..ac8c4fb3f5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/ControlPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/ControlPanel.java @@ -15,11 +15,13 @@ */ package ghidra.app.plugin.core.instructionsearch.ui; -import java.awt.*; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import javax.swing.BorderFactory; import javax.swing.JPanel; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin; /** @@ -31,11 +33,6 @@ public class ControlPanel extends JPanel { private SelectionScopeWidget rangeWidget; private SearchDirectionWidget directionWidget; - /** - * - * @param plugin - * @param dialog - */ public ControlPanel(InstructionSearchPlugin plugin, InstructionSearchDialog dialog) { setLayout(new GridBagLayout()); @@ -60,21 +57,13 @@ public class ControlPanel extends JPanel { gbc.weightx = 1.0; this.add(directionWidget, gbc); - this.setBorder(BorderFactory.createLineBorder(Color.GRAY)); + this.setBorder(BorderFactory.createLineBorder(Java.BORDER)); } - /** - * - * @return - */ public SelectionScopeWidget getRangeWidget() { return this.rangeWidget; } - /** - * - * @return - */ public SearchDirectionWidget getDirectionWidget() { return this.directionWidget; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java index ef67a1393a..ba0e87cf72 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java @@ -15,25 +15,23 @@ */ package ghidra.app.plugin.core.instructionsearch.ui; -import java.awt.Color; import java.awt.Font; import docking.widgets.textarea.HintTextArea; +import generic.theme.GThemeDefaults.Colors; /** * Allows users to provide a text hint in a text field, shown only when the text is empty. - * + * * Hint text will be shown in light grey, italicized, and in angle brackets. Normal text will * be plain black. */ public class HintTextAreaIS extends HintTextArea { - private String hint; - /** * Constructs the class with the hint text to be shown. * - * @param hint + * @param hint the hint */ public HintTextAreaIS(final String hint) { super(hint); @@ -53,16 +51,12 @@ public class HintTextAreaIS extends HintTextArea { setAttributes(); } - /********************************************************************************************* - * PRIVATE METHODS - ********************************************************************************************/ - /** * Sets the text attributes to be used when there is an error in the input. */ private void setErrorAttributes() { this.setFont(getFont().deriveFont(Font.PLAIN)); - setForeground(Color.RED); + setForeground(Colors.ERROR); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java index 0b1743217a..154a7db003 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java @@ -15,7 +15,8 @@ */ package ghidra.app.plugin.core.instructionsearch.ui; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; @@ -25,6 +26,7 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import docking.DialogComponentProvider; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.plugin.core.instructionsearch.model.*; import ghidra.app.plugin.core.instructionsearch.ui.SelectionModeWidget.InputMode; import ghidra.app.plugin.core.instructionsearch.util.InstructionSearchUtils; @@ -290,7 +292,8 @@ public class InsertBytesWidget extends DialogComponentProvider implements KeyLis // there's a problem with the input. Just print a message to the user and // exit. if (allBytes.size() < instruction.getLength()) { - msgPanel.setMessageText("Input invalid: unknown disassembly error.", Color.RED); + msgPanel.setMessageText("Input invalid: unknown disassembly error.", + Messages.ERROR); return; } allBytes.subList(0, instruction.getLength()).clear(); @@ -300,7 +303,8 @@ public class InsertBytesWidget extends DialogComponentProvider implements KeyLis // If there's an exception, just stop and let the user figure out what went // wrong - no need to continue. - msgPanel.setMessageText("Input invalid: unknown disassembly error.", Color.RED); + msgPanel.setMessageText("Input invalid: unknown disassembly error.", + Messages.ERROR); Msg.debug(this, "Error disassembling instruction", e); return; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionSearchDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionSearchDialog.java index ec79cebaad..9d7beb1fdb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionSearchDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionSearchDialog.java @@ -23,6 +23,8 @@ import javax.swing.*; import docking.ComponentProvider; import docking.DialogComponentProvider; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin; import ghidra.app.plugin.core.instructionsearch.model.InstructionMetadata; @@ -61,6 +63,9 @@ import ghidra.util.task.TaskMonitor; public class InstructionSearchDialog extends DialogComponentProvider implements Observer { + private static final Color BG_COLOR_MARKERS = + new GColor("color.bg.plugin.instructionsearch.search.markers"); + // Panel containing the {@link InstructionTable} and {@link PreviewTable}. private InstructionSearchMainPanel tablePanel; @@ -136,7 +141,7 @@ public class InstructionSearchDialog extends DialogComponentProvider implements if (selection == null && getMessagePanel() != null) { getMessagePanel().setMessageText( "Select instructions from the listing (and hit reload) to populate the table.", - Color.BLUE); + Messages.NORMAL); } if (selection != null && plugin.isSelectionValid(selection, this)) { @@ -498,7 +503,7 @@ public class InstructionSearchDialog extends DialogComponentProvider implements model.setSelectionSize(matchSize); TableComponentProvider
tableProvider = table.showTableWithMarkers(title + " " + model.getName(), "InstructionSearch", - model, Color.GREEN, null, "Instruction Search Results", null); + model, BG_COLOR_MARKERS, null, "Instruction Search Results", null); tableProvider.installRemoveItemsAction(); }; SystemUtilities.runSwingLater(runnable); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java index 1723488baf..6499b49a69 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.instructionsearch.ui; -import java.awt.Color; import java.awt.event.*; import java.util.List; @@ -23,6 +22,8 @@ import javax.swing.*; import docking.DockingWindowManager; import docking.widgets.EmptyBorderButton; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin; import ghidra.app.plugin.core.instructionsearch.model.*; import ghidra.app.services.GoToService; @@ -32,6 +33,7 @@ import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.exception.InvalidInputException; import ghidra.util.task.*; +import resources.Icons; import resources.ResourceManager; /** @@ -47,15 +49,6 @@ public class InstructionTable extends AbstractInstructionTable { // Defines the width/height for all icons on the toolbar private static final int ICON_SIZE = 16; - private static final String GO_HOME_ICON_OVERLAY = "images/go-home.png"; - private static final String ADDRESS_ICON_OVERLAY = "images/DOSA_A.png"; - private static final String SCALAR_ICON_OVERLAY = "images/DOSA_S.png"; - private static final String OPERAND_ICON_OVERLAY = "images/DOSA_O.png"; - private static final String UNDEFINED_ICON_OVERLAY = "images/DOSA_D.png"; - private static final String CLEAR_ICON_OVERLAY = "images/edit-clear.png"; - private static final String RELOAD_ICON_OVERLAY = "images/reload.png"; - private static final String MANUAL_ENTRY_ICON_OVERLAY = "images/editbytes.gif"; - // Need to keep track of the column in case the user clicks on the column header and we // need to display the context menu. private int selectedColumn = -1; @@ -168,7 +161,9 @@ public class InstructionTable extends AbstractInstructionTable { } InstructionTableDataObject[][] dataObjects = - new InstructionTableDataObject[dialog.getSearchData().getInstructions().size()][numColumns]; + new InstructionTableDataObject[dialog.getSearchData() + .getInstructions() + .size()][numColumns]; // Loop over all instructions, adding pertinent info to each data object. This could be a long-running // operation so put in a task that can be cancelled. @@ -285,21 +280,21 @@ public class InstructionTable extends AbstractInstructionTable { } private void createGoToAddressBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(GO_HOME_ICON_OVERLAY); + Icon icon = Icons.HOME_ICON; Action action = new NavAction("navigation", icon, "Navigate to the address defined by this instruction set"); createToolbarButton(buttonToolbar, icon, action, "nav button"); } private void createMaskClearAllBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(CLEAR_ICON_OVERLAY); + Icon icon = Icons.CLEAR_ICON; Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new ClearMasksAction("undefined", scaledIcon, "Unmask all"); createToolbarButton(buttonToolbar, icon, action, "unmask all button"); } private void createReloadBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(RELOAD_ICON_OVERLAY); + Icon icon = Icons.REFRESH_ICON; Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new ReloadAction("undefined", scaledIcon, "Load selected instructions from listing"); @@ -307,14 +302,14 @@ public class InstructionTable extends AbstractInstructionTable { } private void createManualEditBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(MANUAL_ENTRY_ICON_OVERLAY); + Icon icon = new GIcon("icon.plugin.instructiontable.manual.entry"); Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new ManualEntryAction("undefined", scaledIcon, "Enter bytes manually"); createToolbarButton(buttonToolbar, icon, action, "manual entry"); } private void createMaskDataBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(UNDEFINED_ICON_OVERLAY); + Icon icon = new GIcon("icon.plugin.instructiontable.undefined"); Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new MaskUndefinedAction("undefined", scaledIcon, "Mask all non-instructions (data)"); @@ -322,21 +317,21 @@ public class InstructionTable extends AbstractInstructionTable { } private void createMaskAddressesBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(ADDRESS_ICON_OVERLAY); + Icon icon = new GIcon("icon.plugin.instructiontable.address"); Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new MaskAddressesAction("addresses", scaledIcon, "Mask all addresses"); createToolbarButton(buttonToolbar, icon, action, "mask addresses button"); } private void createMaskScalarsBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(SCALAR_ICON_OVERLAY); + Icon icon = new GIcon("icon.plugin.instructiontable.scalar"); Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new MaskScalarsAction("scalars", scaledIcon, "Mask all scalars"); createToolbarButton(buttonToolbar, icon, action, "mask scalars button"); } private void createMaskOperandsBtn(JToolBar buttonToolbar) { - Icon icon = ResourceManager.loadImage(OPERAND_ICON_OVERLAY); + Icon icon = new GIcon("icon.plugin.instructiontable.operand"); Icon scaledIcon = ResourceManager.getScaledIcon(icon, ICON_SIZE, ICON_SIZE); Action action = new MaskOperandsAction("operands", scaledIcon, "Mask all operands"); createToolbarButton(buttonToolbar, icon, action, "mask operands button"); @@ -516,9 +511,10 @@ public class InstructionTable extends AbstractInstructionTable { } else { if (dialog.getMessagePanel() != null) { - dialog.getMessagePanel().setMessageText( - "Instruction was loaded manually, no address in the listing to navigate to.", - Color.BLUE); + dialog.getMessagePanel() + .setMessageText( + "Instruction was loaded manually, no address in the listing to navigate to.", + Messages.NORMAL); } } } @@ -546,7 +542,6 @@ public class InstructionTable extends AbstractInstructionTable { /** * Creates a new {@link InstructionTableDataObject} for the given operand. * - * @param mnemonic the mnemonic ID * @param col the column in the table * @param dataObjects the set of data objects to modify */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java index 58fa759f76..d6833c37a8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java @@ -21,6 +21,7 @@ import javax.swing.*; import javax.swing.table.TableModel; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.Gui; import ghidra.app.plugin.core.instructionsearch.model.InstructionTableDataObject; import ghidra.util.table.GhidraTableCellRenderer; @@ -29,13 +30,10 @@ import ghidra.util.table.GhidraTableCellRenderer; * while adding some custom logic for changing background/foreground attributes. */ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { + private static final String FONT_ID = "font.plugin.instruction.table.renderer"; - /** - * - * @param font - */ - public InstructionTableCellRenderer(Font font) { - super(font); + public InstructionTableCellRenderer() { + super(Gui.getFont(FONT_ID)); } /** @@ -76,24 +74,10 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { return this; } - /********************************************************************************************* - * PRIVATE METHODS - ********************************************************************************************/ - - /** - * - * @param dataObject - * @param theRenderer - */ private void setBorderAttributes(InstructionTableDataObject dataObject, JLabel theRenderer) { theRenderer.setBorder(dataObject.getBorder()); } - /** - * - * @param dataObject - * @param theRenderer - */ private void setForegroundAttributes(InstructionTableDataObject dataObject, JLabel theRenderer) { // Change the foreground to use a font of our choosing. The main reason is that we @@ -103,12 +87,6 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { theRenderer.setFont(newFont); } - /** - * - * @param isSelected - * @param hasFocus - * @param dataObject - */ private void setBackgroundAttributes(boolean isSelected, boolean hasFocus, InstructionTableDataObject dataObject) { // Set the background color based on what the cell says. If it's selected, make it a @@ -116,7 +94,7 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { Color backgroundColor = dataObject.getBackgroundColor(); if (backgroundColor != null) { if (isSelected || hasFocus) { - setBackground(backgroundColor.darker()); + setBackground(Gui.darker(backgroundColor)); } else { setBackground(backgroundColor); @@ -124,12 +102,6 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { } } - /** - * - * @param table - * @param value - * @param col - */ private void setTextAttributes(JTable table, Object value, int col) { setHorizontalAlignment(SwingConstants.LEFT); TableModel model = table.getModel(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java index 9e4692de6f..f3ae5aa469 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java @@ -31,6 +31,7 @@ import docking.action.DockingAction; import docking.action.MenuData; import docking.dnd.GClipboard; import docking.widgets.EmptyBorderButton; +import generic.theme.GIcon; import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin; import ghidra.app.plugin.core.instructionsearch.model.*; import ghidra.app.plugin.core.instructionsearch.ui.SelectionModeWidget.InputMode; @@ -39,7 +40,7 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.util.Msg; import ghidra.util.exception.InvalidInputException; import ghidra.util.task.*; -import resources.ResourceManager; +import resources.Icons; /** * Displays the preview string for all instructions in the @@ -231,12 +232,6 @@ public class PreviewTable extends AbstractInstructionTable { new TaskLauncher(task, PreviewTable.this); } - /********************************************************************************************* - * PROTECTED METHODS - ********************************************************************************************/ - /** - * - */ @Override protected Object[] createColumnHeaders() { @@ -246,9 +241,6 @@ public class PreviewTable extends AbstractInstructionTable { return colsNames; } - /** - * - */ @Override protected JToolBar createToolbar() { JToolBar toolbar1 = new JToolBar(); @@ -293,10 +285,6 @@ public class PreviewTable extends AbstractInstructionTable { return dataObjects; } - /********************************************************************************************* - * PRIVATE METHODS - ********************************************************************************************/ - private void buildPreviewString(int instrSize, String valueStr, String maskStr, int posptr, int row) { @@ -328,8 +316,8 @@ public class PreviewTable extends AbstractInstructionTable { } private void createCopyBtn(JToolBar toolbar1) { - Icon copyIcon = ResourceManager.loadImage("images/page_white_copy.png"); - Action copyAction = new CopyAction("copy", (ImageIcon) copyIcon, + Icon copyIcon = Icons.COPY_ICON; + Action copyAction = new CopyAction("copy", copyIcon, "Copy the full search string to clipboard"); EmptyBorderButton copyBtn = new EmptyBorderButton(); copyBtn.setAction(copyAction); @@ -339,8 +327,8 @@ public class PreviewTable extends AbstractInstructionTable { } private EmptyBorderToggleButton createHexViewBtn(JToolBar toolbar1) { - Icon hexIcon = ResourceManager.loadImage("images/hexData.png"); - Action hexAction = new HexAction("hex", (ImageIcon) hexIcon, "hex view"); + Icon hexIcon = new GIcon("icon.plugin.instructiontable.hex"); + Action hexAction = new HexAction("hex", hexIcon, "hex view"); EmptyBorderToggleButton hexBtn = new EmptyBorderToggleButton(); hexBtn.setAction(hexAction); hexBtn.setName("Hex View Button"); @@ -351,8 +339,8 @@ public class PreviewTable extends AbstractInstructionTable { } private EmptyBorderToggleButton createBinaryViewBtn(JToolBar toolbar1) { - Icon binaryIcon = ResourceManager.loadImage("images/binaryData.gif"); - Action binaryAction = new BinaryAction("binary", (ImageIcon) binaryIcon, "binary view"); + Icon binaryIcon = new GIcon("icon.plugin.instructiontable.binary"); + Action binaryAction = new BinaryAction("binary", binaryIcon, "binary view"); EmptyBorderToggleButton binaryBtn = new EmptyBorderToggleButton(); binaryBtn.setAction(binaryAction); binaryBtn.setName("binary view button"); @@ -449,19 +437,19 @@ public class PreviewTable extends AbstractInstructionTable { createCopyNoSpacesAction(owner); copyNoSpacesAction.setPopupMenuData( new MenuData(new String[] { "Copy Special", "Selected instructions (no spaces)" }, - ResourceManager.loadImage("images/page_white_copy.png"), actionMenuGroup, + Icons.COPY_ICON, actionMenuGroup, MenuData.NO_MNEMONIC, Integer.toString(1))); createCopyInstructionAction(owner); copyInstructionAction.setPopupMenuData( new MenuData(new String[] { "Copy Special", "Selected Instructions" }, - ResourceManager.loadImage("images/page_white_copy.png"), actionMenuGroup, + Icons.COPY_ICON, actionMenuGroup, MenuData.NO_MNEMONIC, Integer.toString(1))); createCopyInstructionWithCommentsAction(owner); copyInstructionWithCommentsAction.setPopupMenuData( new MenuData(new String[] { "Copy Special", "Selected Instructions (with comments)" }, - ResourceManager.loadImage("images/page_white_copy.png"), actionMenuGroup, + Icons.COPY_ICON, actionMenuGroup, MenuData.NO_MNEMONIC, Integer.toString(1))); dialog.addAction(copyNoSpacesAction); @@ -488,8 +476,12 @@ public class PreviewTable extends AbstractInstructionTable { if (comment != null) { StringBuilder builder = new StringBuilder(); - builder.append(val).append("\t").append("// ").append(comment).append( - "\n"); + builder.append(val) + .append("\t") + .append("// ") + .append(comment) + .append( + "\n"); val = builder.toString(); } } @@ -566,7 +558,7 @@ public class PreviewTable extends AbstractInstructionTable { private class BinaryAction extends AbstractAction { - public BinaryAction(String text, ImageIcon icon, String desc) { + public BinaryAction(String text, Icon icon, String desc) { super(text, icon); putValue(SHORT_DESCRIPTION, desc); } @@ -580,7 +572,7 @@ public class PreviewTable extends AbstractInstructionTable { private class HexAction extends AbstractAction { - public HexAction(String text, ImageIcon icon, String desc) { + public HexAction(String text, Icon icon, String desc) { super(text, icon); putValue(SHORT_DESCRIPTION, desc); } @@ -594,7 +586,7 @@ public class PreviewTable extends AbstractInstructionTable { private class CopyAction extends AbstractAction { - public CopyAction(String text, ImageIcon icon, String desc) { + public CopyAction(String text, Icon icon, String desc) { super(text, icon); putValue(SHORT_DESCRIPTION, desc); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/SearchInstructionsTask.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/SearchInstructionsTask.java index 833fc6a7b9..d3902ba782 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/SearchInstructionsTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/SearchInstructionsTask.java @@ -15,19 +15,18 @@ */ package ghidra.app.plugin.core.instructionsearch.ui; -import java.awt.Color; import java.util.*; -import javax.swing.SwingUtilities; - +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin; import ghidra.app.plugin.core.instructionsearch.model.InstructionMetadata; import ghidra.app.plugin.core.instructionsearch.ui.SearchDirectionWidget.Direction; import ghidra.app.services.GoToService; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressRange; -import ghidra.program.model.listing.CodeUnit; +import ghidra.program.model.listing.*; import ghidra.program.util.BytesFieldLocation; +import ghidra.util.Swing; import ghidra.util.task.Task; import ghidra.util.task.TaskMonitor; @@ -73,8 +72,11 @@ class SearchInstructionsTask extends Task { // See if we're searching forward or backwards. boolean forward = - searchDialog.getControlPanel().getDirectionWidget().getSearchDirection().equals( - Direction.FORWARD); + searchDialog.getControlPanel() + .getDirectionWidget() + .getSearchDirection() + .equals( + Direction.FORWARD); // If we're searching backwards we need to process address ranges in reverse so reverse // the list. @@ -121,7 +123,7 @@ class SearchInstructionsTask extends Task { // // Note we put these on the swing thread or it will throw off the task monitor display. if (searchResults != null) { - SwingUtilities.invokeLater(() -> { + Swing.runLater(() -> { goToLocation(searchResults.getAddr()); searchDialog.getMessagePanel().clear(); }); @@ -134,7 +136,8 @@ class SearchInstructionsTask extends Task { // If we've gone through all the ranges and there are still no results, show an // error message. - searchDialog.getMessagePanel().setMessageText("No results found", Color.BLUE); + searchDialog.getMessagePanel() + .setMessageText("No results found", Messages.NORMAL); return; } @@ -157,13 +160,13 @@ class SearchInstructionsTask extends Task { // The reason for the getting the CodeUnit is that the instruction might be an off-cut, // and if that's the case, then we can't navigate directly to it. What we have to do // is find the CodeUnit containing the instruction and navigate to that. + Program currentProgram = searchPlugin.getCurrentProgram(); + Listing listing = currentProgram.getListing(); if (direction == Direction.FORWARD) { for (InstructionMetadata instr : searchResults) { - CodeUnit unit = searchPlugin.getCurrentProgram().getListing().getCodeUnitContaining( - instr.getAddr()); - - if (unit.getMinAddress().compareTo(currentAddress) > 0) { - return unit.getMinAddress(); + CodeUnit cu = listing.getCodeUnitContaining(instr.getAddr()); + if (cu.getMinAddress().compareTo(currentAddress) > 0) { + return cu.getMinAddress(); } } } @@ -173,14 +176,12 @@ class SearchInstructionsTask extends Task { // // See above for an explanation for why we need to get the CodeUnit in this block. if (direction == Direction.BACKWARD) { - ListIteratoriter = - searchResults.listIterator(searchResults.size()); - while (iter.hasPrevious()) { - InstructionMetadata instr = iter.previous(); - CodeUnit unit = searchPlugin.getCurrentProgram().getListing().getCodeUnitContaining( - instr.getAddr()); - if (unit.getMinAddress().compareTo(currentAddress) < 0) { - return unit.getMinAddress(); + ListIterator it = searchResults.listIterator(searchResults.size()); + while (it.hasPrevious()) { + InstructionMetadata instr = it.previous(); + CodeUnit cu = listing.getCodeUnitContaining(instr.getAddr()); + if (cu.getMinAddress().compareTo(currentAddress) < 0) { + return cu.getMinAddress(); } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/AnsiRenderer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/AnsiRenderer.java index 5d2231686f..a10b54c0c1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/AnsiRenderer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/AnsiRenderer.java @@ -19,7 +19,9 @@ import java.awt.Color; import javax.swing.text.*; +import generic.theme.GColor; import ghidra.app.plugin.core.interpreter.AnsiParser.AnsiParserHandler; +import ghidra.util.ColorUtils; /** * An object for parsing and rendering ANSI-styled strings into a Swing {@link Document}. @@ -32,22 +34,6 @@ import ghidra.app.plugin.core.interpreter.AnsiParser.AnsiParserHandler; * renderers prevents the corruption of those escape sequences when interleaving the output streams. */ public class AnsiRenderer { - public static final Color BLACK = new Color(0, 0, 0); - public static final Color RED = new Color(194, 54, 33); - public static final Color GREEN = new Color(37, 188, 36); - public static final Color YELLOW = new Color(173, 173, 39); - public static final Color BLUE = new Color(73, 46, 225); - public static final Color MAGENTA = new Color(211, 56, 211); - public static final Color CYAN = new Color(51, 187, 200); - public static final Color WHITE = new Color(203, 204, 205); - public static final Color HI_BLACK = new Color(129, 131, 131); - public static final Color HI_RED = new Color(252, 57, 31); - public static final Color HI_GREEN = new Color(49, 231, 34); - public static final Color HI_YELLOW = new Color(234, 236, 35); - public static final Color HI_BLUE = new Color(88, 51, 255); - public static final Color HI_MAGENTA = new Color(249, 53, 248); - public static final Color HI_CYAN = new Color(20, 240, 240); - public static final Color HI_WHITE = new Color(233, 235, 235); /** * These colors are taken from Terminal.app as documented on Wikipedia as of 26 April 2022. @@ -58,23 +44,23 @@ public class AnsiRenderer { */ private static final Color[] BASIC_COLORS = { // standard colors - BLACK, - RED, - GREEN, - YELLOW, - BLUE, - MAGENTA, - CYAN, - WHITE, + new GColor("color.fg.plugin.interpreter.renderer.color.standard.1"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.2"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.3"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.4"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.5"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.6"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.7"), + new GColor("color.fg.plugin.interpreter.renderer.color.standard.8"), // high intensity colors - HI_BLACK, - HI_RED, - HI_GREEN, - HI_YELLOW, - HI_BLUE, - HI_MAGENTA, - HI_CYAN, - HI_WHITE, + new GColor("color.fg.plugin.interpreter.renderer.color.intense.1"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.2"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.3"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.4"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.5"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.6"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.7"), + new GColor("color.fg.plugin.interpreter.renderer.color.intense.8"), }; /** * This aids the implementation of the 6x6x6 color cube. @@ -98,12 +84,12 @@ public class AnsiRenderer { } /** - * Get the 8-bit ansi color. + * Get the 8-bit ANSI color. * * - * Colors 0-15 are the {@link AnsiRenderer#BASIC_COLORS: standard + high-intensity. Colors + * Colors 0-15 are the {@link AnsiRenderer#AnsiRenderer}: standard + high-intensity. Colors * 16-231 come from a 6x6x6 RGB cube; see {@link AnsiRenderer#CUBE_STEPS}. Finally, colors - * 232-255 are 24 steps of grayscale. + * 232-255 are 24 steps of gray scale. * * @param v an 8-bit number * @return the ANSI color @@ -117,12 +103,12 @@ public class AnsiRenderer { int b = v % 6; int g = (v / 6) % 6; int r = (v / 36) % 6; - return new Color(CUBE_STEPS[r], CUBE_STEPS[g], CUBE_STEPS[b]); + return ColorUtils.getColor(CUBE_STEPS[r], CUBE_STEPS[g], CUBE_STEPS[b]); } else if (v < 256) { v -= 232; int gray = v * 10 + 8; - return new Color(gray, gray, gray); + return ColorUtils.getColor(gray, gray, gray); } else { /* invalid */ @@ -146,7 +132,7 @@ public class AnsiRenderer { private int handleSGRAttribute(String[] bits, int pos) throws NumberFormatException { int code = Integer.parseInt(bits[pos]); if (code >= 30 && code < 50) { - /* Colour codes */ + /* Color codes */ Object attributeName = (code < 40) ? StyleConstants.Foreground : StyleConstants.Background; int colorCode = code % 10; @@ -172,7 +158,7 @@ public class AnsiRenderer { int r = Integer.parseInt(bits[pos + 2]); int g = Integer.parseInt(bits[pos + 3]); int b = Integer.parseInt(bits[pos + 4]); - attributes.addAttribute(attributeName, new Color(r, g, b)); + attributes.addAttribute(attributeName, ColorUtils.getColor(r, g, b)); return 5; } return 1; @@ -314,6 +300,7 @@ public class AnsiRenderer { * @param document Document to render the string to * @param text A text string which may contain 7-bit ANSI escape codes * @param attributes Current text attributes; may be modified by this function + * @throws BadLocationException if there is an error parsing the text */ public void renderString(StyledDocument document, String text, MutableAttributeSet attributes) throws BadLocationException { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java index ae2ff6e252..299cd4734b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java @@ -25,6 +25,7 @@ import javax.swing.border.EmptyBorder; import javax.swing.event.ListDataListener; import docking.widgets.list.GListCellRenderer; +import generic.theme.GThemeDefaults.Colors; import generic.util.WindowUtilities; import ghidra.app.plugin.core.console.CodeCompletion; @@ -37,7 +38,7 @@ import ghidra.app.plugin.core.console.CodeCompletion; public class CodeCompletionWindow extends JDialog { private static final long serialVersionUID = 1L; /* from ReferenceHoverPlugin */ - private static final Color BACKGROUND_COLOR = new Color(255, 255, 230); + private static final Color BACKGROUND_COLOR = Colors.BACKGROUND_TOOLTIP; protected final InterpreterPanel console; protected final JTextPane outputTextField; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java index 4db22f295a..d868bfeb9a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java @@ -26,18 +26,15 @@ import docking.ActionContext; import docking.action.DockingAction; import docking.action.ToolBarData; import docking.widgets.OptionDialog; +import generic.theme.GIcon; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.util.HelpLocation; import resources.Icons; -import resources.ResourceManager; import utility.function.Callback; public class InterpreterComponentProvider extends ComponentProviderAdapter implements InterpreterConsole { - private static final String CONSOLE_GIF = "images/monitor.png"; - private static final String CLEAR_GIF = "images/erase16.png"; - private InterpreterPanel panel; private InterpreterConnection interpreter; private List
firstActivationCallbacks; @@ -57,7 +54,7 @@ public class InterpreterComponentProvider extends ComponentProviderAdapter Icon icon = interpreter.getIcon(); if (icon == null) { - icon = ResourceManager.loadImage(CONSOLE_GIF); + icon = new GIcon("icon.plugin.interpreter.provider"); } setIcon(icon); @@ -73,7 +70,7 @@ public class InterpreterComponentProvider extends ComponentProviderAdapter } }; clearAction.setDescription("Clear Interpreter"); - clearAction.setToolBarData(new ToolBarData(ResourceManager.loadImage(CLEAR_GIF), null)); + clearAction.setToolBarData(new ToolBarData(Icons.CLEAR_ICON, null)); clearAction.setEnabled(true); addLocalAction(clearAction); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java index cc093ba06c..0d970baac9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterConnection.java @@ -17,7 +17,7 @@ package ghidra.app.plugin.core.interpreter; import java.util.List; -import javax.swing.ImageIcon; +import javax.swing.Icon; import ghidra.app.plugin.core.console.CodeCompletion; @@ -38,7 +38,7 @@ public interface InterpreterConnection { * * @return The icon associated with the interpreter. Null if default icon is desired. */ - public ImageIcon getIcon(); + public Icon getIcon(); /** * Gets a {@link List} of {@link CodeCompletion code completions} for the given command. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java index bf7f1f7ff1..6a9b7be33f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java @@ -28,12 +28,15 @@ import javax.swing.text.*; import docking.DockingUtils; import docking.actions.KeyBindingUtils; +import generic.theme.GColor; +import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.framework.options.OptionsChangeListener; import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.PluginTool; -import ghidra.util.*; +import ghidra.util.HelpLocation; +import ghidra.util.Msg; public class InterpreterPanel extends JPanel implements OptionsChangeListener { @@ -41,13 +44,14 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { private static final String COMPLETION_WINDOW_TRIGGER_DESCRIPTION = "The key binding used to show the auto-complete window " + "(for those consoles that have auto-complete)."; + private static final String FONT_ID = "font.plugin.console"; private static final String FONT_OPTION_LABEL = "Font"; private static final String FONT_DESCRIPTION = "This is the font that will be used in the Console. " + "Double-click the font example to change it."; - private static final Color NORMAL_COLOR = Color.black; - private static final Color ERROR_COLOR = Color.red; + private static final Color NORMAL_COLOR = new GColor("color.fg.interpreterpanel"); + private static final Color ERROR_COLOR = new GColor("color.fg.interpreterpanel.error"); public enum TextType { STDOUT, STDERR, STDIN; @@ -68,8 +72,6 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { private PrintWriter outWriter; private PrintWriter errWriter; - private Font basicFont = getBasicFont(); - private Font basicBoldFont = getBoldFont(basicFont); private SimpleAttributeSet STDOUT_SET; private SimpleAttributeSet STDERR_SET; private SimpleAttributeSet STDIN_SET; @@ -81,14 +83,6 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { private boolean caretGuard = true; private PluginTool tool; - private static Font getBasicFont() { - return new Font(Font.MONOSPACED, Font.PLAIN, 20); - } - - private static Font getBoldFont(Font font) { - return font.deriveFont(Font.BOLD); - } - private static SimpleAttributeSet createAttributes(Font font, Color color) { SimpleAttributeSet attributeSet = new SimpleAttributeSet(); attributeSet.addAttribute(StyleConstants.FontFamily, font.getFamily()); @@ -368,15 +362,14 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { } } - private void updateFontAttributes(Font newFont) { - basicFont = newFont; - basicBoldFont = getBoldFont(newFont); - STDOUT_SET = createAttributes(basicFont, NORMAL_COLOR); - STDERR_SET = createAttributes(basicFont, ERROR_COLOR); - STDIN_SET = createAttributes(basicBoldFont, NORMAL_COLOR); + private void updateFontAttributes(Font font) { + Font boldFont = font.deriveFont(Font.BOLD); + STDOUT_SET = createAttributes(font, NORMAL_COLOR); + STDERR_SET = createAttributes(font, ERROR_COLOR); + STDIN_SET = createAttributes(boldFont, NORMAL_COLOR); - setTextPaneFont(inputTextPane, basicBoldFont); - setTextPaneFont(promptTextPane, basicFont); + setTextPaneFont(inputTextPane, boldFont); + setTextPaneFont(promptTextPane, font); setPrompt(promptTextPane.getText()); } @@ -387,13 +380,13 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { HelpLocation help = new HelpLocation(getName(), "ConsolePlugin"); options.setOptionsHelpLocation(help); - options.registerOption(FONT_OPTION_LABEL, basicFont, help, FONT_DESCRIPTION); + options.registerThemeFontBinding(FONT_OPTION_LABEL, FONT_ID, help, + FONT_DESCRIPTION); options.registerOption(COMPLETION_WINDOW_TRIGGER_LABEL, CompletionWindowTrigger.TAB, help, COMPLETION_WINDOW_TRIGGER_DESCRIPTION); - basicFont = options.getFont(FONT_OPTION_LABEL, basicFont); - basicFont = SystemUtilities.adjustForFontSizeOverride(basicFont); - updateFontAttributes(basicFont); + Font font = Gui.getFont(FONT_ID); + updateFontAttributes(font); completionWindowTrigger = options.getEnum(COMPLETION_WINDOW_TRIGGER_LABEL, CompletionWindowTrigger.TAB); @@ -411,8 +404,8 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { public void optionsChanged(ToolOptions options, String optionName, Object oldValue, Object newValue) { if (optionName.equals(FONT_OPTION_LABEL)) { - basicFont = SystemUtilities.adjustForFontSizeOverride((Font) newValue); - updateFontAttributes(basicFont); + Font font = Gui.getFont(FONT_ID); + updateFontAttributes(font); } else if (optionName.equals(COMPLETION_WINDOW_TRIGGER_LABEL)) { completionWindowTrigger = (CompletionWindowTrigger) newValue; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/LabelHistoryPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/LabelHistoryPanel.java index cd60813c14..b58a5832b2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/LabelHistoryPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/LabelHistoryPanel.java @@ -27,6 +27,7 @@ import javax.swing.table.TableColumnModel; import docking.widgets.GenericDateCellRenderer; import docking.widgets.table.GTableCellRenderer; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.Gui; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.LabelHistory; import ghidra.util.table.GhidraTable; @@ -126,16 +127,11 @@ class LabelHistoryPanel extends JPanel { private Font monoFont; - LabelCellRenderer() { - Font f = getFont(); - monoFont = new Font("monospaced", f.getStyle(), f.getSize()); - } - @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { Component c = super.getTableCellRendererComponent(data); - c.setFont(monoFont); + c.setFont(Gui.getFont("font.monospaced")); return c; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/MarkerSetImpl.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/MarkerSetImpl.java index 1df241ba0f..0c99f671b6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/MarkerSetImpl.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/MarkerSetImpl.java @@ -35,6 +35,7 @@ import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.util.MarkerLocation; import ghidra.program.util.ProgramLocation; +import ghidra.util.ColorUtils; import ghidra.util.Swing; import ghidra.util.datastruct.SortedRangeList; @@ -262,7 +263,7 @@ abstract class MarkerSetImpl implements MarkerSet { int red = (c.getRed() + 3 * COLOR_VALUE) / 4; int green = (c.getGreen() + 3 * COLOR_VALUE) / 4; int blue = (c.getBlue() + 3 * COLOR_VALUE) / 4; - return new Color(red, green, blue); + return ColorUtils.getColor(red, green, blue); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/PointMarkerSet.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/PointMarkerSet.java index 5e241effab..e055d7bb98 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/PointMarkerSet.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/marker/PointMarkerSet.java @@ -31,6 +31,7 @@ import ghidra.program.model.listing.Program; import ghidra.program.util.MarkerLocation; import ghidra.util.datastruct.Range; import ghidra.util.datastruct.SortedRangeList; +import resources.Icons; import resources.ResourceManager; class PointMarkerSet extends MarkerSetImpl { @@ -61,7 +62,7 @@ class PointMarkerSet extends MarkerSetImpl { colorBackground, markerColor, isPreferred); if (icon == null) { - icon = ResourceManager.loadImage("images/warning.png"); + icon = Icons.WARNING_ICON; } ImageIcon imageIcon = ResourceManager.getScaledIcon(icon, 16, 16, Image.SCALE_SMOOTH); image = imageIcon.getImage(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java index 07d3eb5c43..619dd824f3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java @@ -29,6 +29,7 @@ import docking.action.ToolBarData; import docking.widgets.label.GLabel; import docking.widgets.table.*; import docking.widgets.textfield.GValidatedTextField.MaxLengthField; +import generic.theme.GIcon; import ghidra.app.context.ProgramActionContext; import ghidra.framework.model.DomainFile; import ghidra.framework.plugintool.ComponentProviderAdapter; @@ -40,7 +41,6 @@ import ghidra.program.model.mem.MemoryBlockType; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.table.GhidraTable; -import resources.ResourceManager; /** * Provider for the memory map Component. @@ -65,16 +65,6 @@ class MemoryMapProvider extends ComponentProviderAdapter { private MemoryMapPlugin plugin = null; - private final static String ADD_IMAGE = "images/Plus.png"; - private final static String MOVE_IMAGE = "images/move.png"; - private final static String SPLIT_IMAGE = "images/verticalSplit.png"; - private final static String EXPAND_UP_IMAGE = "images/collapse.gif"; - private final static String EXPAND_DOWN_IMAGE = "images/expand.gif"; - private final static String MERGE_IMAGE = "images/Merge.png"; - private final static String DELETE_IMAGE = "images/edit-delete.png"; - private final static String IMAGE_BASE = "images/house.png"; - final static String MEMORY_IMAGE = "images/memory16.gif"; - private Program program; private MemoryMapManager memManager; @@ -84,7 +74,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { setHelpLocation(new HelpLocation(plugin.getName(), getName())); memManager = plugin.getMemoryMapManager(); - setIcon(ResourceManager.loadImage(MEMORY_IMAGE)); + setIcon(new GIcon("icon.plugin.memorymap.provider")); addToToolbar(); mainPanel = buildMainPanel(); addToTool(); @@ -185,7 +175,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { } private void addLocalActions() { - ImageIcon addImage = ResourceManager.loadImage(ADD_IMAGE); + Icon addImage = new GIcon("icon.plugin.memorymap.add"); addAction = new MemoryMapAction("Add Block", addImage) { @Override @@ -200,7 +190,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { addAction.setDescription("Add a new block to memory"); tool.addLocalAction(this, addAction); - ImageIcon moveImage = ResourceManager.loadImage(MOVE_IMAGE); + Icon moveImage = new GIcon("icon.plugin.memorymap.move"); moveAction = new MemoryMapAction("Move Block", moveImage) { @Override public void actionPerformed(ActionContext context) { @@ -213,7 +203,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { moveAction.setDescription("Move a block to another address"); tool.addLocalAction(this, moveAction); - ImageIcon splitImage = ResourceManager.loadImage(SPLIT_IMAGE); + Icon splitImage = new GIcon("icon.plugin.memorymap.split"); splitAction = new MemoryMapAction("Split Block", splitImage) { @Override @@ -228,7 +218,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { splitAction.setDescription("Split a block"); tool.addLocalAction(this, splitAction); - ImageIcon expandUpImage = ResourceManager.loadImage(EXPAND_UP_IMAGE); + Icon expandUpImage = new GIcon("icon.plugin.memorymap.expand.up"); expandUpAction = new MemoryMapAction("Expand Block Up", expandUpImage) { @Override @@ -242,7 +232,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { expandUpAction.setDescription("Expand block by setting new start address"); tool.addLocalAction(this, expandUpAction); - ImageIcon expandDownImage = ResourceManager.loadImage(EXPAND_DOWN_IMAGE); + Icon expandDownImage = new GIcon("icon.plugin.memorymap.expand.down"); expandDownAction = new MemoryMapAction("Expand Block Down", expandDownImage) { @Override @@ -256,7 +246,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { expandDownAction.setDescription("Expand block by setting new end address"); tool.addLocalAction(this, expandDownAction); - ImageIcon mergeImage = ResourceManager.loadImage(MERGE_IMAGE); + Icon mergeImage = new GIcon("icon.plugin.memorymap.merge"); mergeAction = new MemoryMapAction("Merge Blocks", mergeImage) { @Override public void actionPerformed(ActionContext context) { @@ -269,7 +259,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { mergeAction.setDescription("Merge blocks into a single block"); tool.addLocalAction(this, mergeAction); - ImageIcon deleteImage = ResourceManager.loadImage(DELETE_IMAGE); + Icon deleteImage = new GIcon("icon.plugin.memorymap.delete"); deleteAction = new MemoryMapAction("Delete Block", deleteImage) { @Override public void actionPerformed(ActionContext context) { @@ -282,7 +272,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { deleteAction.setDescription("Delete a block"); tool.addLocalAction(this, deleteAction); - ImageIcon setBaseIcon = ResourceManager.loadImage(IMAGE_BASE); + Icon setBaseIcon = new GIcon("icon.plugin.memorymap.image.base"); setBaseAction = new MemoryMapAction("Set Image Base", setBaseIcon) { @Override public void actionPerformed(ActionContext context) { @@ -687,7 +677,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { } private abstract class MemoryMapAction extends DockingAction { - MemoryMapAction(String name, ImageIcon icon) { + MemoryMapAction(String name, Icon icon) { super(name, plugin.getName()); this.setToolBarData(new ToolBarData(icon, null)); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/FontAdjustPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/FontAdjustPlugin.java new file mode 100644 index 0000000000..af5cc78ffb --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/FontAdjustPlugin.java @@ -0,0 +1,70 @@ +/* ### + * 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.misc; + +import docking.ActionContext; +import docking.ComponentProvider; +import docking.action.builder.ActionBuilder; +import ghidra.app.CorePluginPackage; +import ghidra.app.plugin.PluginCategoryNames; +import ghidra.framework.plugintool.*; +import ghidra.framework.plugintool.util.PluginStatus; + +/** + * Manages the markers to display areas where changes have occurred + */ +@PluginInfo( //@formatter:off + status = PluginStatus.RELEASED, + packageName = CorePluginPackage.NAME, + category = PluginCategoryNames.MISC, + shortDescription = "Provides generic actions for increasing/decreasing fonts.", + description = "This plugin provides actions for increasing fonts used by component providers. "+ + "ComponentProviders can either override the \"changeFontSize()\" method or register a" + + "theme font id that can be automatically adjusted." +) //@formatter:on + +public class FontAdjustPlugin extends Plugin { + public FontAdjustPlugin(PluginTool tool) { + + super(tool); + + new ActionBuilder("Increment Font", "tool") + .keyBinding("ctrl EQUALS") + .onAction(this::incrementFont) + .buildAndInstall(tool); + + new ActionBuilder("Decrement Font", "tool") + .keyBinding("ctrl MINUS") + .onAction(this::decrementFont) + .buildAndInstall(tool); + + } + + private void incrementFont(ActionContext context) { + ComponentProvider provider = context.getComponentProvider(); + if (provider != null) { + provider.adjustFontSize(true); + } + } + + private void decrementFont(ActionContext context) { + ComponentProvider provider = context.getComponentProvider(); + if (provider != null) { + provider.adjustFontSize(false); + } + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java index 24aaf0a191..b375368cf5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java @@ -24,11 +24,13 @@ package ghidra.app.plugin.core.misc; import java.awt.Color; import java.io.IOException; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.ActionContext; import docking.action.DockingAction; import docking.action.ToolBarData; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.ProgramPlugin; @@ -50,7 +52,6 @@ import ghidra.util.task.SwingUpdateManager; import ghidra.util.task.TaskMonitor; import ghidra.util.worker.Job; import ghidra.util.worker.Worker; -import resources.ResourceManager; /** * Manages the markers to display areas where changes have occurred @@ -73,6 +74,15 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma private final static int OTHER_CHANGES_PRIORITY = MarkerService.CHANGE_PRIORITY + 2; private final static int CONFLICT_PRIORITY = MarkerService.CHANGE_PRIORITY + 3; + private static final Color BG_COLOR_MARKER_UNSAVED = + new GColor("color.bg.plugin.myprogramchangesdisplay.markers.changes.unsaved"); + private static final Color BG_COLOR_MARKER_CONFLICTING = + new GColor("color.bg.plugin.myprogramchangesdisplay.markers.changes.conflicting"); + private static final Color BG_COLOR_MARKER_LATEST = + new GColor("color.bg.plugin.myprogramchangesdisplay.markers.changes.latest.version"); + private static final Color BG_COLOR_MARKER_NOT_CHECKED_IN = + new GColor("color.bg.plugin.myprogramchangesdisplay.markers.changes.not.checked.in"); + private MarkerService markerService; private MarkerSet currentMyChangeMarks; // my changes since last save @@ -110,7 +120,7 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma private void createActions() { - ImageIcon icon = ResourceManager.loadImage("images/vcMerge.png"); + Icon icon = new GIcon("icon.plugin.myprogramchanges.merge"); mergeAction = new DockingAction("Update", getName()) { @Override public void actionPerformed(ActionContext context) { @@ -127,7 +137,7 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma mergeAction.setDescription("Update checked out file with latest version"); mergeAction.setHelpLocation(new HelpLocation("VersionControl", mergeAction.getName())); - icon = ResourceManager.loadImage("images/vcCheckIn.png"); + icon = new GIcon("icon.plugin.myprogramchanges.checkin"); checkInAction = new DockingAction("CheckIn", getName()) { @Override public void actionPerformed(ActionContext context) { @@ -191,7 +201,7 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma private void createMarkerSets(Program program) { currentMyChangeMarks = markerService.createAreaMarker("Changes: Unsaved", "My changes not yet saved", program, - MY_CHANGE_PRIORITY, true, true, false, Color.darkGray); + MY_CHANGE_PRIORITY, true, true, false, BG_COLOR_MARKER_UNSAVED); if (program.getDomainFile().isCheckedOut()) { trackServerChanges(program); @@ -201,15 +211,15 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma private void trackServerChanges(Program program) { currentChangesSinceCheckoutMarks = markerService.createAreaMarker("Changes: Not Checked-In", "My saved changes made since I checked it out", program, CHANGES_SINCE_CO_PRIORITY, - true, true, false, Color.GREEN); + true, true, false, BG_COLOR_MARKER_NOT_CHECKED_IN); currentOtherChangeMarks = markerService.createAreaMarker("Changes: Latest Version", "Changes made by others to this program since I checked it out", program, - OTHER_CHANGES_PRIORITY, true, true, false, Color.BLUE); + OTHER_CHANGES_PRIORITY, true, true, false, BG_COLOR_MARKER_LATEST); currentConflictChangeMarks = markerService.createAreaMarker("Changes: Conflicting", "Changes made by others to this program that conflict with my changes", program, - CONFLICT_PRIORITY, true, true, false, Color.RED); + CONFLICT_PRIORITY, true, true, false, BG_COLOR_MARKER_CONFLICTING); } private void disposeMarkerSets(Program program) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/RegisterField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/RegisterField.java index fa4d3f27ab..6431da816b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/RegisterField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/RegisterField.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,61 +23,63 @@ import javax.swing.*; import javax.swing.event.ChangeListener; import javax.swing.text.*; -/** - * - */ +import generic.theme.GThemeDefaults.Colors; + public class RegisterField extends JTextField { -// private static Color UNSET_COLOR = new Color(204,0,204); + private int bitSize; private Long currentValue; private long maxValue; - private PlainDocument doc; + private PlainDocument doc; private boolean inFocus; private boolean skipFilter; private ChangeListener listener; - private Color noValueColor = Color.LIGHT_GRAY; - private Color valueColor = Color.BLACK; - private boolean useNoValue; - /** - * Constructor for RegisterField. - */ - public RegisterField(int bitSize, Long initialValue) { - this(bitSize, initialValue, true); - } - - public RegisterField(int bitSize, Long initialValue, boolean useNoValue) { - this.useNoValue = useNoValue; - setBitSize( bitSize ); - - doc = new PlainDocument(); - doc.setDocumentFilter(new MyDocFilter()); - this.setDocument(doc); - doSetValue(initialValue); + private Color noValueColor = Colors.FOREGROUND_DISABLED; + private Color valueColor = Colors.FOREGROUND; + private boolean useNoValue; - this.addFocusListener(new FocusListener() { - public void focusGained(FocusEvent ev) { + public RegisterField(int bitSize, Long initialValue) { + this(bitSize, initialValue, true); + } + + public RegisterField(int bitSize, Long initialValue, boolean useNoValue) { + this.useNoValue = useNoValue; + setBitSize(bitSize); + + doc = new PlainDocument(); + doc.setDocumentFilter(new MyDocFilter()); + this.setDocument(doc); + doSetValue(initialValue); + + this.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent ev) { inFocus = true; doSetValue(currentValue); - } + } - public void focusLost(FocusEvent ev) { - inFocus = false; + @Override + public void focusLost(FocusEvent ev) { + inFocus = false; doSetValue(currentValue); - } - }); - } + } + }); + } + public Long getValue() { return currentValue; } - + public void setNoValueColor(Color c) { noValueColor = c; updateColor(); } + public void setValueColor(Color c) { valueColor = c; updateColor(); } + private void updateColor() { if (inFocus || currentValue != null) { setForeground(valueColor); @@ -89,104 +90,113 @@ public class RegisterField extends JTextField { setHorizontalAlignment(CENTER); } } - public void setBitSize( int bitSize ) { - this.bitSize = bitSize; - boolean isValid = bitSize >= 1 && bitSize < 64; + public void setBitSize(int bitSize) { + this.bitSize = bitSize; - this.setEditable(isValid); - this.setEnabled(isValid); + boolean isValid = bitSize >= 1 && bitSize < 64; - this.useNoValue = true; + this.setEditable(isValid); + this.setEnabled(isValid); - if (isValid) { - this.maxValue = (1L << bitSize) - 1; - } - else { - skipFilter = true; - this.maxValue = 1; - } + this.useNoValue = true; - /// if the value is no longer valid, then clear the value - if ( !isValidValue( getValue() ) ) { - doSetValue( null ); - } - } - public void setValue(Long value) { + if (isValid) { + this.maxValue = (1L << bitSize) - 1; + } + else { + skipFilter = true; + this.maxValue = 1; + } + + /// if the value is no longer valid, then clear the value + if (!isValidValue(getValue())) { + doSetValue(null); + } + } + + public void setValue(Long value) { if (isEqual(value, currentValue)) { return; } doSetValue(value); - } - private void doSetValue(Long value) { - if (value == null) { - if (inFocus) { + } + + private void doSetValue(Long value) { + if (value == null) { + if (inFocus) { setTextField(""); - } - else { - if (useNoValue) { + } + else { + if (useNoValue) { setTextField("-- No Value --"); - } - else { - setTextField(""); - } - } - } - else { - setTextField("0x"+Long.toHexString(value.longValue())); - } - currentValue = value; + } + else { + setTextField(""); + } + } + } + else { + setTextField("0x" + Long.toHexString(value.longValue())); + } + currentValue = value; updateColor(); - } - private boolean isEqual(Long l1, Long l2) { - if (l1 != null) { - return l1.equals(l2); - } - else if (l2 != null) { - return false; - } - return true; - } + } + + private boolean isEqual(Long l1, Long l2) { + if (l1 != null) { + return l1.equals(l2); + } + else if (l2 != null) { + return false; + } + return true; + } + private void setTextField(String text) { - if ( doc == null ) { - return; - } + if (doc == null) { + return; + } skipFilter = true; - try { - doc.replace(0, doc.getLength(), text, null); - } - catch (BadLocationException e) {} + try { + doc.replace(0, doc.getLength(), text, null); + } + catch (BadLocationException e) { + // ignore + } skipFilter = false; } + public void setChangeListener(ChangeListener listener) { this.listener = listener; } + private boolean processText() { String text = getText(); - - if (text.length() == 0){ + + if (text.length() == 0) { if (currentValue != null) { currentValue = null; notifyListeners(); } return true; } - + if (text.equals("0x") || text.equals("0X")) { - if ((currentValue == null) || (currentValue.longValue() != 0)) { - currentValue = new Long(0); + if ((currentValue == null) || (currentValue.longValue() != 0)) { + currentValue = 0L; notifyListeners(); } return true; } try { if (!text.startsWith("0x") && !text.startsWith("0X")) { - while(text.length() > 1 && text.charAt(0)== '0') { + while (text.length() > 1 && text.charAt(0) == '0') { text = text.substring(1); - } + } } - Long newValue = Long.decode(text); - if ( isValidValue( newValue ) ) { + Long newValue = Long.decode(text); + if (isValidValue(newValue)) { if (!newValue.equals(currentValue)) { currentValue = newValue; notifyListeners(); @@ -194,46 +204,42 @@ public class RegisterField extends JTextField { return true; } } - catch(Exception e) { + catch (Exception e) { + // handled by using beep below } + Toolkit.getDefaultToolkit().beep(); return false; } - private boolean isValidValue(Long value) { - if ( value == null ) { - return false; - } - long l = value.longValue(); - return (l >= 0) && (l <= maxValue); - } + private boolean isValidValue(Long value) { + if (value == null) { + return false; + } + long l = value.longValue(); + return (l >= 0) && (l <= maxValue); + } - class MyDocFilter extends DocumentFilter { - /** - * @see javax.swing.text.DocumentFilter#insertString(FilterBypass, int, String, AttributeSet) - */ - @Override - public void insertString(FilterBypass fb, int offset, String string, - AttributeSet attr) throws BadLocationException { + + @Override + public void insertString(FilterBypass fb, int offset, String string, + AttributeSet attr) throws BadLocationException { if (skipFilter) { super.insertString(fb, offset, string, attr); return; } String oldText = getText(); - fb.insertString(offset, string, attr); + fb.insertString(offset, string, attr); if (!processText()) { fb.replace(0, doc.getLength(), oldText, attr); } - } + } - /** - * @see javax.swing.text.DocumentFilter#remove(FilterBypass, int, int) - */ - @Override - public void remove(FilterBypass fb, int offset, int length) - throws BadLocationException { + @Override + public void remove(FilterBypass fb, int offset, int length) + throws BadLocationException { if (skipFilter) { super.remove(fb, offset, length); return; @@ -244,48 +250,45 @@ public class RegisterField extends JTextField { if (!processText()) { fb.replace(0, doc.getLength(), oldText, null); } - } + } - /** - * @see javax.swing.text.DocumentFilter#replace(FilterBypass, int, int, String, AttributeSet) - */ - @Override - public void replace(FilterBypass fb, int offset, int length, - String text, AttributeSet attrs) throws BadLocationException { + @Override + public void replace(FilterBypass fb, int offset, int length, + String text, AttributeSet attrs) throws BadLocationException { if (skipFilter) { super.replace(fb, offset, length, text, attrs); return; } String oldText = getText(); - fb.replace(offset, length, text, attrs); + fb.replace(offset, length, text, attrs); if (!processText()) { fb.replace(0, doc.getLength(), oldText, attrs); } - } - } + } + } public static void main(String[] args) { JFrame f = new JFrame("Test"); JPanel panel = new JPanel(new BorderLayout()); panel.add(new JTextField("123"), BorderLayout.SOUTH); - RegisterField rf = new RegisterField(1, new Long(1)); + RegisterField rf = new RegisterField(1, 1L); panel.add(rf, BorderLayout.CENTER); f.getContentPane().add(panel); f.pack(); f.setVisible(true); - } - + } + private void notifyListeners() { if (listener != null) { - listener.stateChanged( null ); + listener.stateChanged(null); } - } + } + public int getBitSize() { return bitSize; } + public Color getValueColor() { return valueColor; } } - - diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java index c5700ad5d6..f58852193e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java @@ -42,7 +42,7 @@ import resources.*; public abstract class AbstractNextPreviousAction extends NavigatableContextAction { private static final Icon INVERTED_OVERLAY_ICON = - ImageUtils.makeTransparent(ResourceManager.loadImage("images/dialog-cancel.png"), .5f); + ImageUtils.makeTransparent(Icons.NOT_ALLOWED_ICON, .5f); private boolean isForward = true; private PluginTool tool; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextHighlightedRangeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextHighlightedRangeAction.java index 9c2b667386..a178fc9fb4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextHighlightedRangeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextHighlightedRangeAction.java @@ -20,6 +20,7 @@ import java.awt.event.KeyEvent; import docking.DockingUtils; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.context.ProgramLocationActionContext; import ghidra.app.nav.NextRangeAction; import ghidra.app.plugin.PluginCategoryNames; @@ -27,19 +28,20 @@ import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.PluginTool; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class NextHighlightedRangeAction extends NextRangeAction { + private static final GIcon ICON = new GIcon("icon.plugin.navigation.highlight.range.next"); + public NextHighlightedRangeAction(PluginTool tool, String owner, NavigationOptions navOptions) { super(tool, "Next Highlighted Range", owner, navOptions); setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, - "Next Highlight Range" }, ResourceManager.loadImage("images/NextHighlightBlock16.gif"), + "Next Highlight Range" }, ICON, PluginCategoryNames.NAVIGATION, MenuData.NO_MNEMONIC, NextPrevHighlightRangePlugin.ACTION_SUB_GROUP)); setToolBarData(new ToolBarData( - ResourceManager.loadImage("images/NextHighlightBlock16.gif"), + ICON, ToolConstants.TOOLBAR_GROUP_THREE, NextPrevHighlightRangePlugin.ACTION_SUB_GROUP)); setKeyBindingData( new KeyBindingData(KeyEvent.VK_0, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java index 9830bc6ba9..2745dfcb4b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java @@ -21,12 +21,12 @@ import java.util.ArrayList; import java.util.List; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.ActionContext; import docking.action.*; import docking.menu.MultiActionDockingAction; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.ProgramActionContext; @@ -46,7 +46,6 @@ import ghidra.program.model.listing.*; import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.SymbolTable; import ghidra.util.HelpLocation; -import resources.ResourceManager; /** * NextPrevAddressPluginallows the user to go back and forth in @@ -65,8 +64,8 @@ import resources.ResourceManager; public class NextPrevAddressPlugin extends Plugin { private static final String HISTORY_MENU_GROUP = "1_Menu_History_Group"; - private static ImageIcon previousIcon = ResourceManager.loadImage("images/left.png"); - private static ImageIcon nextIcon = ResourceManager.loadImage("images/right.png"); + private static Icon PREVIOUS_ICON = new GIcon("icon.plugin.navigation.location.previous"); + private static Icon NEXT_ICON = new GIcon("icon.plugin.navigation.location.next"); private static final String PREVIOUS_ACTION_NAME = "Previous Location in History"; private static final String NEXT_ACTION_NAME = "Next Location in History"; @@ -301,7 +300,7 @@ public class NextPrevAddressPlugin extends Plugin { super(name, owner); this.isNext = isNext; - setToolBarData(new ToolBarData(isNext ? nextIcon : previousIcon, + setToolBarData(new ToolBarData(isNext ? NEXT_ICON : PREVIOUS_ICON, ToolConstants.TOOLBAR_GROUP_TWO)); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name)); int keycode = isNext ? KeyEvent.VK_RIGHT : KeyEvent.VK_LEFT; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java index f136f996ac..424da1777d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java @@ -23,6 +23,7 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import generic.util.image.ImageUtils; import ghidra.app.CorePluginPackage; import ghidra.app.context.NavigatableActionContext; @@ -33,7 +34,7 @@ import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.util.PluginStatus; import ghidra.util.HelpLocation; -import resources.ResourceManager; +import resources.Icons; /** * The NextPrevCodeUnitPlugin generates a GoTo event based on where the cursor @@ -135,9 +136,9 @@ public class NextPrevCodeUnitPlugin extends Plugin { private class InvertStateAction extends ToggleDockingAction { private final Icon INVERTED_ICON_OFF = ImageUtils.makeTransparent( - ResourceManager.loadImage("images/dialog-cancel.png")); + Icons.NOT_ALLOWED_ICON); private final Icon INVERTED_ICON_ON = ImageUtils.makeTransparent( - ResourceManager.loadImage("images/dialog-cancel.png"), .8f); + Icons.NOT_ALLOWED_ICON, .8f); private boolean isInverted = false; public InvertStateAction(String subGroup) { @@ -146,10 +147,7 @@ public class NextPrevCodeUnitPlugin extends Plugin { setToolBarData(new ToolBarData(INVERTED_ICON_OFF, ToolConstants.TOOLBAR_GROUP_FOUR, subGroup)); - // TODO add help entry setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName())); - - // TODO setDescriptoin("..."); setSelected(false); addToWindowWhen(NavigatableActionContext.class); @@ -169,8 +167,8 @@ public class NextPrevCodeUnitPlugin extends Plugin { } private class ToggleDirectionAction extends NavigatableContextAction { - private final Icon FORWARD_ICON = ResourceManager.loadImage("images/down.png"); - private final Icon BACKWARD_ICON = ResourceManager.loadImage("images/up.png"); + private final Icon FORWARD_ICON = new GIcon("icon.down"); + private final Icon BACKWARD_ICON = new GIcon("icon.up"); private boolean isForward = true; ToggleDirectionAction(String subGroup) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java index c72345c884..d002ecc7dc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java @@ -18,7 +18,8 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.*; import java.util.Iterator; -import javax.swing.*; +import javax.swing.Icon; +import javax.swing.KeyStroke; import docking.ActionContext; import docking.action.*; @@ -26,6 +27,7 @@ import docking.menu.ActionState; import docking.menu.MultiStateDockingAction; import docking.tool.ToolConstants; import docking.widgets.EventTrigger; +import generic.theme.GIcon; import generic.util.image.ImageUtils; import ghidra.app.context.ListingActionContext; import ghidra.app.context.NavigatableActionContext; @@ -45,26 +47,21 @@ public class NextPreviousBookmarkAction extends MultiStateDockingActionpublic static final String ALL_BOOKMARK_TYPES = "All Bookmark Types"; private static final Icon INVERTED_OVERLAY_ICON = - ImageUtils.makeTransparent(ResourceManager.loadImage("images/dialog-cancel.png"), .5f); + ImageUtils.makeTransparent(Icons.NOT_ALLOWED_ICON, .5f); private PluginTool tool; private boolean isForward = true; private boolean isInverted; - private static final ImageIcon BOOKMARK_ICON = ResourceManager.getScaledIcon( - ResourceManager.loadImage("images/B.gif"), 16, 16); - private static final ImageIcon BOOKMARK_ANALYSIS_ICON = - ResourceManager.loadImage("images/applications-system.png"); - private static final ImageIcon BOOKMARK_ERROR_ICON = - ResourceManager.loadImage("images/edit-delete.png"); - private static final ImageIcon BOOKMARK_INFO_ICON = - ResourceManager.loadImage("images/information.png"); - private static final ImageIcon BOOKMARK_NOTE_ICON = - ResourceManager.loadImage("images/notes.gif"); - private static final ImageIcon BOOKMARK_WARNING_ICON = - ResourceManager.loadImage("images/warning.png"); - private static final ImageIcon BOOKMARK_UNKNOWN_ICON = - ResourceManager.loadImage("images/unknown.gif"); + //@formatter:off + private static final Icon BOOKMARK_ICON = new GIcon("icon.plugin.navigation.bookmark"); + private static final Icon BOOKMARK_ANALYSIS_ICON = new GIcon("icon.plugin.navigation.bookmark.analysis"); + private static final Icon BOOKMARK_ERROR_ICON = new GIcon("icon.plugin.navigation.bookmark.error"); + private static final Icon BOOKMARK_INFO_ICON = new GIcon("icon.plugin.navigation.bookmark.info"); + private static final Icon BOOKMARK_NOTE_ICON = new GIcon("icon.plugin.navigation.bookmark.note"); + private static final Icon BOOKMARK_WARNING_ICON = new GIcon("icon.plugin.navigation.bookmark.warning"); + private static final Icon BOOKMARK_UNKNOWN_ICON = new GIcon("icon.plugin.navigation.bookmark.unknown"); + //@formatter:on public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) { super("Next Bookmark", owner); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousDefinedDataAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousDefinedDataAction.java index 9e3a4214c2..112fa274f4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousDefinedDataAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousDefinedDataAction.java @@ -21,15 +21,17 @@ import java.awt.event.KeyEvent; import javax.swing.Icon; import javax.swing.KeyStroke; +import generic.theme.GIcon; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.Address; import ghidra.program.model.listing.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.data"); + public NextPreviousDefinedDataAction(PluginTool tool, String owner, String subGroup) { super(tool, "Next Data", owner, subGroup); } @@ -41,7 +43,7 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction { @Override protected Icon getIcon() { - return ResourceManager.loadImage("images/D.gif"); + return ICON; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousFunctionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousFunctionAction.java index 05ab11ae15..208785c82a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousFunctionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousFunctionAction.java @@ -21,6 +21,7 @@ import java.awt.event.KeyEvent; import javax.swing.Icon; import javax.swing.KeyStroke; +import generic.theme.GIcon; import ghidra.app.nav.Navigatable; import ghidra.app.services.GoToService; import ghidra.framework.plugintool.PluginTool; @@ -30,17 +31,18 @@ import ghidra.program.model.listing.*; import ghidra.program.util.FunctionSignatureFieldLocation; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class NextPreviousFunctionAction extends AbstractNextPreviousAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.function"); + public NextPreviousFunctionAction(PluginTool tool, String owner, String subGroup) { super(tool, "Next Function", owner, subGroup); } @Override protected Icon getIcon() { - return ResourceManager.loadImage("images/F.gif"); + return ICON; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousInstructionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousInstructionAction.java index 62149fd9a1..cdae9cdaef 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousInstructionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousInstructionAction.java @@ -21,22 +21,24 @@ import java.awt.event.KeyEvent; import javax.swing.Icon; import javax.swing.KeyStroke; +import generic.theme.GIcon; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.Address; import ghidra.program.model.listing.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class NextPreviousInstructionAction extends AbstractNextPreviousAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.instruction"); + public NextPreviousInstructionAction(PluginTool tool, String owner, String subGroup) { super(tool, "Next Instruction", owner, subGroup); } @Override protected Icon getIcon() { - return ResourceManager.loadImage("images/I.gif"); + return ICON; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousLabelAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousLabelAction.java index e73bc6233b..975287a9c7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousLabelAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousLabelAction.java @@ -21,6 +21,7 @@ import java.awt.event.KeyEvent; import javax.swing.Icon; import javax.swing.KeyStroke; +import generic.theme.GIcon; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressIterator; @@ -28,17 +29,18 @@ import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class NextPreviousLabelAction extends AbstractNextPreviousAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.label"); + public NextPreviousLabelAction(PluginTool tool, String owner, String subGroup) { super(tool, "Next Label", owner, subGroup); } @Override protected Icon getIcon() { - return ResourceManager.loadImage("images/L.gif"); + return ICON; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousSameBytesAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousSameBytesAction.java index 366dd942bc..0aced61f54 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousSameBytesAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousSameBytesAction.java @@ -22,6 +22,7 @@ import java.util.Iterator; import javax.swing.Icon; import javax.swing.KeyStroke; +import generic.theme.GIcon; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; @@ -33,7 +34,6 @@ import ghidra.util.Msg; import ghidra.util.exception.AssertException; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * Navigates to the same byte pattern value under the current code unit. When negated, the search @@ -42,7 +42,7 @@ import resources.ResourceManager; */ public class NextPreviousSameBytesAction extends AbstractNextPreviousAction { - private static final Icon ICON = ResourceManager.loadImage("images/V.png"); + private static final Icon ICON = new GIcon("icon.plugin.navigation.bytes"); NextPreviousSameBytesAction(PluginTool tool, String owner, String subGroup) { super(tool, "Next Matching Byte Values", owner, subGroup); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousUndefinedAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousUndefinedAction.java index c2c0f5793b..67733e7cfe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousUndefinedAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousUndefinedAction.java @@ -21,22 +21,24 @@ import java.awt.event.KeyEvent; import javax.swing.Icon; import javax.swing.KeyStroke; +import generic.theme.GIcon; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.Address; import ghidra.program.model.listing.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class NextPreviousUndefinedAction extends AbstractNextPreviousAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.undefined"); + public NextPreviousUndefinedAction(PluginTool tool, String owner, String subGroup) { super(tool, "Next Undefined", owner, subGroup); } @Override protected Icon getIcon() { - return ResourceManager.loadImage("images/U.gif"); + return ICON; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextSelectedRangeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextSelectedRangeAction.java index 2bc0c9e7fb..ac32d83bed 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextSelectedRangeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextSelectedRangeAction.java @@ -18,9 +18,12 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import javax.swing.Icon; + import docking.DockingUtils; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.context.ProgramLocationActionContext; import ghidra.app.nav.NextRangeAction; import ghidra.app.plugin.PluginCategoryNames; @@ -28,21 +31,22 @@ import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.PluginTool; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class NextSelectedRangeAction extends NextRangeAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.selection.range.next"); + public NextSelectedRangeAction(PluginTool tool, String ownerName, NavigationOptions navOptions) { super(tool, "Next Selected Range", ownerName, navOptions); setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, - "Next Selected Range" }, ResourceManager.loadImage("images/NextSelectionBlock16.gif"), + "Next Selected Range" }, ICON, PluginCategoryNames.NAVIGATION, MenuData.NO_MNEMONIC, NextPrevSelectedRangePlugin.ACTION_SUB_GROUP)); setToolBarData(new ToolBarData( - ResourceManager.loadImage("images/NextSelectionBlock16.gif"), + ICON, ToolConstants.TOOLBAR_GROUP_THREE, NextPrevSelectedRangePlugin.ACTION_SUB_GROUP)); setKeyBindingData( new KeyBindingData(KeyEvent.VK_OPEN_BRACKET, DockingUtils.CONTROL_KEY_MODIFIER_MASK | diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousHighlightedRangeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousHighlightedRangeAction.java index f83cadee78..2ead540e82 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousHighlightedRangeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousHighlightedRangeAction.java @@ -17,9 +17,12 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.KeyEvent; +import javax.swing.Icon; + import docking.DockingUtils; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.context.ProgramLocationActionContext; import ghidra.app.nav.PreviousRangeAction; import ghidra.app.plugin.PluginCategoryNames; @@ -27,21 +30,22 @@ import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.PluginTool; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class PreviousHighlightedRangeAction extends PreviousRangeAction { + private static final Icon ICON = new GIcon("icon.plugin.navigation.highlight.range.previous"); + public PreviousHighlightedRangeAction(PluginTool tool, String owner, NavigationOptions navOptions) { super(tool, "Previous Highlighted Range", owner, navOptions); setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, "Previous Highlight Range" }, - ResourceManager.loadImage("images/PreviousHighlightBlock16.gif"), + ICON, PluginCategoryNames.NAVIGATION, MenuData.NO_MNEMONIC, NextPrevHighlightRangePlugin.ACTION_SUB_GROUP)); setToolBarData(new ToolBarData( - ResourceManager.loadImage("images/PreviousHighlightBlock16.gif"), + ICON, ToolConstants.TOOLBAR_GROUP_THREE, NextPrevHighlightRangePlugin.ACTION_SUB_GROUP)); setKeyBindingData( new KeyBindingData(KeyEvent.VK_9, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousSelectedRangeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousSelectedRangeAction.java index 7ef4a1ad07..9aa8c0c341 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousSelectedRangeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/PreviousSelectedRangeAction.java @@ -18,11 +18,12 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.DockingUtils; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.context.ProgramLocationActionContext; import ghidra.app.nav.PreviousRangeAction; import ghidra.app.plugin.PluginCategoryNames; @@ -30,20 +31,20 @@ import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.PluginTool; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class PreviousSelectedRangeAction extends PreviousRangeAction { + private Icon ICON = new GIcon("icon.plugin.navigation.selection.range.previous"); + public PreviousSelectedRangeAction(PluginTool tool, String ownerName, NavigationOptions navOptions) { super(tool, "Previous Selected Range", ownerName, navOptions); - ImageIcon icon = ResourceManager.loadImage("images/PreviousSelectionBlock16.gif"); setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, - "Previous Selected Range" }, icon, PluginCategoryNames.NAVIGATION, + "Previous Selected Range" }, ICON, PluginCategoryNames.NAVIGATION, MenuData.NO_MNEMONIC, NextPrevSelectedRangePlugin.ACTION_SUB_GROUP)); - setToolBarData(new ToolBarData(icon, ToolConstants.TOOLBAR_GROUP_THREE, + setToolBarData(new ToolBarData(ICON, ToolConstants.TOOLBAR_GROUP_THREE, NextPrevSelectedRangePlugin.ACTION_SUB_GROUP)); setKeyBindingData( new KeyBindingData(KeyEvent.VK_CLOSE_BRACKET, DockingUtils.CONTROL_KEY_MODIFIER_MASK | diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesHighlighter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesHighlighter.java index 50e0090637..db1fd6dd2c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesHighlighter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesHighlighter.java @@ -18,6 +18,7 @@ package ghidra.app.plugin.core.navigation.locationreferences; import java.awt.Color; import docking.widgets.fieldpanel.support.Highlight; +import generic.theme.GColor; import ghidra.GhidraOptions; import ghidra.app.nav.Navigatable; import ghidra.app.services.*; @@ -42,7 +43,8 @@ class LocationReferencesHighlighter { "Reference Search" + GhidraOptions.DELIMITER + "Highlight Match Color"; private static final String HIGHLIGHT_COLOR_DESCRIPTION = "The highlight color of matches for the 'Show References' searcher"; - private static Color DEFAULT_HIGHLIGHT_COLOR = new Color(168, 202, 242); + private static GColor DEFAULT_HIGHLIGHT_COLOR = + new GColor("color.bg.plugin.locationreferences.highlight"); private boolean isHighlighting = false; private final Navigatable navigatable; @@ -52,13 +54,9 @@ class LocationReferencesHighlighter { private HighlightProvider highlightProvider; private MarkerRemover markerRemover; private Color highlightColor; - private OptionsChangeListener optionsListener = new OptionsChangeListener() { - @Override - public void optionsChanged(ToolOptions options, String name, Object oldValue, - Object newValue) { - if (name.equals(HIGHLIGHT_COLOR_KEY)) { - highlightColor = (Color) newValue; - } + private OptionsChangeListener optionsListener = (options, name, oldValue, newValue) -> { + if (name.equals(HIGHLIGHT_COLOR_KEY)) { + highlightColor = (Color) newValue; } }; @@ -67,7 +65,7 @@ class LocationReferencesHighlighter { // tool until a search has happened, which is odd. static void registerHighlighterOptions(LocationReferencesPlugin plugin) { ToolOptions options = plugin.getTool().getOptions(OPTIONS_TITLE); - options.registerOption(HIGHLIGHT_COLOR_KEY, DEFAULT_HIGHLIGHT_COLOR, + options.registerThemeColorBinding(HIGHLIGHT_COLOR_KEY, DEFAULT_HIGHLIGHT_COLOR.getId(), plugin.getHelpLocation(), HIGHLIGHT_COLOR_DESCRIPTION); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesProvider.java index 6422fbdebf..911b1c1893 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesProvider.java @@ -25,6 +25,7 @@ import javax.swing.event.ChangeListener; import docking.ActionContext; import docking.action.*; import docking.widgets.table.GTable; +import generic.theme.GIcon; import ghidra.app.nav.Navigatable; import ghidra.app.nav.NavigatableRemovalListener; import ghidra.app.services.GoToService; @@ -51,8 +52,8 @@ import resources.ResourceManager; public class LocationReferencesProvider extends ComponentProviderAdapter implements DomainObjectListener, NavigatableRemovalListener { - private static Icon HIGHLIGHT_ICON = ResourceManager.loadImage("images/tag_yellow.png"); - private static Icon HOME_ICON = ResourceManager.loadImage("images/go-home.png"); + private static Icon HIGHLIGHT_ICON = new GIcon("icon.plugin.locationreferences.highlight"); + private static Icon HOME_ICON = Icons.HOME_ICON; private static Icon REFRESH_ICON = Icons.REFRESH_ICON; private static Icon REFRESH_NOT_NEEDED_ICON = ResourceManager.getDisabledIcon(Icons.REFRESH_ICON, 60); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesTableModel.java index 3f77196d72..671955bdab 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesTableModel.java @@ -15,13 +15,13 @@ */ package ghidra.app.plugin.core.navigation.locationreferences; -import java.awt.Color; import java.awt.Component; import java.util.*; import org.apache.commons.lang3.StringUtils; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GThemeDefaults.Colors.Tables; import ghidra.docking.settings.Settings; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; @@ -171,7 +171,7 @@ class LocationReferencesTableModel extends AddressBasedTableModel showAddBundlesFileChooser()) .buildAndInstallLocal(this); - icon = ResourceManager.loadImage("images/edit-delete.png"); + icon = Icons.DELETE_ICON; new ActionBuilder("RemoveBundles", this.getName()) .popupMenuPath("Remove selected bundle(s)") .popupMenuIcon(icon) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusTableModel.java index 7f7a957baa..d30d509af6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleStatusTableModel.java @@ -15,9 +15,9 @@ */ package ghidra.app.plugin.core.osgi; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; import java.util.*; -import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -29,6 +29,7 @@ import org.osgi.framework.Bundle; import docking.widgets.table.*; import generic.jar.ResourceFile; +import generic.theme.GColor; import generic.util.Path; import ghidra.docking.settings.Settings; import ghidra.framework.plugintool.ServiceProvider; @@ -42,11 +43,14 @@ import ghidra.util.table.column.GColumnRenderer; */ public class BundleStatusTableModel extends GDynamicColumnTableModel > { - private static final Color COLOR_BUNDLE_ERROR = Color.RED; - private static final Color COLOR_BUNDLE_DISABLED = Color.DARK_GRAY; - private static final Color COLOR_BUNDLE_BUSY = Color.GRAY; - private static final Color COLOR_BUNDLE_INACTIVE = Color.BLACK; - private static final Color COLOR_BUNDLE_ACTIVE = new Color(0.0f, .6f, 0.0f); // a dark green + + //@formatter:off + private static final Color COLOR_BUNDLE_ERROR = new GColor("color.fg.error"); + private static final Color COLOR_BUNDLE_DISABLED = new GColor("color.fg.table.bundle.disabled"); + private static final Color COLOR_BUNDLE_BUSY = new GColor("color.fg.table.bundle.busy"); + private static final Color COLOR_BUNDLE_INACTIVE = new GColor("color.fg.table.bundle.inactive"); + private static final Color COLOR_BUNDLE_ACTIVE = new GColor("color.fg.table.bundle.active"); + //@formatter:on private BundleHost bundleHost; private BundleStatusComponentProvider provider; @@ -146,8 +150,6 @@ public class BundleStatusTableModel }); } - /***************************************************/ - @Override public boolean isCellEditable(int rowIndex, int columnIndex) { BundleStatus status = statuses.get(rowIndex); @@ -553,7 +555,6 @@ public class BundleStatusTableModel BundleStatus status = (BundleStatus) data.getRowObject(); ResourceFile file = (ResourceFile) data.getValue(); JLabel label = (JLabel) super.getTableCellRendererComponent(data); - label.setFont(defaultFont.deriveFont(defaultFont.getStyle() | Font.BOLD)); label.setText(Path.toPathString(file)); GhidraBundle bundle = bundleHost.getGhidraBundle(file); if (bundle == null || bundle instanceof GhidraPlaceholderBundle || !file.exists()) { @@ -573,6 +574,7 @@ public class BundleStatusTableModel label.setForeground(COLOR_BUNDLE_INACTIVE); } } + return label; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorComponent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorComponent.java index 5cd4bb09ef..3f89bba1cb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorComponent.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorComponent.java @@ -25,6 +25,7 @@ import java.util.List; import javax.swing.*; import docking.action.DockingActionIf; +import generic.theme.GColor; import ghidra.app.nav.Navigatable; import ghidra.app.services.GoToService; import ghidra.app.util.viewer.listingpanel.OverviewProvider; @@ -40,7 +41,7 @@ import help.Help; * Uses an {@link OverviewColorService} to get the appropriate color for an address. */ public class OverviewColorComponent extends JPanel implements OverviewProvider { - private static final Color DEFAULT_COLOR = Color.GRAY; + private static final Color DEFAULT_COLOR = new GColor("color.bg.plugin.overview.defalt"); private OverviewColorService service; private Color[] colors = new Color[0]; private final SwingUpdateManager refreshUpdater = @@ -158,7 +159,7 @@ public class OverviewColorComponent extends JPanel implements OverviewProvider { } BigInteger indexCount = map.getIndexCount(); if (indexCount.equals(BigInteger.ZERO)) { - Arrays.fill(colors, Color.GRAY); + Arrays.fill(colors, DEFAULT_COLOR); repaint(); return; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorPlugin.java index c4b89cfbe5..b334936956 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/OverviewColorPlugin.java @@ -23,6 +23,7 @@ import javax.swing.SwingUtilities; import docking.ActionContext; import docking.action.*; import docking.menu.MultiActionDockingAction; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.ProgramPlugin; @@ -35,7 +36,6 @@ import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.classfinder.ClassSearcher; -import resources.ResourceManager; /** * Plugin to manage {@link OverviewColorService}s. It creates actions for each service and installs @@ -132,7 +132,7 @@ public class OverviewColorPlugin extends ProgramPlugin { multiAction = new MultiActionDockingAction("Overview", getName()); multiAction.setActions(new ArrayList (actionMap.values())); multiAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/x-office-document-template.png"))); + new ToolBarData(new GIcon("icon.plugin.overview.provider"))); codeViewerService.addLocalAction(multiAction); multiAction.setDescription("Toggles overview margin displays."); multiAction.setHelpLocation( diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/addresstype/AddressTypeOverviewColorService.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/addresstype/AddressTypeOverviewColorService.java index 9817106f1f..26b590edeb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/addresstype/AddressTypeOverviewColorService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/addresstype/AddressTypeOverviewColorService.java @@ -22,6 +22,7 @@ import java.util.List; import docking.ActionContext; import docking.DialogComponentProvider; import docking.action.DockingActionIf; +import generic.theme.GColor; import ghidra.app.plugin.core.overview.*; import ghidra.framework.model.*; import ghidra.framework.options.OptionsChangeListener; @@ -44,13 +45,18 @@ import ghidra.util.HelpLocation; public class AddressTypeOverviewColorService implements OverviewColorService, OptionsChangeListener, DomainObjectListener { private static final String OPTIONS_NAME = "Overview"; - private static final Color DEFAULT_INSTRUCTION_COLOR = new Color(192, 192, 255); - private static final Color DEFAULT_DATA_COLOR = new Color(128, 255, 128); - private static final Color DEFAULT_FUNCTION_COLOR = new Color(204, 150, 255); - private static final Color DEFAULT_UNDEFINED_COLOR = new Color(255, 51, 102); - private static final Color DEFAULT_UNINITIALIZED_COLOR = Color.BLACK; - private static final Color DEFAULT_EXTERNAL_REF_COLOR = new Color(255, 150, 150); - private static final Color DEFAULT_MARKER_COLOR = Color.WHITE; + private static final GColor DEFAULT_INSTRUCTION_COLOR = + new GColor("color.bg.plugin.overview.address.instruction"); + private static final GColor DEFAULT_DATA_COLOR = + new GColor("color.bg.plugin.overview.address.data"); + private static final GColor DEFAULT_FUNCTION_COLOR = + new GColor("color.bg.plugin.overview.address.function"); + private static final GColor DEFAULT_UNDEFINED_COLOR = + new GColor("color.bg.plugin.overview.address.undefined"); + private static final GColor DEFAULT_UNINITIALIZED_COLOR = + new GColor("color.bg.plugin.overview.address.uninitialized"); + private static final GColor DEFAULT_EXTERNAL_REF_COLOR = + new GColor("color.bg.plugin.overview.address.external.ref"); Color instructionColor = DEFAULT_INSTRUCTION_COLOR; Color dataColor = DEFAULT_DATA_COLOR; @@ -274,16 +280,20 @@ public class AddressTypeOverviewColorService ToolOptions options = tool.getOptions(OPTIONS_NAME); HelpLocation help = new HelpLocation(OverviewColorPlugin.HELP_TOPIC, "OverviewOptions"); - options.registerOption("Instruction Color", DEFAULT_INSTRUCTION_COLOR, help, + options.registerThemeColorBinding("Instruction Color", DEFAULT_INSTRUCTION_COLOR.getId(), + help, "Color for instructions"); - options.registerOption("Data Color", DEFAULT_DATA_COLOR, help, "Color for data"); - options.registerOption("Function Color", DEFAULT_FUNCTION_COLOR, help, + options.registerThemeColorBinding("Data Color", DEFAULT_DATA_COLOR.getId(), help, + "Color for data"); + options.registerThemeColorBinding("Function Color", DEFAULT_FUNCTION_COLOR.getId(), help, "Color for functions"); - options.registerOption("Undefined Color", DEFAULT_UNDEFINED_COLOR, help, + options.registerThemeColorBinding("Undefined Color", DEFAULT_UNDEFINED_COLOR.getId(), help, "Color for undefined bytes"); - options.registerOption("Uninitialized Color", DEFAULT_UNINITIALIZED_COLOR, help, + options.registerThemeColorBinding("Uninitialized Color", + DEFAULT_UNINITIALIZED_COLOR.getId(), help, "Color for uninitialize memory"); - options.registerOption("External Reference Color", DEFAULT_EXTERNAL_REF_COLOR, help, + options.registerThemeColorBinding("External Reference Color", + DEFAULT_EXTERNAL_REF_COLOR.getId(), help, "Color for external references"); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewColorService.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewColorService.java index 16d2b5d6f8..ff26592b01 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewColorService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewColorService.java @@ -42,7 +42,7 @@ public class EntropyOverviewColorService implements OverviewColorService { private byte[] chunkBuffer; private double[] logtable; private int[] histogram = new int[256]; - private Palette palette; + private OverviewPalette palette; private EntropyOverviewOptionsManager entropyOptionsManager; private OverviewColorComponent overviewComponent; private OverviewColorLegendDialog legendDialog; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewOptionsManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewOptionsManager.java index cdb0a1bb80..7ee5058bcc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewOptionsManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/EntropyOverviewOptionsManager.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.overview.entropy; import java.awt.Color; +import generic.theme.GColor; import ghidra.app.plugin.core.overview.OverviewColorPlugin; import ghidra.framework.options.OptionsChangeListener; import ghidra.framework.options.ToolOptions; @@ -28,46 +29,53 @@ import ghidra.util.HelpLocation; * the color Palette for that service. */ public class EntropyOverviewOptionsManager implements OptionsChangeListener { - private static final Color uninitializedColor = Color.decode("0x0000ff"); + private static final Color UNINITIALIZED_COLOR = + new GColor("color.bg.plugin.overview.entropy.uninitialized"); private static final String OPTIONS_NAME = "Entropy"; - private final static String CHUNKSIZE_STRING = "Chunk size"; - private final static String CHUNKSIZE_DESC_STRING = "Number of bytes per entropy score"; - private final static EntropyChunkSize chunksize_def = EntropyChunkSize.LARGE; - private final static String KNOT_COLOR_STRING = + private static final String CHUNKSIZE_STRING = "Chunk size"; + private static final String CHUNKSIZE_DESC_STRING = "Number of bytes per entropy score"; + private static final EntropyChunkSize CHUNKSIZE_DEF = EntropyChunkSize.LARGE; + private static final String KNOT_COLOR_STRING = "Color to use for highlighting a specific range of entropy values"; - private final static String KNOT_TYPE_STRING = "Type of range to highlight"; - private final static String KNOT1_COLOR_STRING = "Range 1 color"; - private final static String KNOT1_TYPE_STRING = "Entropy Range 1"; - private final static Color knot1_def_color = Color.decode("0xff0000"); - private final static EntropyKnot knot1_def_type = EntropyKnot.COMPRESSED; - private final static String KNOT2_COLOR_STRING = "Range 2 color"; - private final static String KNOT2_TYPE_STRING = "Entropy Range 2"; - private final static Color knot2_def_color = Color.decode("0x0000ff"); - private final static EntropyKnot knot2_def_type = EntropyKnot.X86; - private final static String KNOT3_COLOR_STRING = "Range 3 color"; - private final static String KNOT3_TYPE_STRING = "Entropy Range 3"; - private final static Color knot3_def_color = Color.decode("0x00ff00"); - private final static EntropyKnot knot3_def_type = EntropyKnot.ASCII; - private final static String KNOT4_COLOR_STRING = "Range 4 color"; - private final static String KNOT4_TYPE_STRING = "Entropy Range 4"; - private final static Color knot4_def_color = Color.decode("0xffff00"); - private final static EntropyKnot knot4_def_type = EntropyKnot.UTF16; - private final static String KNOT5_COLOR_STRING = "Range 5 color"; - private final static String KNOT5_TYPE_STRING = "Entropy Range 5"; - private final static Color knot5_def_color = Color.decode("0x0000ff"); - private final static EntropyKnot knot5_def_type = EntropyKnot.NONE; + private static final String KNOT_TYPE_STRING = "Type of range to highlight"; + + private static final String KNOT1_COLOR_OPTION_NAME = "Range 1 color"; + private static final String KNOT1_TYPE_OPTION_NAME = "Entropy Range 1"; + private static final GColor KNOT1_COLOR = new GColor("color.bg.plugin.overview.entropy.knot.1"); + private static final EntropyKnot KNOT1_DEF_TYPE = EntropyKnot.COMPRESSED; + + private static final String KNOT2_COLOR_OPTION_NAME = "Range 2 color"; + private static final String KNOT2_TYPE_OPTION_NAME = "Entropy Range 2"; + private static final GColor KNOT2_COLOR = new GColor("color.bg.plugin.overview.entropy.knot.2"); + private static final EntropyKnot KNOT2_DEF_TYPE = EntropyKnot.X86; + + private static final String KNOT3_COLOR_OPTION_NAME = "Range 3 color"; + private static final String KNOT3_TYPE_OPTION_NAME = "Entropy Range 3"; + private static final GColor KNOT3_COLOR = new GColor("color.bg.plugin.overview.entropy.knot.3"); + private static final EntropyKnot KNOT3_DEF_TYPE = EntropyKnot.ASCII; + + private static final String KNOT4_COLOR_OPTION_NAME = "Range 4 color"; + private static final String KNOT4_TYPE_OPTION_NAME = "Entropy Range 4"; + private static final GColor KNOT4_COLOR = new GColor("color.bg.plugin.overview.entropy.knot.4"); + private static final EntropyKnot KNOT4_DEF_TYPE = EntropyKnot.UTF16; + + private static final String KNOT5_COLOR_OPTION_NAME = "Range 5 color"; + private static final String KNOT5_TYPE_OPTION_NAME = "Entropy Range 5"; + private static final GColor KNOT5_COLOR = new GColor("color.bg.plugin.overview.entropy.knot.5"); + private static final EntropyKnot KNOT5_DEF_TYPE = EntropyKnot.NONE; + + private static final GColor PALETTE_COLOR_HIGH = + new GColor("color.bg.plugin.overview.entropy.palette.base.high"); + private static final GColor PALETTE_COLOR_LOW = + new GColor("color.bg.plugin.overview.entropy.palette.base.low"); + private EntropyChunkSize chunksize; - private Color knot1color; private EntropyKnot knot1type; - private Color knot2color; private EntropyKnot knot2type; - private Color knot3color; private EntropyKnot knot3type; - private Color knot4color; private EntropyKnot knot4type; - private Color knot5color; private EntropyKnot knot5type; - private Palette palette = new Palette(256, uninitializedColor); + private OverviewPalette palette = new OverviewPalette(256, UNINITIALIZED_COLOR); private EntropyOverviewColorService service; public EntropyOverviewOptionsManager(PluginTool tool, EntropyOverviewColorService service) { @@ -78,18 +86,23 @@ public class EntropyOverviewOptionsManager implements OptionsChangeListener { options.addOptionsChangeListener(this); options.setOptionsHelpLocation(help); - options.registerOption(CHUNKSIZE_STRING, chunksize_def, help, CHUNKSIZE_DESC_STRING); - options.registerOption(KNOT1_COLOR_STRING, knot1_def_color, help, KNOT_COLOR_STRING); - options.registerOption(KNOT2_COLOR_STRING, knot2_def_color, help, KNOT_COLOR_STRING); - options.registerOption(KNOT3_COLOR_STRING, knot3_def_color, help, KNOT_COLOR_STRING); - options.registerOption(KNOT4_COLOR_STRING, knot4_def_color, help, KNOT_COLOR_STRING); - options.registerOption(KNOT5_COLOR_STRING, knot5_def_color, help, KNOT_COLOR_STRING); + options.registerOption(CHUNKSIZE_STRING, CHUNKSIZE_DEF, help, CHUNKSIZE_DESC_STRING); + options.registerThemeColorBinding(KNOT1_COLOR_OPTION_NAME, KNOT1_COLOR.getId(), help, + KNOT_COLOR_STRING); + options.registerThemeColorBinding(KNOT2_COLOR_OPTION_NAME, KNOT2_COLOR.getId(), help, + KNOT_COLOR_STRING); + options.registerThemeColorBinding(KNOT3_COLOR_OPTION_NAME, KNOT3_COLOR.getId(), help, + KNOT_COLOR_STRING); + options.registerThemeColorBinding(KNOT4_COLOR_OPTION_NAME, KNOT4_COLOR.getId(), help, + KNOT_COLOR_STRING); + options.registerThemeColorBinding(KNOT5_COLOR_OPTION_NAME, KNOT5_COLOR.getId(), help, + KNOT_COLOR_STRING); - options.registerOption(KNOT1_TYPE_STRING, knot1_def_type, help, KNOT_TYPE_STRING); - options.registerOption(KNOT2_TYPE_STRING, knot2_def_type, help, KNOT_TYPE_STRING); - options.registerOption(KNOT3_TYPE_STRING, knot3_def_type, help, KNOT_TYPE_STRING); - options.registerOption(KNOT4_TYPE_STRING, knot4_def_type, help, KNOT_TYPE_STRING); - options.registerOption(KNOT5_TYPE_STRING, knot5_def_type, help, KNOT_TYPE_STRING); + options.registerOption(KNOT1_TYPE_OPTION_NAME, KNOT1_DEF_TYPE, help, KNOT_TYPE_STRING); + options.registerOption(KNOT2_TYPE_OPTION_NAME, KNOT2_DEF_TYPE, help, KNOT_TYPE_STRING); + options.registerOption(KNOT3_TYPE_OPTION_NAME, KNOT3_DEF_TYPE, help, KNOT_TYPE_STRING); + options.registerOption(KNOT4_TYPE_OPTION_NAME, KNOT4_DEF_TYPE, help, KNOT_TYPE_STRING); + options.registerOption(KNOT5_TYPE_OPTION_NAME, KNOT5_DEF_TYPE, help, KNOT_TYPE_STRING); readOptions(options); updatePalettes(); @@ -104,23 +117,17 @@ public class EntropyOverviewOptionsManager implements OptionsChangeListener { } private void readOptions(ToolOptions options) { - chunksize = options.getEnum(CHUNKSIZE_STRING, chunksize_def); + chunksize = options.getEnum(CHUNKSIZE_STRING, CHUNKSIZE_DEF); - knot1color = options.getColor(KNOT1_COLOR_STRING, knot1_def_color); - knot2color = options.getColor(KNOT2_COLOR_STRING, knot2_def_color); - knot3color = options.getColor(KNOT3_COLOR_STRING, knot3_def_color); - knot4color = options.getColor(KNOT4_COLOR_STRING, knot4_def_color); - knot5color = options.getColor(KNOT5_COLOR_STRING, knot5_def_color); - - knot1type = options.getEnum(KNOT1_TYPE_STRING, knot1_def_type); - knot2type = options.getEnum(KNOT2_TYPE_STRING, knot2_def_type); - knot3type = options.getEnum(KNOT3_TYPE_STRING, knot3_def_type); - knot4type = options.getEnum(KNOT4_TYPE_STRING, knot4_def_type); - knot5type = options.getEnum(KNOT5_TYPE_STRING, knot5_def_type); + knot1type = options.getEnum(KNOT1_TYPE_OPTION_NAME, KNOT1_DEF_TYPE); + knot2type = options.getEnum(KNOT2_TYPE_OPTION_NAME, KNOT2_DEF_TYPE); + knot3type = options.getEnum(KNOT3_TYPE_OPTION_NAME, KNOT3_DEF_TYPE); + knot4type = options.getEnum(KNOT4_TYPE_OPTION_NAME, KNOT4_DEF_TYPE); + knot5type = options.getEnum(KNOT5_TYPE_OPTION_NAME, KNOT5_DEF_TYPE); } - private void addPaletteKnot(String name, Color col, double point, double width) { + private void addPaletteKnot(String name, Color color, double point, double width) { int palettewidth = 256; int pointint = (int) Math.floor((palettewidth / 8.0) * point); if (pointint > 255) { @@ -131,11 +138,11 @@ public class EntropyOverviewOptionsManager implements OptionsChangeListener { if (start < 0) { start = 0; } - palette.addKnot(name, col, start, pointint); + palette.addKnot(name, color, start, pointint); } private void updatePalettes() { - palette.setBase(Color.decode("0x000000"), Color.decode("0xffffff")); + palette.setBase(PALETTE_COLOR_LOW, PALETTE_COLOR_HIGH); addPaletteKnots(); service.paletteChanged(); } @@ -143,23 +150,23 @@ public class EntropyOverviewOptionsManager implements OptionsChangeListener { private void addPaletteKnots() { EntropyRecord rec = knot1type.getRecord(); if (rec != null) { - addPaletteKnot(rec.name, knot1color, rec.center, rec.width); + addPaletteKnot(rec.name, KNOT1_COLOR, rec.center, rec.width); } rec = knot2type.getRecord(); if (rec != null) { - addPaletteKnot(rec.name, knot2color, rec.center, rec.width); + addPaletteKnot(rec.name, KNOT2_COLOR, rec.center, rec.width); } rec = knot3type.getRecord(); if (rec != null) { - addPaletteKnot(rec.name, knot3color, rec.center, rec.width); + addPaletteKnot(rec.name, KNOT3_COLOR, rec.center, rec.width); } rec = knot4type.getRecord(); if (rec != null) { - addPaletteKnot(rec.name, knot4color, rec.center, rec.width); + addPaletteKnot(rec.name, KNOT4_COLOR, rec.center, rec.width); } rec = knot5type.getRecord(); if (rec != null) { - addPaletteKnot(rec.name, knot5color, rec.center, rec.width); + addPaletteKnot(rec.name, KNOT5_COLOR, rec.center, rec.width); } } @@ -175,7 +182,7 @@ public class EntropyOverviewOptionsManager implements OptionsChangeListener { * Returns the palette computed after reading the options. * @return the color palette for the {@link EntropyOverviewColorService} */ - public Palette getPalette() { + public OverviewPalette getPalette() { return palette; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotLabelPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotLabelPanel.java index efc614aee3..20453c9c9c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotLabelPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotLabelPanel.java @@ -20,16 +20,19 @@ import java.util.ArrayList; import javax.swing.JPanel; +import generic.theme.GThemeDefaults.Colors.Java; +import generic.theme.Gui; + public class KnotLabelPanel extends JPanel { - private static final Font FONT = new Font("Times New Roman", Font.BOLD, 16); + private static final String FONT_ID = "font.plugin.entropy.label.knot"; private int topBottomMargin = 10; - private Palette palette; + private OverviewPalette palette; public KnotLabelPanel(int topBottomMargin) { this.topBottomMargin = topBottomMargin; } - public void setPalette(Palette palette) { + public void setPalette(OverviewPalette palette) { this.palette = palette; } @@ -45,14 +48,14 @@ public class KnotLabelPanel extends JPanel { g.setColor(getBackground()); g.fillRect(0, 0, width, height); int paletteSize = palette.getSize(); - g.setFont(FONT); + g.setFont(Gui.getFont(FONT_ID)); FontMetrics fontMetrics = g.getFontMetrics(); int ascent = fontMetrics.getAscent(); int descent = fontMetrics.getDescent(); int fontOffset = ascent / 3; // this looks about right ArrayList knots = palette.getKnots(); - g.setColor(Color.BLACK); + g.setColor(Java.BORDER); g.drawLine(5, topBottomMargin - 6, 10, topBottomMargin - ascent + 2); g.drawString("min entropy (0.0)", 20, topBottomMargin - ascent - descent); @@ -67,7 +70,7 @@ public class KnotLabelPanel extends JPanel { g.drawLine(5, y, 10, y); } - g.setColor(Color.BLACK); + g.setColor(Java.BORDER); g.drawLine(5, height + topBottomMargin + 4, 10, height + topBottomMargin + 8); g.drawString("max entropy (8.0)", 20, topBottomMargin + height + ascent + descent); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotPanel.java deleted file mode 100644 index bde94c8cbc..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/KnotPanel.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.overview.entropy; - -import java.awt.*; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.util.ArrayList; - -import javax.swing.*; -import javax.swing.border.LineBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import docking.util.GraphicsUtils; -import docking.widgets.label.GLabel; - -/** - * Class used by the entropy legend panel to show known entropy ranges. - */ -public class KnotPanel extends JPanel implements ComponentListener { - private static final long serialVersionUID = 1L; - private static final int SPACING = 5; - private static final Font FONT = new Font("SansSerif", Font.PLAIN, 10); - private Palette palette = null; - private FontMetrics metrics; - - private ChangeListener paletteListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - buildLabels(); - } - }; - - public KnotPanel() { - super(); - addComponentListener(this); - metrics = getFontMetrics(FONT); - setPreferredSize( - new Dimension(100, SPACING + metrics.getMaxAscent() + metrics.getMaxDescent())); - } - - public void oldPaintComponent(Graphics g) { - super.paintComponent(g); - g.setColor(getBackground()); - Rectangle clip = g.getClipBounds(); - g.fillRect(clip.x, clip.y, clip.width, clip.height); - - if (palette == null) { - return; - } - - g.setColor(Color.BLACK); - g.setFont(FONT); - int height = getHeight(); - int width = getWidth(); - int palsize = palette.getSize(); - int fontHeight = metrics.getMaxAscent() + metrics.getMaxDescent(); - int baseline = (height - fontHeight - 1) / 2 + metrics.getMaxAscent(); - - ArrayList knots = palette.getKnots(); - for (int i = 0; i < knots.size(); i++) { - KnotRecord rec = knots.get(i); - int start = (rec.start * width) / palsize; - int end = (rec.end * width) / palsize; - g.drawLine(start, 0, start, height - 1); - g.drawLine(end, 0, end, height - 1); - g.drawLine(start, height - 1, end, height - 1); - - FontMetrics currentMetrics = metrics; - int w = currentMetrics.stringWidth(rec.name); - int knotwidth = end - start; - while (w > knotwidth) { - currentMetrics = getSmallerFontMetrics(currentMetrics); - w = currentMetrics.stringWidth(rec.name); - - if (currentMetrics.getFont().getSize() <= 4) { - break; // can't go any smaller - } - } - - if (w < knotwidth) { // we found a suitable font - g.setFont(currentMetrics.getFont()); - GraphicsUtils.drawString(this, g, rec.name, start + (knotwidth - 1) / 2 - w / 2, - baseline); - g.setFont(FONT); - } - else { // must be no room to paint the string, even with a small font - String ellipsis = "..."; - w = metrics.stringWidth(ellipsis); - GraphicsUtils.drawString(this, g, ellipsis, start + (knotwidth - 1) / 2 - w / 2, - baseline); - } - - // reset the font - currentMetrics = metrics; - } - - } - - private FontMetrics getSmallerFontMetrics(FontMetrics fontMetrics) { - Font currentFont = fontMetrics.getFont(); - int size = currentFont.getSize(); - Font newFont = currentFont.deriveFont((float) --size); - return getFontMetrics(newFont); - } - - public void setPalette(Palette pal) { - palette = pal; - palette.addPaletteListener(paletteListener); - buildLabels(); - repaint(); - } - - private void buildLabels() { - removeAll(); - setLayout(null); - - int paletteSize = palette.getSize(); - Container parent = getParent(); - - ArrayList knots = palette.getKnots(); - for (KnotRecord record : knots) { - JLabel label = new GLabel(record.name); - label.setFont(FONT); - label.setBorder(new ToplessLineBorder(Color.BLACK)); - label.setHorizontalAlignment(SwingConstants.CENTER); - label.setToolTipText(record.name); - - int height = getHeight(); - int width = getWidth(); - int start = (record.start * width) / paletteSize; - int end = (record.end * width) / paletteSize; - - int labelWidth = end - start; - int labelHeight = height - 1; - int x = start + ((end - start >> 1) - (labelWidth >> 1)); - int y = 0; - - label.setBounds(x, y, labelWidth, labelHeight); - add(label); - } - invalidate(); - if (parent != null) { - parent.validate(); - } - } - - public void refresh() { - buildLabels(); - repaint(); - } - - @Override - public void componentResized(ComponentEvent e) { - refresh(); - } - - @Override - public void componentHidden(ComponentEvent e) { - } - - @Override - public void componentMoved(ComponentEvent e) { - } - - @Override - public void componentShown(ComponentEvent e) { - } - - private class ToplessLineBorder extends LineBorder { - - public ToplessLineBorder(Color color) { - super(color); - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - super.paintBorder(c, g, x, y - 1, width, height + 1); - } - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/LegendPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/LegendPanel.java index e466589ab4..d06dfe1ee5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/LegendPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/LegendPanel.java @@ -48,7 +48,7 @@ public class LegendPanel extends JPanel { return new Dimension(210, 300); } - public void setPalette(Palette pal) { + public void setPalette(OverviewPalette pal) { palettePanel.setPalette(pal); knotPanel.setPalette(pal); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/Palette.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/OverviewPalette.java similarity index 93% rename from Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/Palette.java rename to Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/OverviewPalette.java index 74b1c64a18..78f0b8bf0c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/Palette.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/OverviewPalette.java @@ -21,13 +21,14 @@ import java.util.ArrayList; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import ghidra.util.ColorUtils; import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; /** * Manages the colors used by the entropy overview bar. */ -public class Palette { +public class OverviewPalette { private Color uninitializedColor; private Color[] colors; private ArrayList knots; @@ -35,7 +36,7 @@ public class Palette { private WeakSet listeners = WeakDataStructureFactory.createSingleThreadAccessWeakSet(); - public Palette(int sz, Color uninit) { + public OverviewPalette(int sz, Color uninit) { uninitializedColor = uninit; colors = new Color[sz]; knots = new ArrayList<>(); @@ -75,7 +76,7 @@ public class Palette { int green = (int) (lo.getGreen() * (1.0 - t) + hi.getGreen() * t); int blue = (int) (lo.getBlue() * (1.0 - t) + hi.getGreen() * t); t += step; - colors[i] = new Color(red, green, blue); + colors[i] = ColorUtils.getColor(red, green, blue); } knots.clear(); firePaletteChanged(); @@ -111,7 +112,7 @@ public class Palette { int green = (int) Math.floor(tmp); tmp = (knot.getBlue() - oldcolor.getBlue()) * t + oldcolor.getBlue(); int blue = (int) Math.floor(tmp); - colors[start] = new Color(red, green, blue); + colors[start] = ColorUtils.getColor(red, green, blue); cur += radianstep; start += 1; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/PalettePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/PalettePanel.java index 0fb78759f6..3ab95ed958 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/PalettePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/overview/entropy/PalettePanel.java @@ -19,9 +19,11 @@ import java.awt.*; import javax.swing.JPanel; +import generic.theme.GThemeDefaults.Colors.Java; + public class PalettePanel extends JPanel { - private Palette palette; + private OverviewPalette palette; private final int topBottomMargin; PalettePanel(int topBottomMargin) { @@ -33,7 +35,7 @@ public class PalettePanel extends JPanel { return new Dimension(20, 10); } - public void setPalette(Palette palette) { + public void setPalette(OverviewPalette palette) { this.palette = palette; } @@ -45,12 +47,12 @@ public class PalettePanel extends JPanel { g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); - g.setColor(Color.BLACK); + g.setColor(Java.BORDER); if (palette == null) { - g.setColor(Color.BLACK); g.drawRect(0, 0, width - 1, height - 1); return; } + int palsize = palette.getSize(); //Draw the rectangles for each pixel for (int i = 0; i < height; i++) { @@ -62,7 +64,7 @@ public class PalettePanel extends JPanel { g.setColor(c); g.fillRect(0, topBottomMargin + i, width, 1); } - g.setColor(Color.BLACK); + g.setColor(Java.BORDER); g.drawRect(0, topBottomMargin, width - 1, height); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/CodeUnitPrintable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/CodeUnitPrintable.java index 8a6a2115e9..1cc065b393 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/CodeUnitPrintable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/CodeUnitPrintable.java @@ -27,13 +27,14 @@ import docking.widgets.fieldpanel.LayoutModel; import docking.widgets.fieldpanel.internal.EmptyLayoutBackgroundColorManager; import docking.widgets.fieldpanel.internal.LayoutBackgroundColorManager; import docking.widgets.fieldpanel.internal.PaintContext; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; import ghidra.util.DateUtils; import ghidra.util.Msg; import ghidra.util.task.TaskMonitor; public class CodeUnitPrintable implements Printable { - //private FieldPanel panel; private LayoutModel lm; private int startIndex; private int endIndex; @@ -48,12 +49,11 @@ public class CodeUnitPrintable implements Printable { private static final PaintContext PAINT_CONTEXT = new PaintContext(); static { - PAINT_CONTEXT.setForegroundColor(Color.BLACK); - PAINT_CONTEXT.setDefaultBackgroundColor(Color.WHITE); - PAINT_CONTEXT.setBackgroundColor(Color.white); - PAINT_CONTEXT.setCursorColor(Color.RED); - PAINT_CONTEXT.setSelectionColor(new Color(180, 255, 180)); - PAINT_CONTEXT.setHighlightColor(new Color(255, 255, 150)); + PAINT_CONTEXT.setForegroundColor(Colors.FOREGROUND); + PAINT_CONTEXT.setBackgroundColor(Colors.BACKGROUND); + PAINT_CONTEXT.setCursorColor(Colors.CURSOR); + PAINT_CONTEXT.setSelectionColor(new GColor("color.bg.selection")); + PAINT_CONTEXT.setHighlightColor(new GColor("color.bg.highlight")); PAINT_CONTEXT.setPrinting(true); } @@ -70,13 +70,6 @@ public class CodeUnitPrintable implements Printable { this.book = book; this.job = job; this.startDate = startDate; - - if (pod.getMonochrome()) { - PAINT_CONTEXT.setPrintColor(Color.BLACK); - } - else { - PAINT_CONTEXT.setPrintColor(null); - } } public CodeUnitPrintable(LayoutModel lm, java.util.List layouts, double scaleAmount, @@ -90,20 +83,13 @@ public class CodeUnitPrintable implements Printable { this.book = book; this.job = job; this.startDate = startDate; - - if (pod.getMonochrome()) { - PAINT_CONTEXT.setPrintColor(Color.BLACK); - } - else { - PAINT_CONTEXT.setPrintColor(null); - } } @Override public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { Graphics2D g2 = GraphicsUtils.getGraphics2D(graphics); - g2.setColor(Color.BLACK); + g2.setColor(Colors.FOREGROUND); monitor.setMessage("Printing Page " + (pageIndex + 1)); monitor.initialize(100); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/PrintOptionsDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/PrintOptionsDialog.java index 6ea1b7ed7a..059cd32b20 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/PrintOptionsDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/printing/PrintOptionsDialog.java @@ -23,13 +23,12 @@ import javax.swing.*; import docking.DialogComponentProvider; import docking.widgets.button.GRadioButton; import docking.widgets.checkbox.GCheckBox; +import generic.theme.Gui; import ghidra.util.HelpLocation; public class PrintOptionsDialog extends DialogComponentProvider { - private final Font HEADER_FONT = new Font("SansSerif", Font.PLAIN, 10); - private final FontMetrics HEADER_METRICS = rootPanel.getFontMetrics(HEADER_FONT); - + private static final String FONT_ID = "font.print"; private boolean selectionEnabled; private boolean cancelled = false; @@ -163,11 +162,11 @@ public class PrintOptionsDialog extends DialogComponentProvider { } public Font getHeaderFont() { - return HEADER_FONT; + return Gui.getFont(FONT_ID); } public FontMetrics getHeaderMetrics() { - return HEADER_METRICS; + return rootPanel.getFontMetrics(getHeaderFont()); } public boolean showHeader() { @@ -183,7 +182,8 @@ public class PrintOptionsDialog extends DialogComponentProvider { } public int getHeaderHeight() { - return HEADER_METRICS.getMaxAscent() + HEADER_METRICS.getMaxDescent(); + FontMetrics metrics = getHeaderMetrics(); + return metrics.getMaxAscent() + metrics.getMaxDescent(); } public void setSelectionEnabled(boolean selectionEnabled) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java index 9cad4e9a0c..6f3397b4b4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/InstructionInfoProvider.java @@ -21,6 +21,7 @@ import javax.swing.*; import javax.swing.table.DefaultTableModel; import docking.widgets.checkbox.GCheckBox; +import generic.theme.Gui; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger; import ghidra.app.plugin.processors.sleigh.SleighDebugLogger.SleighDebugMode; import ghidra.framework.model.DomainObjectChangedEvent; @@ -38,6 +39,7 @@ import ghidra.util.table.GhidraTable; * */ class InstructionInfoProvider extends ComponentProviderAdapter implements DomainObjectListener { + private static final String FONT_ID = "font.plugin.instruction.info"; private JPanel mainPanel; private JSplitPane pane; private ShowInstructionInfoPlugin plugin; @@ -99,14 +101,12 @@ class InstructionInfoProvider extends ComponentProviderAdapter implements Domain mainPanel = new JPanel(new BorderLayout()); instructionText = new JTextArea(); - Font defaultFont = instructionText.getFont(); - Font fixedWidthFont = new Font("monospaced", defaultFont.getStyle(), 14); - instructionText.setFont(fixedWidthFont); + Gui.registerFont(instructionText, FONT_ID); instructionText.setEditable(false); operandModel = new OperandModel(); opTable = new GhidraTable(operandModel); - opTable.setFont(fixedWidthFont); + Gui.registerFont(opTable, FONT_ID); opTable.setPreferredScrollableViewportSize(new Dimension(425, 105)); //opTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/AbstractUndoRedoAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/AbstractUndoRedoAction.java index a16ca582db..54367cf564 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/AbstractUndoRedoAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/AbstractUndoRedoAction.java @@ -22,6 +22,7 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.context.ProgramActionContext; import ghidra.app.services.GoToService; import ghidra.app.services.NavigationHistoryService; @@ -31,7 +32,6 @@ import ghidra.framework.model.TransactionListener; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.listing.Program; import ghidra.util.*; -import resources.ResourceManager; /** * Abstract base class for the undo and redo actions. These actions add a listener to the @@ -44,14 +44,14 @@ public abstract class AbstractUndoRedoAction extends DockingAction { private TransactionListener transactionListener; public AbstractUndoRedoAction(PluginTool tool, ProgramManagerPlugin plugin, String name, - String iconPath, String keyBinding, String subGroup) { + String iconId, String keyBinding, String subGroup) { super(name, plugin.getName()); this.tool = tool; this.plugin = plugin; String[] menuPath = { ToolConstants.MENU_EDIT, "&" + name }; - Icon icon = ResourceManager.loadImage(iconPath); + Icon icon = new GIcon(iconId); String group = "Undo"; MenuData menuData = new MenuData(menuPath, icon, group); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiTabPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiTabPanel.java index 91c25c1b1e..739e66634e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiTabPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiTabPanel.java @@ -27,33 +27,40 @@ import javax.swing.border.*; import docking.actions.KeyBindingUtils; import docking.widgets.label.GDLabel; import docking.widgets.label.GIconLabel; +import generic.theme.*; import generic.util.WindowUtilities; import ghidra.framework.model.ProjectLocator; import ghidra.program.model.listing.Program; import ghidra.util.layout.HorizontalLayout; -import resources.ResourceManager; +import resources.Icons; /** * Panel to show a "tab" for an object. ChangeListeners are notified when a tab is selected. */ public class MultiTabPanel extends JPanel { + private static final String FONT_TABS_ID = "font.plugin.tabs"; + private static final String FONT_TABS_LIST_ID = "font.plugin.tabs.list"; + //@formatter:off + private final static Color SELECTED_TAB_COLOR = new GColor("color.bg.listing.tabs.selected"); + private final static Color HIGHLIGHTED_TAB_BG_COLOR = new GColor("color.bg.listing.tabs.highlighted"); + private final static Icon EMPTY16_ICON = Icons.EMPTY_ICON; + private final static Icon EMPTY8_ICON = new GIcon("icon.plugin.programmanager.empty.small"); + private final static Icon CLOSE_ICON = new GIcon("icon.plugin.programmanager.close"); + private final static Icon HIGHLIGHT_CLOSE_ICON = new GIcon("icon.plugin.programmanager.close.highlight"); + private final static Icon LIST_ICON = new GIcon("icon.plugin.programmanager.list"); + private final static Icon TRANSIENT_ICON = new GIcon("icon.plugin.programmanager.transient"); + //@formatter:on - private final static Color SELECTED_TAB_COLOR = new Color(120, 140, 189); - private final static Color HIGHLIGHTED_TAB_COLOR = SELECTED_TAB_COLOR.brighter(); - private final static Icon EMPTY16_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif"); - private final static Icon EMPTY8_ICON = ResourceManager.loadImage("images/empty8x16.png"); - private final static Icon CLOSE_ICON = ResourceManager.loadImage("images/x.gif"); - private final static Icon HIGHLIGHT_CLOSE_ICON = ResourceManager.loadImage("images/pinkX.gif"); - private final static Icon LIST_ICON = ResourceManager.loadImage("images/VCRFastForward.gif"); - private final static Icon TRANSIENT_ICON = ResourceManager.loadImage("images/link.png", 8, 16); - - private final static Color TEXT_SELECTION_COLOR = Color.WHITE; - private final static Color TEXT_NON_SELECTION_COLOR = UIManager.getColor("Tree.textForeground"); + private final static Color TEXT_SELECTION_COLOR = + new GColor("color.fg.listing.tabs.text.selected"); + private final static Color TEXT_NON_SELECTION_COLOR = + new GColor("color.fg.listing.tabs.text.unselected"); private final static Color BG_SELECTION_COLOR = SELECTED_TAB_COLOR; - private final static Color BG_NON_SELECTION_COLOR = UIManager.getColor("Panel.background"); + private final static Color BG_NON_SELECTION_COLOR = + new GColor("color.bg.listing.tabs.unselected"); + private static final Color BG_COLOR_MORE_TABS_HOVER = + new GColor("color.bg.listing.tabs.more.tabs.hover"); - private static final Font LABEL_FONT = new Font("Tahoma", Font.PLAIN, 11); - private static final Font LIST_LABEL_FONT = new Font("Tahoma", Font.BOLD, 9); private static final String DEFAULT_HIDDEN_COUNT_STR = "99"; /** A list of tabs that are hidden from view due to space constraints */ @@ -70,8 +77,6 @@ public class MultiTabPanel extends JPanel { private MultiTabPlugin multiTabPlugin; private ProgramListPanel programListPanel; private Border defaultListLabelBorder; - private Border noTabsBorder; - private Border tabbedBorder; private JLabel showHiddenListLabel; private JDialog listWindow; private JTextField filterField; @@ -126,8 +131,8 @@ public class MultiTabPanel extends JPanel { currentProgram = null; ArrayList list = new ArrayList<>(linkedProgramMap.keySet()); - for (int i = 0; i < list.size(); i++) { - doRemoveProgram(list.get(i)); + for (Program element : list) { + doRemoveProgram(element); } linkedProgramMap.clear(); visibleTabList.clear(); @@ -206,8 +211,6 @@ public class MultiTabPanel extends JPanel { return false; } - //////////////////////////////////////////////////////////// - private TabPanel createProgramTab(final Program program, boolean isSelected) { final JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 1)); labelPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 10)); @@ -215,7 +218,7 @@ public class MultiTabPanel extends JPanel { JLabel nameLabel = new GDLabel(); nameLabel.setIconTextGap(1); nameLabel.setName("objectName"); // junit access - nameLabel.setFont(LABEL_FONT); + Gui.registerFont(nameLabel, FONT_TABS_ID); Color foregroundColor = isSelected ? TEXT_SELECTION_COLOR : TEXT_NON_SELECTION_COLOR; nameLabel.setForeground(foregroundColor); @@ -632,11 +635,11 @@ public class MultiTabPanel extends JPanel { private JLabel createLabel() { JLabel newLabel = new GDLabel(DEFAULT_HIDDEN_COUNT_STR, LIST_ICON, SwingConstants.LEFT); newLabel.setIconTextGap(0); - newLabel.setFont(LIST_LABEL_FONT); + Gui.registerFont(newLabel, FONT_TABS_LIST_ID); newLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4)); newLabel.setToolTipText("Show Tab List"); newLabel.setName("showList"); - newLabel.setBackground(new Color(255, 226, 213)); + newLabel.setBackground(BG_COLOR_MORE_TABS_HOVER); defaultListLabelBorder = newLabel.getBorder(); final Border hoverBorder = BorderFactory.createBevelBorder(BevelBorder.RAISED); @@ -912,7 +915,8 @@ public class MultiTabPanel extends JPanel { //================================================================================================== private class TabPanel extends JPanel { - private Color defaultBackgroundColor; + private Color defaultBgColor; + private Color defaultFgColor; protected final JLabel nameLabel; protected final JPanel labelPanel; protected final JLabel iconLabel; @@ -920,7 +924,8 @@ public class MultiTabPanel extends JPanel { private TabPanel(Color backgroundColor, Program program, JLabel nameLabel, JPanel labelPanel, JLabel iconLabel) { - this.defaultBackgroundColor = backgroundColor; + this.defaultBgColor = backgroundColor; + this.defaultFgColor = nameLabel.getForeground(); this.program = program; this.nameLabel = nameLabel; this.labelPanel = labelPanel; @@ -942,14 +947,19 @@ public class MultiTabPanel extends JPanel { } void paintHighlightedColor(boolean paintHighlight) { - Color newBackgroundColor = defaultBackgroundColor; + Color newBgColor = defaultBgColor; + Color newFgColor = defaultFgColor; if (paintHighlight) { - newBackgroundColor = HIGHLIGHTED_TAB_COLOR; + newBgColor = HIGHLIGHTED_TAB_BG_COLOR; + newFgColor = TEXT_SELECTION_COLOR; + } - setBackground(newBackgroundColor); - nameLabel.setBackground(newBackgroundColor); - labelPanel.setBackground(newBackgroundColor); - iconLabel.setBackground(newBackgroundColor); + + setBackground(newBgColor); + nameLabel.setBackground(newBgColor); + nameLabel.setForeground(newFgColor); + labelPanel.setBackground(newBgColor); + iconLabel.setBackground(newBgColor); } } @@ -985,9 +995,9 @@ public class MultiTabPanel extends JPanel { @Override void paintHighlightedColor(boolean paintHighlight) { super.paintHighlightedColor(paintHighlight); - Color foreground = Color.WHITE; + Color foreground = TEXT_NON_SELECTION_COLOR; if (paintHighlight) { - foreground = Color.BLACK; + foreground = TEXT_SELECTION_COLOR; } // this tab is selected, so change the foreground to be readable diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramListPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramListPanel.java index 1a05165d30..95a0e4fb21 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramListPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramListPanel.java @@ -30,16 +30,20 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Document; import docking.widgets.list.GListCellRenderer; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.program.model.listing.Program; /** - * Panel that displays the overflow of currently open programs that can be choosen. + * Panel that displays the overflow of currently open programs that can be chosen. * * Programs that don't have a visible tab are displayed in bold. */ class ProgramListPanel extends JPanel { - private static final Color BACKGROUND_COLOR = new Color(255, 255, 230); + private static final Color BACKGROUND_COLOR = new GColor("color.bg.listing.tabs.list"); + private static final Color FOREGROUND_COLOR = new GColor("color.fg.listing.tabs.list"); + private List
hiddenList; private List shownList; private JList programList; @@ -74,9 +78,6 @@ class ProgramListPanel extends JPanel { programList.clearSelection(); } - /** - * Return the JList component. - */ JList getList() { return programList; } @@ -115,6 +116,7 @@ class ProgramListPanel extends JPanel { initListModel(); programList = new JList<>(listModel); programList.setBackground(BACKGROUND_COLOR); + programList.setForeground(FOREGROUND_COLOR); programList.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); programList.addMouseMotionListener(new MouseMotionAdapter() { @Override @@ -147,7 +149,7 @@ class ProgramListPanel extends JPanel { // add some padding around the panel Border innerBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); - Border outerBorder = BorderFactory.createLineBorder(Color.BLACK); + Border outerBorder = BorderFactory.createLineBorder(Java.BORDER); Border compoundBorder = BorderFactory.createCompoundBorder(outerBorder, innerBorder); setBorder(compoundBorder); @@ -157,6 +159,7 @@ class ProgramListPanel extends JPanel { private JTextField createFilterField() { JTextField newFilterField = new JTextField(20); newFilterField.setBackground(BACKGROUND_COLOR); + newFilterField.setForeground(FOREGROUND_COLOR); newFilterField.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); newFilterField.getDocument().addDocumentListener(new DocumentListener() { @@ -222,11 +225,11 @@ class ProgramListPanel extends JPanel { private void initListModel() { listModel.clear(); - for (int i = 0; i < hiddenList.size(); i++) { - listModel.addElement(hiddenList.get(i)); + for (Program element : hiddenList) { + listModel.addElement(element); } - for (int i = 0; i < shownList.size(); i++) { - listModel.addElement(shownList.get(i)); + for (Program element : shownList) { + listModel.addElement(element); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java index e7ffcd1c18..1728e08b7d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java @@ -27,7 +27,7 @@ public class RedoAction extends AbstractUndoRedoAction { public static final String SUBGROUP = "2Redo"; public RedoAction(ProgramManagerPlugin plugin, PluginTool tool) { - super(tool, plugin, "Redo", "images/redo.png", "ctrl shift Z", SUBGROUP); + super(tool, plugin, "Redo", "icon.redo", "ctrl shift Z", SUBGROUP); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/SaveProgramAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/SaveProgramAction.java index f44a331334..607b2b882a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/SaveProgramAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/SaveProgramAction.java @@ -15,12 +15,12 @@ */ package ghidra.app.plugin.core.progmgr; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.action.*; import docking.tool.ToolConstants; import ghidra.program.model.listing.Program; -import resources.ResourceManager; +import resources.Icons; /** * Action class for the "Save Program" action @@ -33,7 +33,7 @@ public class SaveProgramAction extends AbstractProgramNameSwitchingAction { menuData.setMenuGroup(group); menuData.setMenuSubGroup(Integer.toString(subGroup)); setMenuBarData(menuData); - ImageIcon icon = ResourceManager.loadImage("images/disk.png"); + Icon icon = Icons.SAVE_ICON; setToolBarData(new ToolBarData(icon, ToolConstants.TOOLBAR_GROUP_ONE)); setKeyBindingData(new KeyBindingData("ctrl S")); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/TransactionMonitor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/TransactionMonitor.java index eda5259631..91fcd6eb40 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/TransactionMonitor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/TransactionMonitor.java @@ -22,17 +22,17 @@ import java.util.List; import javax.swing.*; +import generic.theme.GIcon; import ghidra.framework.data.DomainObjectAdapterDB; import ghidra.framework.model.Transaction; import ghidra.framework.model.TransactionListener; import ghidra.program.database.ProgramDB; import ghidra.program.model.listing.Program; import ghidra.util.HTMLUtilities; -import resources.ResourceManager; class TransactionMonitor extends JComponent implements TransactionListener { - private static ImageIcon busyIcon; + private static Icon busyIcon; private static Dimension prefSize; ProgramDB program; @@ -40,7 +40,7 @@ class TransactionMonitor extends JComponent implements TransactionListener { TransactionMonitor() { super(); - busyIcon = ResourceManager.loadImage("images/editbytes.gif"); + busyIcon = new GIcon("icon.plugin.programmanager.busy"); prefSize = new Dimension(busyIcon.getIconWidth(), busyIcon.getIconHeight()); ToolTipManager.sharedInstance().registerComponent(this); } @@ -60,27 +60,18 @@ class TransactionMonitor extends JComponent implements TransactionListener { repaint(); } - /** - * @see ghidra.framework.model.TransactionListener#transactionStarted(ghidra.framework.data.DomainObjectAdapterDB, ghidra.framework.model.Transaction) - */ @Override public void transactionStarted(DomainObjectAdapterDB domainObj, Transaction tx) { lastTx = tx; repaint(); } - /** - * @see ghidra.framework.model.TransactionListener#transactionEnded(ghidra.framework.data.DomainObjectAdapterDB) - */ @Override public void transactionEnded(DomainObjectAdapterDB domainObj) { lastTx = null; repaint(); } - /** - * @see ghidra.framework.model.TransactionListener#undoStackChanged(ghidra.framework.data.DomainObjectAdapterDB) - */ @Override public void undoStackChanged(DomainObjectAdapterDB domainObj) { // don't care @@ -91,17 +82,11 @@ class TransactionMonitor extends JComponent implements TransactionListener { // don't care } - /** - * @see java.awt.Component#getPreferredSize() - */ @Override public Dimension getPreferredSize() { return new Dimension(prefSize); } - /** - * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) - */ @Override protected void paintComponent(Graphics g) { g.setColor(getBackground()); @@ -111,9 +96,6 @@ class TransactionMonitor extends JComponent implements TransactionListener { } } - /** - * @see javax.swing.JComponent#getToolTipText() - */ @Override public String getToolTipText() { if (lastTx != null) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java index 899f85be41..b01591fd5f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java @@ -27,7 +27,7 @@ public class UndoAction extends AbstractUndoRedoAction { public static final String SUBGROUP = "1Undo"; public UndoAction(ProgramManagerPlugin plugin, PluginTool tool) { - super(tool, plugin, "Undo", "images/undo.png", "ctrl Z", SUBGROUP); + super(tool, plugin, "Undo", "icon.undo", "ctrl Z", SUBGROUP); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DnDTreeCellRenderer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DnDTreeCellRenderer.java index bc28bf23ab..43c2e48d82 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DnDTreeCellRenderer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DnDTreeCellRenderer.java @@ -19,10 +19,14 @@ import java.awt.*; import java.awt.image.BufferedImage; import java.util.*; -import javax.swing.*; +import javax.swing.Icon; +import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; import docking.widgets.GComponent; +import generic.theme.GColor; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; import ghidra.program.model.listing.Group; import resources.ResourceManager; @@ -30,11 +34,10 @@ import resources.ResourceManager; * Cell renderer for the drag and drop tree. */ class DnDTreeCellRenderer extends DefaultTreeCellRenderer { + private static final Color BACKGROUND_UNSELECTED = new GColor("color.bg.tree"); + private static final Color BACKGROUND_SELECTED = new GColor("color.bg.tree.selected"); - private static final String DOCS = "images/openBookBlue.png"; private static final String DISABLED_DOCS = "DisabledDocument.gif"; - static final String FRAGMENT = "images/codeNotInView.gif"; - private static final String EMPTY_FRAGMENT = "images/emptyFragment.gif"; private static final String DISABLED_FRAGMENT = "DisabledFragment"; private static final String DISABLED_VIEWED_FRAGMENT = "DisabledViewedFragment"; private static final String DISABLED_EMPTY_FRAGMENT = "DisabledEmptyFragment"; @@ -46,13 +49,18 @@ class DnDTreeCellRenderer extends DefaultTreeCellRenderer { private static final String DISABLED_CLOSED_FOLDER = "DisabledClosedFolder"; private static final String DISABLED_OPEN_FOLDER = "DisabledOpenedFolder"; - static final String VIEWED_FRAGMENT = "images/codeInView.gif"; - static final String VIEWED_EMPTY_FRAGMENT = "images/emptyFragmentInView.gif"; - static final String VIEWED_CLOSED_FOLDER = "images/closedFolderInView.png"; - static final String VIEWED_OPEN_FOLDER = "images/openFolderInView.png"; - static final String VIEWED_CLOSED_FOLDER_WITH_DESC = "images/closedDescendantsInView.png"; - static final String CLOSED_FOLDER = "images/closedFolder.png"; // closed folder not in view - static final String OPEN_FOLDER = "images/openFolder.png"; + private static final String DOCS = "icon.plugin.programtree.docs"; + static final String FRAGMENT = "icon.plugin.programtree.fragment"; + private static final String EMPTY_FRAGMENT = "icon.plugin.programtree.fragment.empty"; + + static final String VIEWED_FRAGMENT = "icon.plugin.programtree.fragment.viewed"; + static final String VIEWED_EMPTY_FRAGMENT = "icon.plugin.programtree.fragment.viewed.empty"; + static final String VIEWED_CLOSED_FOLDER = "icon.plugin.programtree.fragment.closed.folder"; + static final String VIEWED_OPEN_FOLDER = "icon.plugin.programtree.fragment.open.folder"; + static final String VIEWED_CLOSED_FOLDER_WITH_DESC = + "icon.plugin.programtree.fragment.viewed.closed.folder.with.description"; + static final String CLOSED_FOLDER = "icon.plugin.programtree.closed.folder"; + static final String OPEN_FOLDER = "icon.plugin.programtree.open.folder"; private Map iconMap; @@ -67,8 +75,8 @@ class DnDTreeCellRenderer extends DefaultTreeCellRenderer { */ DnDTreeCellRenderer() { super(); - defaultNonSelectionColor = getBackgroundNonSelectionColor(); - defaultSelectionColor = getBackgroundSelectionColor(); + defaultNonSelectionColor = BACKGROUND_UNSELECTED; + defaultSelectionColor = BACKGROUND_SELECTED; rowForFeedback = -1; // disable HTML rendering @@ -142,7 +150,7 @@ class DnDTreeCellRenderer extends DefaultTreeCellRenderer { /** * Set colors for background according to the draw feedback state. - * @param selected + * @param selected true if selected * @param row row of the node * @param node node to render * @param dtree tree @@ -307,24 +315,21 @@ class DnDTreeCellRenderer extends DefaultTreeCellRenderer { private void loadImages() { // try to load icon images iconMap = new HashMap<>(); - String[] filenames = + String[] iconIds = { DOCS, FRAGMENT, EMPTY_FRAGMENT, VIEWED_FRAGMENT, VIEWED_EMPTY_FRAGMENT, - VIEWED_CLOSED_FOLDER, VIEWED_OPEN_FOLDER, VIEWED_CLOSED_FOLDER_WITH_DESC, // descendants in view - CLOSED_FOLDER, // closed folder not in view - OPEN_FOLDER, // opened folder not in the view + VIEWED_CLOSED_FOLDER, VIEWED_OPEN_FOLDER, VIEWED_CLOSED_FOLDER_WITH_DESC, + CLOSED_FOLDER, OPEN_FOLDER, }; - String[] disabledFilenames = { DISABLED_DOCS, DISABLED_FRAGMENT, DISABLED_EMPTY_FRAGMENT, + String[] disabledNames = { DISABLED_DOCS, DISABLED_FRAGMENT, DISABLED_EMPTY_FRAGMENT, DISABLED_VIEWED_EMPTY_FRAGMENT, DISABLED_VIEWED_FRAGMENT, DISABLED_VIEWED_CLOSED_FOLDER, DISABLED_VIEWED_OPEN_FOLDER, DISABLED_VIEWED_CLOSED_FOLDER_WITH_DESC, DISABLED_CLOSED_FOLDER, DISABLED_OPEN_FOLDER, }; - for (int i = 0; i < filenames.length; i++) { - ImageIcon icon = ResourceManager.loadImage(filenames[i]); - if (icon != null) { - iconMap.put(filenames[i], icon); - Icon disabledIcon = getDisabledIcon(filenames[i], icon); - iconMap.put(disabledFilenames[i], disabledIcon); - } + for (int i = 0; i < iconIds.length; i++) { + GIcon icon = new GIcon(iconIds[i]); + iconMap.put(iconIds[i], icon); + Icon disabledIcon = getDisabledIcon(iconIds[i], icon); + iconMap.put(disabledNames[i], disabledIcon); } } @@ -337,13 +342,13 @@ class DnDTreeCellRenderer extends DefaultTreeCellRenderer { return dim; } - static Icon getDisabledIcon(String imageName, ImageIcon icon) { - Image cutImage = icon.getImage(); + static Icon getDisabledIcon(String imageName, GIcon icon) { + Image cutImage = icon.getImageIcon().getImage(); BufferedImage bufferedImage = new BufferedImage(cutImage.getWidth(null), cutImage.getHeight(null), BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = bufferedImage.createGraphics(); g2d.drawImage(cutImage, 0, 0, null); - g2d.setColor(new Color(255, 255, 255, 128)); + g2d.setColor(Colors.DISABLED); g2d.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); return ResourceManager.getImageIconFromImage(imageName, bufferedImage); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DragNDropTree.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DragNDropTree.java index e0852ccc6a..5d7e59c13a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DragNDropTree.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/DragNDropTree.java @@ -29,6 +29,8 @@ import docking.DockingUtils; import docking.actions.KeyBindingUtils; import docking.dnd.*; import docking.widgets.table.AutoscrollAdapter; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; /** * Class to support Drag and Drop; it is also responsible for @@ -37,6 +39,9 @@ import docking.widgets.table.AutoscrollAdapter; */ public abstract class DragNDropTree extends JTree implements Draggable, Droppable, Autoscroll { + private static final Color BG_COLOR_DRAG_NO_SELECTION = + new GColor("color.bg.tree.drag.no.selection"); + private AutoscrollAdapter autoscroller; protected DefaultTreeModel treeModel; @@ -63,15 +68,9 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl protected Color nonSelectionDragColor; protected int relativeMousePos; // mouse position within the node: - // -1 --> above node, - // 0 --> at the node - // 1 --> below the node - - /** - * Construct a new DragNDropTree. - */ public DragNDropTree(DefaultTreeModel model) { super(model); + setBackground(new GColor("color.bg.tree")); treeModel = model; this.root = (ProgramNode) model.getRoot(); //setEditable(true); // edit interferes with drag gesture listener @@ -82,7 +81,7 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl dndCellRenderer = new DnDTreeCellRenderer(); setCellRenderer(dndCellRenderer); plafSelectionColor = dndCellRenderer.getBackgroundSelectionColor(); - nonSelectionDragColor = new Color(204, 204, 255); + nonSelectionDragColor = BG_COLOR_DRAG_NO_SELECTION; initDragNDrop(); ToolTipManager.sharedInstance().registerComponent(this); autoscroller = new AutoscrollAdapter(this, getRowHeight()); @@ -164,7 +163,8 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl public void dragCanceled(DragSourceDropEvent event) { draggedNodes = null; dndCellRenderer.setBackgroundSelectionColor(plafSelectionColor); - dndCellRenderer.setBackgroundNonSelectionColor(dndCellRenderer.getBackgroundNonSelectionColor()); + dndCellRenderer + .setBackgroundNonSelectionColor(dndCellRenderer.getBackgroundNonSelectionColor()); } ////////////////////////////////////////////////////////////////////// @@ -263,8 +263,8 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl } else { destinationNode = null; - dndCellRenderer.setSelectionForDrag(Color.red); - dndCellRenderer.setNonSelectionForDrag(Color.red); + dndCellRenderer.setSelectionForDrag(Colors.ERROR); + dndCellRenderer.setNonSelectionForDrag(Colors.ERROR); } Point p = e.getLocation(); dndCellRenderer.setRowForFeedback(getRowForLocation(p.x, p.y)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramDnDTree.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramDnDTree.java index 2da9e4d094..81878f9acf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramDnDTree.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramDnDTree.java @@ -315,8 +315,9 @@ public class ProgramDnDTree extends DragNDropTree { return false; } try { - Object data = e.getTransferable().getTransferData( - SelectionTransferable.localProgramSelectionFlavor); + Object data = e.getTransferable() + .getTransferData( + SelectionTransferable.localProgramSelectionFlavor); SelectionTransferData transferData = (SelectionTransferData) data; return program.getDomainFile().getPathname().equals(transferData.getProgramPath()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java index 6f38511c1e..c242f8b982 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java @@ -23,6 +23,7 @@ import javax.swing.tree.TreePath; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.cmd.module.*; import ghidra.app.events.ProgramActivatedPluginEvent; @@ -46,7 +47,6 @@ import ghidra.util.datastruct.StringKeyIndexer; import ghidra.util.exception.AssertException; import ghidra.util.task.RunManager; import resources.Icons; -import resources.ResourceManager; /** * Plugin that creates view provider services to show the trees in a program. @@ -81,8 +81,6 @@ public class ProgramTreePlugin extends ProgramPlugin private static final String TREE_NAME = "TreeName"; private static final String TOGGLE_STATE = "NavigationToggleState"; - private final static String OPEN_VIEW_ICON_NAME = "images/openSmallFolder.png"; - private final static String CREATE_ICON_NAME = "images/layout_add.png"; private final static Icon NAVIGATION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON; private HashMap providerMap;// map of view providers, key is the name @@ -480,7 +478,8 @@ public class ProgramTreePlugin extends ProgramPlugin /** * Close the view if we are not trying to close the last view. * - * @param treeViewProvider + * + * @param treeViewProvider the provider * @return true if the view can be closed */ boolean closeView(TreeViewProvider treeViewProvider) { @@ -516,10 +515,9 @@ public class ProgramTreePlugin extends ProgramPlugin /** * Method renameView. - * - * @param treeViewProvider - * @param newName - * @return boolean + * @param treeViewProvider the provider + * @param newName the new name + * @return true if renamed */ boolean renameView(TreeViewProvider treeViewProvider, String newName) { Listing listing = currentProgram.getListing(); @@ -932,7 +930,7 @@ public class ProgramTreePlugin extends ProgramPlugin } }; - Icon icon = ResourceManager.loadImage(OPEN_VIEW_ICON_NAME); + Icon icon = new GIcon("icon.plugin.programtree.open.tree"); openAction.setToolBarData(new ToolBarData(icon)); openAction.setEnabled(false); openAction.setDescription("Open Tree View"); @@ -945,7 +943,7 @@ public class ProgramTreePlugin extends ProgramPlugin } }; - icon = ResourceManager.loadImage(CREATE_ICON_NAME); + icon = new GIcon("icon.plugin.programtree.new.tree"); createAction.setToolBarData(new ToolBarData(icon)); createAction.setEnabled(false); createAction.setDescription(HTMLUtilities.toHTML("Create a new default tree view; shows\n" + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/TreeDragSrcAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/TreeDragSrcAdapter.java index bb0244c6ab..774b549507 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/TreeDragSrcAdapter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/TreeDragSrcAdapter.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,50 +15,41 @@ */ package ghidra.app.plugin.core.programtree; - import java.awt.*; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragSource; -import javax.swing.ImageIcon; - import docking.dnd.DragSrcAdapter; import docking.dnd.Draggable; - -import resources.ResourceManager; - +import generic.theme.GIcon; /** - * Drag source adapter on tree to set the custom cursors for the drag under - * feedback. + * Drag source adapter on tree to set the custom cursors for the drag under feedback. */ class TreeDragSrcAdapter extends DragSrcAdapter { - - private static String MOVE_CURSOR_FILENAME = "images/dragMoveCursor.gif"; - private static String COPY_CURSOR_FILENAME = "images/dragCopyCursor.gif"; - - private static String MOVE_NAME = "MoveCursor"; - private static String COPY_NAME = "CopyCursor"; - + + private static final String MOVE_CURSOR_ID = "icon.plugin.programtree.drag.move"; + private static final String COPY_CURSOR_ID = "icon.plugin.programtree.drag.copy"; + + private static final String MOVE_NAME = "MoveCursor"; + private static final String COPY_NAME = "CopyCursor"; + private Cursor feedbackCursor; private Cursor copyCursor; - private Cursor moveCursor; - + private Cursor moveCursor; + public TreeDragSrcAdapter(Draggable dragComponent) { super(dragComponent); } - - /** - * @see docking.dnd.DragSrcAdapter#getDropOkCursor(int) - */ + @Override - protected Cursor getDropOkCursor(int action) { + protected Cursor getDropOkCursor(int action) { if (feedbackCursor != null) { return feedbackCursor; } return super.getDropOkCursor(action); } - + /** * Get the appropriate cursor for the action and mouse position within the node. * @param action move, copy, link @@ -79,14 +69,14 @@ class TreeDragSrcAdapter extends DragSrcAdapter { } } else { - c = DragSource.DefaultCopyDrop; - if (relativeMousePos != 0) { - c = getCopyCursor(); - } + c = DragSource.DefaultCopyDrop; + if (relativeMousePos != 0) { + c = getCopyCursor(); + } } - return c; + return c; } - + /** * Set the cursor for drag under feedback. * @param c cursor for feedback; may be null if there is no feedback. @@ -94,34 +84,26 @@ class TreeDragSrcAdapter extends DragSrcAdapter { void setFeedbackCursor(Cursor c) { feedbackCursor = c; } - - private Cursor getMoveCursor() { - if ( moveCursor == null ) { - moveCursor = createCursor(MOVE_CURSOR_FILENAME, MOVE_NAME, new Point(0, 16)); - } - return moveCursor; - } - private Cursor getCopyCursor() { - if ( copyCursor == null ) { - copyCursor = createCursor(COPY_CURSOR_FILENAME, COPY_NAME, new Point(0, 24)); - } - return copyCursor; - } - - /** - * Create a cursor with the filename and cursor name. - * @param filename a name from the images resource - * @param cursorName name to use int the createCustomCursor() - * method on Toolkit - */ - private static Cursor createCursor(String filename, String cursorName, - Point hotSpot) { - ImageIcon icon = ResourceManager.loadImage(filename); - Image image = icon.getImage(); + private Cursor getMoveCursor() { + if (moveCursor == null) { + moveCursor = createCursor(MOVE_CURSOR_ID, MOVE_NAME, new Point(0, 16)); + } + return moveCursor; + } + + private Cursor getCopyCursor() { + if (copyCursor == null) { + copyCursor = createCursor(COPY_CURSOR_ID, COPY_NAME, new Point(0, 24)); + } + return copyCursor; + } + + private static Cursor createCursor(String id, String cursorName, Point hotSpot) { + GIcon icon = new GIcon(id); + Image image = icon.getImageIcon().getImage(); Toolkit tk = Toolkit.getDefaultToolkit(); - Cursor cursor = tk.createCustomCursor(image, hotSpot, cursorName); - return cursor; + return tk.createCustomCursor(image, hotSpot, cursorName); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/reachability/FunctionReachabilityPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/reachability/FunctionReachabilityPlugin.java index f3bf1fa77f..7c4f0b7771 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/reachability/FunctionReachabilityPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/reachability/FunctionReachabilityPlugin.java @@ -23,6 +23,7 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.context.ListingActionContext; import ghidra.app.plugin.PluginCategoryNames; @@ -32,8 +33,6 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginStatus; import ghidra.program.util.*; import ghidra.util.HelpLocation; -import resources.ResourceManager; -import resources.icons.RotateIcon; //@formatter:off @PluginInfo( @@ -49,8 +48,7 @@ import resources.icons.RotateIcon; public class FunctionReachabilityPlugin extends ProgramPlugin { // TODO - static final Icon ICON = new RotateIcon( - ResourceManager.loadImage("images/function_graph_curvey.png"), 90); + static final Icon ICON = new GIcon("icon.plugin.reachability.provider"); private DockingAction showProviderAction; private List providers = diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditMemoryReferencePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditMemoryReferencePanel.java index 353a696771..bc66418267 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditMemoryReferencePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditMemoryReferencePanel.java @@ -24,16 +24,18 @@ import java.util.List; import javax.swing.*; import javax.swing.border.LineBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import javax.swing.table.AbstractTableModel; import org.jdom.Element; +import docking.DropDownMenuIcon; import docking.widgets.checkbox.GCheckBox; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.GDLabel; import docking.widgets.label.GLabel; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.app.util.AddressInput; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; @@ -41,12 +43,13 @@ import ghidra.program.model.scalar.Scalar; import ghidra.program.model.symbol.*; import ghidra.program.util.OperandFieldLocation; import ghidra.program.util.ProgramLocation; +import ghidra.util.Swing; import ghidra.util.layout.PairLayout; -import resources.ResourceManager; class EditMemoryReferencePanel extends EditReferencePanel { - private static ImageIcon PULLDOWN_ICON = ResourceManager.loadImage("images/menu16.gif"); + private static final Color BUTTON_COLOR = new GColor("color.fg.button"); + private static final Icon MENU_ICON = new DropDownMenuIcon(BUTTON_COLOR); private static final RefType[] MEM_REF_TYPES = RefTypeFactory.getMemoryRefTypes(); @@ -83,13 +86,7 @@ class EditMemoryReferencePanel extends EditReferencePanel { @Override public void requestFocus() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // do later to override the default later nature of focus - toAddressField.requestFocus(); - } - }); + Swing.runLater(() -> toAddressField.requestFocus()); } private void buildPanel() { @@ -97,12 +94,7 @@ class EditMemoryReferencePanel extends EditReferencePanel { offsetCheckbox = new GCheckBox("Offset:"); offsetCheckbox.setHorizontalAlignment(SwingConstants.RIGHT); - offsetCheckbox.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - enableOffsetField(offsetCheckbox.isSelected()); - } - }); + offsetCheckbox.addChangeListener(e -> enableOffsetField(offsetCheckbox.isSelected())); offsetField = new JTextField(); addrLabel = new GDLabel("Base Address:"); @@ -112,7 +104,7 @@ class EditMemoryReferencePanel extends EditReferencePanel { toAddressField = new AddressInput(); - addrHistoryButton = new JButton(PULLDOWN_ICON); + addrHistoryButton = new JButton(MENU_ICON); addrHistoryButton.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { @@ -150,11 +142,11 @@ class EditMemoryReferencePanel extends EditReferencePanel { enableOffsetField(false); } - private void enableOffsetField(boolean state) { - offsetCheckbox.setSelected(state); - offsetField.setEnabled(state); - offsetField.setBackground(state ? Color.WHITE : getBackground()); - if (!state) { + private void enableOffsetField(boolean enabled) { + offsetCheckbox.setSelected(enabled); + offsetField.setEnabled(enabled); + offsetField.setBackground(enabled ? Colors.BACKGROUND : getBackground()); + if (!enabled) { offsetField.setText("0x0"); } else { @@ -173,7 +165,7 @@ class EditMemoryReferencePanel extends EditReferencePanel { } } } - addrLabel.setText(state ? "Base Address:" : "To Address:"); + addrLabel.setText(enabled ? "Base Address:" : "To Address:"); } private void populateRefTypes(RefType adhocType) { @@ -304,8 +296,9 @@ class EditMemoryReferencePanel extends EditReferencePanel { toAddr = fromCu.getAddress(fromOpIndex); } if (toAddr != null) { - Reference r = p.getReferenceManager().getReference(fromCu.getMinAddress(), toAddr, - fromOpIndex); + Reference r = p.getReferenceManager() + .getReference(fromCu.getMinAddress(), toAddr, + fromOpIndex); if (r != null) { toAddr = null; if (r.isOffsetReference()) { @@ -540,7 +533,7 @@ class EditMemoryReferencePanel extends EditReferencePanel { model = new HistoryTableModel(fromCodeUnit.getProgram()); displayTable = new JTable(model); displayTable.setTableHeader(null); - displayTable.setBorder(new LineBorder(Color.BLACK)); + displayTable.setBorder(new LineBorder(Java.BORDER)); displayTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); displayTable.addMouseListener(new MouseAdapter() { @@ -588,24 +581,26 @@ class EditMemoryReferencePanel extends EditReferencePanel { p.y += toAddressField.getHeight(); historyWin.setLocation(p); - KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( - "focusOwner", new PropertyChangeListener() { - boolean hasFocus = false; + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .addPropertyChangeListener( + "focusOwner", new PropertyChangeListener() { + boolean hasFocus = false; - @Override - public void propertyChange(PropertyChangeEvent evt) { - Object focusOwner = evt.getNewValue(); - if (focusOwner == displayTable || focusOwner == historyWin) { - hasFocus = true; - } - else if (hasFocus) { - hasFocus = false; - KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener( - "focusOwner", this); - hideAddressHistoryPopup(); - } - } - }); + @Override + public void propertyChange(PropertyChangeEvent evt) { + Object focusOwner = evt.getNewValue(); + if (focusOwner == displayTable || focusOwner == historyWin) { + hasFocus = true; + } + else if (hasFocus) { + hasFocus = false; + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .removePropertyChangeListener( + "focusOwner", this); + hideAddressHistoryPopup(); + } + } + }); historyWin.setVisible(true); @@ -627,19 +622,9 @@ class EditMemoryReferencePanel extends EditReferencePanel { @Override public void componentShown(ComponentEvent e) { + // stub } }); - - //displayList.requestFocus(); - -// historyWin.addFocusListener(new FocusListener() { -// public void focusGained(FocusEvent e) { -// } -// public void focusLost(FocusEvent e) { -// toggleAddressHistoryPopup(); -// } -// }); - } private void updateTableSelectionForEvent(MouseEvent anEvent) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java index b883b22de3..41dbbd3899 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java @@ -35,6 +35,9 @@ import docking.dnd.DropTgtAdapter; import docking.dnd.Droppable; import docking.widgets.checkbox.GCheckBox; import docking.widgets.table.*; +import generic.theme.GColor; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors.Tables; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.util.SelectionTransferData; import ghidra.app.util.SelectionTransferable; @@ -52,31 +55,31 @@ import ghidra.util.HelpLocation; import ghidra.util.table.GhidraTable; import ghidra.util.task.SwingUpdateManager; import resources.Icons; -import resources.ResourceManager; public class EditReferencesProvider extends ComponentProviderAdapter implements DomainObjectListener, ChangeListener { private static final String ADD_REFS_GROUP = "AddReferences"; + //@formatter:off private static final HelpLocation HELP = new HelpLocation("ReferencesPlugin", "View_Edit_References_From"); - private static Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private static Icon EDIT_ICON = ResourceManager.loadImage("images/editbytes.gif"); - private static Icon DELETE_ICON = ResourceManager.loadImage("images/edit-delete.png"); - private static Icon RECV_LOCATION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON; - //private static Icon RECV_LOCATION_OFF_ICON = ResourceManager.loadImage("images/locationInOff.gif"); - private static Icon SEND_LOCATION_ICON = Icons.NAVIGATE_ON_OUTGOING_EVENT_ICON; - //private static Icon SEND_LOCATION_OFF_ICON = ResourceManager.loadImage("images/locationOutOff.gif"); - private static Icon HOME_ICON = ResourceManager.loadImage("images/go-home.png"); - private static Icon SELECT_ICON = ResourceManager.loadImage("images/text_align_justify.png"); + private static final Icon ADD_ICON = Icons.ADD_ICON; + private static final Icon EDIT_ICON = new GIcon("icon.base.edit.bytes"); + private static final Icon DELETE_ICON = Icons.DELETE_ICON; + private static final Icon RECV_LOCATION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON; + private static final Icon SEND_LOCATION_ICON = Icons.NAVIGATE_ON_OUTGOING_EVENT_ICON; + private static final Icon HOME_ICON = Icons.HOME_ICON; + private static final Icon SELECT_ICON = Icons.MAKE_SELECTION_ICON; + //@formatter:on private static final String TITLE_PREFIX = "References Editor "; static int MNEMONIC_OPINDEX = ReferenceManager.MNEMONIC; - static Color HIGHLIGHT_COLOR = new Color(205, 205, 205); + static Color BG_COLOR_ACTIVE_OPERAND = + new GColor("color.bg.plugin.references.table.active.operand"); private static final DataFlavor[] ACCEPTABLE_DROP_FLAVORS = new DataFlavor[] { SelectionTransferable.localProgramSelectionFlavor }; @@ -132,8 +135,9 @@ public class EditReferencesProvider extends ComponentProviderAdapter if (currentCodeUnit != null) { Memory memory = currentCodeUnit.getProgram().getMemory(); try { - Object data = e.getTransferable().getTransferData( - SelectionTransferable.localProgramSelectionFlavor); + Object data = e.getTransferable() + .getTransferData( + SelectionTransferable.localProgramSelectionFlavor); AddressSetView view = ((SelectionTransferData) data).getAddressSet(); if (memory.contains(view)) { return true; @@ -530,7 +534,7 @@ public class EditReferencesProvider extends ComponentProviderAdapter private Data findComponent(Data data, Address addr) { while (addr.compareTo(data.getMinAddress()) >= 0) { long offset = addr.subtract(data.getMinAddress()); - Data d = data.getComponentAt((int) offset); + Data d = data.getComponentContaining((int) offset); if (d == null) { break; } @@ -954,8 +958,8 @@ public class EditReferencesProvider extends ComponentProviderAdapter if (!isSelected) { if (ref.getOperandIndex() == instrPanel.getSelectedOpIndex()) { - cb.setBackground(HIGHLIGHT_COLOR); - setBackground(HIGHLIGHT_COLOR); + cb.setBackground(BG_COLOR_ACTIVE_OPERAND); + setBackground(BG_COLOR_ACTIVE_OPERAND); cb.setOpaque(true); } } @@ -1004,7 +1008,7 @@ public class EditReferencesProvider extends ComponentProviderAdapter else { if (ref.getOperandIndex() == instrPanel.getSelectedOpIndex()) { checkbox.setForeground(table.getForeground()); - checkbox.setBackground(HIGHLIGHT_COLOR); + checkbox.setBackground(BG_COLOR_ACTIVE_OPERAND); checkbox.setOpaque(true); } else { @@ -1022,8 +1026,7 @@ public class EditReferencesProvider extends ComponentProviderAdapter RefCellTextRenderer() { defaultFont = getFont(); - boldFont = new Font(defaultFont.getName(), defaultFont.getStyle() | Font.BOLD, - defaultFont.getSize()); + boldFont = defaultFont.deriveFont(defaultFont.getStyle() | Font.BOLD); setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0)); } @@ -1047,7 +1050,7 @@ public class EditReferencesProvider extends ComponentProviderAdapter if (isSelected) { if (bad) { - setForeground(Color.pink); + setForeground(Tables.FG_ERROR_SELECTED); setFont(boldFont); } else { @@ -1060,14 +1063,14 @@ public class EditReferencesProvider extends ComponentProviderAdapter // set color to red if address does not exist in memory if (bad) { - setForeground(Color.red); + setForeground(Tables.FG_ERROR_UNSELECTED); setFont(boldFont); } else { setFont(defaultFont); } if (ref.getOperandIndex() == instrPanel.getSelectedOpIndex()) { - setBackground(HIGHLIGHT_COLOR); + setBackground(BG_COLOR_ACTIVE_OPERAND); setOpaque(true); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java index c1363e5505..5d286166c6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java @@ -27,6 +27,7 @@ import docking.ActionContext; import docking.action.builder.ActionBuilder; import docking.widgets.dialogs.InputDialog; import docking.widgets.table.AbstractSortedTableModel; +import generic.theme.GIcon; import ghidra.app.cmd.refs.*; import ghidra.framework.cmd.Command; import ghidra.framework.cmd.CompoundCmd; @@ -41,17 +42,17 @@ import ghidra.program.model.symbol.SourceType; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.table.GhidraTable; -import resources.ResourceManager; +import resources.Icons; /** * ComponentProvider that displays a table of External Programs. * */ public class ExternalReferencesProvider extends ComponentProviderAdapter { - private static ImageIcon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private static ImageIcon DELETE_ICON = ResourceManager.loadImage("images/edit-delete.png"); - private static ImageIcon EDIT_ICON = ResourceManager.loadImage("images/editbytes.gif"); - private static ImageIcon CLEAR_ICON = ResourceManager.loadImage("images/erase16.png"); + private static Icon ADD_ICON = Icons.ADD_ICON; + private static Icon DELETE_ICON = Icons.DELETE_ICON; + private static Icon EDIT_ICON = new GIcon("icon.base.edit.bytes"); + private static Icon CLEAR_ICON = Icons.CLEAR_ICON; private JPanel mainPanel; private ExternalNamesTableModel tableModel; @@ -343,7 +344,8 @@ public class ExternalReferencesProvider extends ComponentProviderAdapter { } ExternalNamesRow path = - new ExternalNamesRow(programName, extMgr.getExternalLibraryPath(programName)); + new ExternalNamesRow(programName, + extMgr.getExternalLibraryPath(programName)); paths.add(path); } } @@ -364,7 +366,6 @@ public class ExternalReferencesProvider extends ComponentProviderAdapter { return -1; } - @Override public void dispose() { super.dispose(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/InstructionPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/InstructionPanel.java index 7b76ffc81f..98d27c2227 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/InstructionPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/InstructionPanel.java @@ -32,6 +32,8 @@ import docking.actions.KeyBindingUtils; import docking.dnd.DropTgtAdapter; import docking.dnd.Droppable; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.Gui; import ghidra.app.util.*; import ghidra.app.util.viewer.field.BrowserCodeUnitFormat; import ghidra.program.model.address.Address; @@ -43,15 +45,13 @@ import ghidra.program.model.symbol.*; class InstructionPanel extends JPanel implements ChangeListener { - private static final int ETCHED_BORDER_THICKNESS = 2; + private static final int BORDER_SIZE = 2; + private static final Border EMPTY_BORDER = new EmptyBorder(BORDER_SIZE, + BORDER_SIZE, BORDER_SIZE, BORDER_SIZE); + private static final Border ETCHED_BORDER = new EtchedBorder(); - private static final Border ETCHED_BORDER = new EtchedBorder(Color.BLACK, Color.GRAY); - private static final Border EMPTY_BORDER = new EmptyBorder(ETCHED_BORDER_THICKNESS, - ETCHED_BORDER_THICKNESS, ETCHED_BORDER_THICKNESS, ETCHED_BORDER_THICKNESS); - - private final static Color UNLOCKED_LABEL_COLOR = Color.blue; - private final static Color NOT_IN_MEMORY_COLOR = Color.red; - private final static Color DEFAULT_FG_COLOR = Color.black; + private final static Color NOT_IN_MEMORY_COLOR = Colors.ERROR; + private final static Color DEFAULT_FG_COLOR = Colors.FOREGROUND; private static final DataFlavor[] ACCEPTABLE_DROP_FLAVORS = new DataFlavor[] { SelectionTransferable.localProgramSelectionFlavor }; @@ -65,7 +65,6 @@ class InstructionPanel extends JPanel implements ChangeListener { private JLabel[] operandLabels; private DropTarget[] dropTargets; // 0: mnemonic, >= 1: operands private JPanel innerPanel; - private Font monoFont; private int activeIndex; private int activeSubIndex; private CodeUnit currentCodeUnit; @@ -85,13 +84,13 @@ class InstructionPanel extends JPanel implements ChangeListener { */ @Override public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) { + // stub } /** * Return true if is OK to drop the transferable at the location * specified the event. * @param e event that has current state of drag and drop operation - * @param data data that is being dragged */ @Override public boolean isDropOk(DropTargetDragEvent e) { @@ -102,26 +101,27 @@ class InstructionPanel extends JPanel implements ChangeListener { updateLabels(getLabelIndex((JLabel) targetComp), -1); try { - Object data = e.getTransferable().getTransferData( - SelectionTransferable.localProgramSelectionFlavor); + Object data = e.getTransferable() + .getTransferData( + SelectionTransferable.localProgramSelectionFlavor); AddressSetView view = ((SelectionTransferData) data).getAddressSet(); if (memory.contains(view)) { return true; } } catch (UnsupportedFlavorException e1) { + // return false } catch (IOException e1) { + // return false } } return false; } - /** - * Revert back to normal if any drag feedback was set. - */ @Override public void undoDragUnderFeedback() { + // stub } /** @@ -156,9 +156,6 @@ class InstructionPanel extends JPanel implements ChangeListener { create(topPad, leftPad, bottomPad, rightPad); } - /** - * Returns the current code unit displayed. - */ CodeUnit getCurrentCodeUnit() { return currentCodeUnit; } @@ -168,14 +165,6 @@ class InstructionPanel extends JPanel implements ChangeListener { updateLabels(activeIndex, activeSubIndex); } - /** - * Set the code unit location. - * @param cu code unit - * @param loc location - * @param opIndex operand index - * @param showBlockID ID for what to show for the block name in the - * operand - */ void setCodeUnitLocation(CodeUnit cu, int opIndex, int subIndex, boolean locked) { if (cu != null) { this.locked = locked; @@ -218,14 +207,11 @@ class InstructionPanel extends JPanel implements ChangeListener { setBorder(border); addressLabel = new GDLabel("FFFFFFFF"); // use a default - - Font font = addressLabel.getFont(); - monoFont = new Font("monospaced", font.getStyle(), font.getSize()); - addressLabel.setFont(monoFont); + Gui.registerFont(addressLabel, "font.monospaced"); addressLabel.setName("addressLabel"); mnemonicLabel = new GDLabel("movl"); - mnemonicLabel.setFont(monoFont); + Gui.registerFont(mnemonicLabel, "font.monospaced"); mnemonicLabel.setName("mnemonicLabel"); mnemonicLabel.addMouseListener(mouseListener); @@ -233,8 +219,8 @@ class InstructionPanel extends JPanel implements ChangeListener { for (int i = 0; i < operandLabels.length; i++) { operandLabels[i] = new GDLabel("%ebp, "); operandLabels[i].setName("operandLabels[" + i + "]"); - operandLabels[i].setFont(monoFont); operandLabels[i].addMouseListener(mouseListener); + Gui.registerFont(operandLabels[i], "font.monospaced"); } innerPanel = new JPanel(); @@ -286,7 +272,7 @@ class InstructionPanel extends JPanel implements ChangeListener { /** * Enable drop on specified number of operands. * A value of -1 will disable all drop targets. - * @param numOperands + * @param numOperands the number of operands */ private void updateDropTargets(int numOperands) { ++numOperands; @@ -374,7 +360,7 @@ class InstructionPanel extends JPanel implements ChangeListener { if (activeIndex == opIndex) { operandLabels[opIndex].setBorder(ETCHED_BORDER); - operandLabels[opIndex].setBackground(EditReferencesProvider.HIGHLIGHT_COLOR); + operandLabels[opIndex].setBackground(EditReferencesProvider.BG_COLOR_ACTIVE_OPERAND); operandLabels[opIndex].setOpaque(true); } else { @@ -393,7 +379,7 @@ class InstructionPanel extends JPanel implements ChangeListener { mnemonicLabel.setForeground(DEFAULT_FG_COLOR); if (activeIndex == ReferenceManager.MNEMONIC) { - mnemonicLabel.setBackground(EditReferencesProvider.HIGHLIGHT_COLOR); + mnemonicLabel.setBackground(EditReferencesProvider.BG_COLOR_ACTIVE_OPERAND); mnemonicLabel.setBorder(ETCHED_BORDER); mnemonicLabel.setOpaque(true); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java index ef19bb0c9d..c0c5d62f6c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java @@ -22,6 +22,7 @@ import javax.swing.*; import docking.ActionContext; import docking.WindowPosition; import docking.action.*; +import generic.theme.GIcon; import ghidra.app.context.ProgramActionContext; import ghidra.framework.model.*; import ghidra.framework.plugintool.ComponentProviderAdapter; @@ -33,15 +34,12 @@ import ghidra.program.util.ChangeManager; import ghidra.util.HelpLocation; import ghidra.util.task.SwingUpdateManager; import resources.Icons; -import resources.ResourceManager; public class RegisterManagerProvider extends ComponentProviderAdapter { - private static final Icon DELETE_REGISTER_VALUES_ICON = - ResourceManager.loadImage("images/edit-delete.png"); - private static final Icon SELECT_REGISTER_VALUES_ICON = - ResourceManager.loadImage("images/text_align_justify.png"); - private static final Icon FILTER_ICON = ResourceManager.loadImage("images/textfield.png"); - static final ImageIcon REGISTER_ICON = ResourceManager.loadImage("images/registerGroup.png"); + private static final Icon DELETE_REGISTER_VALUES_ICON = Icons.DELETE_ICON; + private static final Icon SELECT_REGISTER_VALUES_ICON = Icons.MAKE_SELECTION_ICON; + private static final Icon FILTER_ICON = Icons.CONFIGURE_FILTER_ICON; + static final Icon REGISTER_ICON = new GIcon("icon.plugin.register.provider"); private static Icon RECV_LOCATION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON; private Program program; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterTree.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterTree.java index ccdddf20ce..94e58dd78f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterTree.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterTree.java @@ -20,15 +20,15 @@ import java.awt.Point; import java.util.*; import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; -import docking.widgets.tree.*; +import docking.widgets.tree.GTree; +import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.program.model.lang.Register; import ghidra.program.model.listing.Program; -import resources.ResourceManager; +import resources.Icons; public class RegisterTree extends GTree { private Program program; @@ -48,15 +48,12 @@ public class RegisterTree extends GTree { // never have a horizontal scroll bar. JScrollPane scrollPane = getScrollPane(); final JViewport viewport = scrollPane.getViewport(); - scrollPane.getViewport().addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - Point viewPosition = viewport.getViewPosition(); - if (viewPosition.x != 0) { - // if it scrolls horizontally, put it back - viewPosition.x = 0; - viewport.setViewPosition(viewPosition); - } + scrollPane.getViewport().addChangeListener(e -> { + Point viewPosition = viewport.getViewPosition(); + if (viewPosition.x != 0) { + // if it scrolls horizontally, put it back + viewPosition.x = 0; + viewport.setViewPosition(viewPosition); } }); setMinimumSize(new Dimension(175, 30)); @@ -78,7 +75,7 @@ public class RegisterTree extends GTree { } private static Register[] getNonHiddenRegisters(Program program) { - ArrayList
list = new ArrayList (); + ArrayList list = new ArrayList<>(); for (Register reg : program.getProgramContext().getRegisters()) { if (!reg.isHidden()) { list.add(reg); @@ -191,9 +188,9 @@ class RegisterTreeRootNode extends SearchableRegisterTreeNode { lastRegisters = registers; HashMap groups = - new HashMap (); + new HashMap<>(); - List nodes = new ArrayList (); + List nodes = new ArrayList<>(); for (Register register : registers) { if (register.getBaseRegister() != register && @@ -220,8 +217,8 @@ class RegisterTreeRootNode extends SearchableRegisterTreeNode { } class RegisterTreeNode extends SearchableRegisterTreeNode { - private static ImageIcon REG_ICON = ResourceManager.loadImage("images/registerIcon.png"); - private static ImageIcon REG_GROUP_ICON = ResourceManager.loadImage("images/registerGroup.png"); + private static Icon REG_ICON = new GIcon("icon.plugin.register"); + private static Icon REG_GROUP_ICON = new GIcon("icon.plugin.register.provider"); private final Register register; public RegisterTreeNode(Register register) { @@ -274,9 +271,8 @@ class RegisterTreeNode extends SearchableRegisterTreeNode { } class RegisterTreeGroupNode extends SearchableRegisterTreeNode { - private static ImageIcon OPEN_ICON = ResourceManager.loadImage("images/openSmallFolder.png"); - private static ImageIcon CLOSED_ICON = - ResourceManager.loadImage("images/closedSmallFolder.png"); + private static Icon OPEN_ICON = Icons.OPEN_FOLDER_ICON; + private static Icon CLOSED_ICON = Icons.CLOSED_FOLDER_ICON; private String name; public RegisterTreeGroupNode(String name) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java index 4e561a4053..ba003a05ed 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java @@ -26,6 +26,9 @@ import javax.swing.*; import docking.widgets.OptionDialog; import docking.widgets.table.*; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Palette; +import generic.theme.Gui; import ghidra.app.cmd.register.SetRegisterCmd; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.services.*; @@ -45,7 +48,8 @@ class RegisterValuesPanel extends JPanel { private static final String VALUE_COLUMN_NAME = "Value"; private static final String START_ADDRESS_COLUMN_NAME = "Start Address"; private static final String END_ADDRESS_COLUMN_NAME = "End Address"; - private static final Color REGISTER_MARKER_COLOR = new Color(0, 153, 153); + private static final Color REGISTER_MARKER_COLOR = + new GColor("color.bg.plugin.register.marker"); private Program currentProgram; private GhidraTable table; @@ -490,11 +494,11 @@ class RegisterValueRange { class RegisterValueRenderer extends GTableCellRenderer { - private Color defaultColor = Color.LIGHT_GRAY; + private Color defaultColor = Palette.LIGHT_GRAY; RegisterValueRenderer(JTable table) { setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); - setFont(new Font("monospaced", Font.PLAIN, 12)); + Gui.registerFont(this, "font.monospaced"); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java index 8a6c51ff82..a077bf5ceb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java @@ -28,6 +28,7 @@ import javax.swing.event.ChangeListener; import docking.DialogComponentProvider; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GLabel; +import generic.theme.Gui; import ghidra.app.util.bean.FixedBitSizeValueField; import ghidra.program.model.address.*; import ghidra.program.model.lang.Register; @@ -92,7 +93,7 @@ public class SetRegisterValueDialog extends DialogComponentProvider { registerChanged(); } }); - f = new Font("monospaced", Font.PLAIN, 13); + f = Gui.getFont("font.monospaced"); addressRangeList = new JList(); addressRangeList.setEnabled(false); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchProvider.java index 4c26b9fcdb..5699fc0aef 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchProvider.java @@ -26,6 +26,7 @@ import docking.*; import docking.widgets.label.GLabel; import docking.widgets.table.GTableFilterPanel; import docking.widgets.table.TableFilter; +import generic.theme.GIcon; import ghidra.app.plugin.core.scalartable.RangeFilterTextField.FilterType; import ghidra.app.services.GoToService; import ghidra.framework.plugintool.ComponentProviderAdapter; @@ -38,7 +39,6 @@ import ghidra.util.table.*; import ghidra.util.table.actions.DeleteTableRowAction; import ghidra.util.table.actions.MakeProgramSelectionAction; import help.HelpService; -import resources.ResourceManager; /** * Displays the results of a query from the {@link ScalarSearchPlugin}. Consists of 2 components: @@ -49,7 +49,7 @@ import resources.ResourceManager; */ public class ScalarSearchProvider extends ComponentProviderAdapter { - public static final ImageIcon ICON = ResourceManager.loadImage("images/dataW.gif"); + public static final Icon ICON = new GIcon("icon.plugin.scalartable.provider"); private ScalarSearchPlugin plugin; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java index d580e9cea3..d7170bf635 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java @@ -38,6 +38,7 @@ import docking.actions.KeyBindingUtils; import docking.tool.ToolConstants; import docking.widgets.table.GTable; import generic.jar.ResourceFile; +import generic.theme.GIcon; import ghidra.app.script.GhidraScriptInfoManager; import ghidra.app.script.ScriptInfo; import ghidra.framework.Application; @@ -45,7 +46,6 @@ import ghidra.framework.options.SaveState; import ghidra.util.*; import ghidra.util.task.*; import resources.Icons; -import resources.ResourceManager; import utilities.util.FileUtilities; class GhidraScriptActionManager { @@ -210,7 +210,7 @@ class GhidraScriptActionManager { private void createActions() { createScriptAction("Run", "Run Script", "Run Script", - ResourceManager.loadImage("images/play.png"), RESOURCE_FILE_ACTION_RUN_GROUP, + new GIcon("icon.plugin.scriptmanager.run"), RESOURCE_FILE_ACTION_RUN_GROUP, provider::runScript); runLastAction = new RerunLastScriptAction(RESOURCE_FILE_ACTION_RUN_GROUP); @@ -220,30 +220,31 @@ class GhidraScriptActionManager { plugin.getTool().addAction(globalRunLastAction); createScriptAction("Edit", "Edit with basic editor", "Edit Script with basic editor", - ResourceManager.loadImage("images/accessories-text-editor.png"), null, + new GIcon("icon.plugin.scriptmanager.edit"), null, provider::editScriptBuiltin); createScriptAction("EditEclipse", "Edit with Eclipse", "Edit Script with Eclipse", - ResourceManager.loadImage("images/eclipse.png"), null, provider::editScriptEclipse); + new GIcon("icon.plugin.scriptmanager.edit.eclipse"), null, provider::editScriptEclipse); keyBindingAction = createScriptAction("Key Binding", "Assign Key Binding", "Assign Key Binding", - ResourceManager.loadImage("images/key.png"), null, provider::assignKeyBinding); + new GIcon("icon.plugin.scriptmanager.keybinding"), null, + provider::assignKeyBinding); createScriptAction("Delete", "Delete", "Delete Script", - ResourceManager.loadImage("images/edit-delete.png"), null, provider::deleteScript); + new GIcon("icon.plugin.scriptmanager.delete"), null, provider::deleteScript); renameAction = createScriptAction("Rename", "Rename", "Rename Script", - ResourceManager.loadImage("images/textfield_rename.png"), null, provider::renameScript); + new GIcon("icon.plugin.scriptmanager.rename"), null, provider::renameScript); newAction = createScriptTableAction("New", "Create New Script", - ResourceManager.loadImage("images/script_add.png"), provider::newScript); + new GIcon("icon.plugin.scriptmanager.new"), provider::newScript); createScriptTableAction("Refresh", "Refresh Script List", Icons.REFRESH_ICON, provider::refresh); showBundleStatusAction = createScriptTableAction("Script Directories", - "Manage Script Directories", ResourceManager.loadImage("images/text_list_bullets.png"), + "Manage Script Directories", new GIcon("icon.plugin.scriptmanager.manage"), provider::showBundleStatusComponent); new ActionBuilder("Script Quick Launch", plugin.getName()) @@ -252,7 +253,7 @@ class GhidraScriptActionManager { .onAction(this::chooseScript) .buildAndInstall(plugin.getTool()); - Icon icon = ResourceManager.loadImage("images/red-cross.png"); + Icon icon = new GIcon("icon.plugin.scriptmanager.api"); Predicate test = context -> { Object contextObject = context.getContextObject(); return (contextObject instanceof GTable) || (contextObject instanceof ResourceFile); @@ -506,7 +507,7 @@ class GhidraScriptActionManager { super(RERUN_LAST_SHARED_ACTION_NAME, plugin.getName(), KeyBindingType.SHARED); setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/play_again.png"), toolbarGroup)); + new ToolBarData(new GIcon("icon.plugin.scriptmanager.run.again"), toolbarGroup)); setDescription("Rerun the last run script"); setHelpLocation(new HelpLocation(plugin.getName(), "Run_Last")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java index ebc7b8fb07..2862efc947 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java @@ -46,6 +46,7 @@ import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; import docking.widgets.tree.support.BreadthFirstIterator; import generic.jar.ResourceFile; +import generic.theme.GIcon; import ghidra.app.plugin.core.osgi.*; import ghidra.app.script.*; import ghidra.app.services.ConsoleService; @@ -57,7 +58,6 @@ import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.task.*; -import resources.ResourceManager; import util.CollectionUtils; import utilities.util.FileUtilities; @@ -126,7 +126,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter { scriptList.addListener(scriptListListener); setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName())); - setIcon(ResourceManager.loadImage("images/play.png")); + setIcon(new GIcon("icon.plugin.scriptmanager.provider")); addToToolbar(); setWindowGroup(WINDOW_GROUP); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptEditorComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptEditorComponentProvider.java index 6c39be52a5..62bbdf4135 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptEditorComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptEditorComponentProvider.java @@ -20,8 +20,6 @@ import java.awt.Font; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.io.*; -import java.util.Collection; -import java.util.Iterator; import javax.swing.*; import javax.swing.text.Document; @@ -30,19 +28,20 @@ import javax.swing.undo.UndoableEdit; import docking.*; import docking.action.*; import docking.actions.KeyBindingUtils; -import docking.options.editor.FontPropertyEditor; +import docking.options.editor.FontEditor; import docking.widgets.OptionDialog; import generic.jar.ResourceFile; +import generic.theme.*; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.script.GhidraScriptUtil; -import ghidra.framework.options.SaveState; import ghidra.util.*; import ghidra.util.datastruct.FixedSizeStack; import resources.Icons; -import resources.ResourceManager; public class GhidraScriptEditorComponentProvider extends ComponentProvider { - static final String EDITOR_COMPONENT_NAME="EDITOR"; - + static final String EDITOR_COMPONENT_NAME = "EDITOR"; + private static final String FONT_ID = "font.plugin.scripts.text.editor"; + static final String CHANGE_DESTINATION_TITLE = "Where Would You Like to Store Your Changes?"; static final String FILE_ON_DISK_CHANGED_TITLE = "File Changed on Disk"; static final String FILE_ON_DISK_MISSING_TITLE = "File on Disk is Missing"; @@ -54,22 +53,6 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { private static final int MAX_UNDO_REDO_SIZE = 50; - private static Font defaultFont = new Font("monospaced", Font.PLAIN, 12); - - static void restoreState(SaveState saveState) { - String name = saveState.getString("DEFAULT_FONT_NAME", "Monospaced"); - int style = saveState.getInt("DEFAULT_FONT_STYLE", Font.PLAIN); - int size = saveState.getInt("DEFAULT_FONT_SIZE", 12); - defaultFont = new Font(name, style, size); - } - - static void saveState(SaveState saveState) { - saveState.putString("DEFAULT_FONT_NAME", defaultFont.getName()); - saveState.putInt("DEFAULT_FONT_STYLE", defaultFont.getStyle()); - saveState.putInt("DEFAULT_FONT_SIZE", defaultFont.getSize()); - } - - private GhidraScriptMgrPlugin plugin; private GhidraScriptComponentProvider provider; private String title; @@ -227,12 +210,13 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { @Override public boolean isEnabledForContext(ActionContext context) { Object contextObject = context.getContextObject(); - return contextObject == GhidraScriptEditorComponentProvider.this && !undoStack.isEmpty(); + return contextObject == GhidraScriptEditorComponentProvider.this && + !undoStack.isEmpty(); } }; undoAction.setDescription("Undo"); undoAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/undo.png"), "UndoRedo")); + new ToolBarData(new GIcon("icon.undo"), "UndoRedo")); undoAction.setEnabled(false); undoAction.setKeyBindingData(new KeyBindingData( KeyStroke.getKeyStroke(KeyEvent.VK_Z, DockingUtils.CONTROL_KEY_MODIFIER_MASK))); @@ -247,12 +231,13 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { @Override public boolean isEnabledForContext(ActionContext context) { Object contextObject = context.getContextObject(); - return contextObject == GhidraScriptEditorComponentProvider.this && !redoStack.isEmpty(); + return contextObject == GhidraScriptEditorComponentProvider.this && + !redoStack.isEmpty(); } }; redoAction.setDescription("Redo"); redoAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/redo.png"), "UndoRedo")); + new ToolBarData(new GIcon("icon.redo"), "UndoRedo")); redoAction.setKeyBindingData(new KeyBindingData( KeyStroke.getKeyStroke(KeyEvent.VK_Y, DockingUtils.CONTROL_KEY_MODIFIER_MASK))); redoAction.setEnabled(false); @@ -280,7 +265,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { }; saveAction.setDescription("Save"); saveAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/disk.png"), "Save")); + new ToolBarData(Icons.SAVE_ICON, "Save")); saveAction.setKeyBindingData(new KeyBindingData( KeyStroke.getKeyStroke(KeyEvent.VK_S, DockingUtils.CONTROL_KEY_MODIFIER_MASK))); @@ -317,7 +302,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { }; saveAsAction.setDescription("Save As..."); saveAsAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/disk_save_as.png"), "Save")); + new ToolBarData(Icons.SAVE_AS_ICON, "Save")); saveAsAction.setEnabled(true); plugin.getTool().addLocalAction(this, saveAsAction); @@ -341,7 +326,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { } }; runAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/play.png"), "ZRun")); + new ToolBarData(new GIcon("icon.plugin.scriptmanager.run"), "ZRun")); runAction.setDescription("Run Editor's Script"); runAction.setPopupMenuData(new MenuData(new String[] { "Run" }, "ZRun")); runAction.setEnabled(true); @@ -355,7 +340,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { } }; fontAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/text_lowercase.png"), "ZZFont")); + new ToolBarData(new GIcon("icon.font"), "ZZFont")); fontAction.setDescription("Select Font"); fontAction.setEnabled(true); plugin.getTool().addLocalAction(this, fontAction); @@ -447,7 +432,8 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { int choice = OptionDialog.showOptionDialog(scrollPane, FILE_ON_DISK_CHANGED_TITLE, "The contents of the script file have changed on disk.
Would " + - "you like to keep your changes in the editor or " + + "you like to keep your changes in the editor or " + "discard your changes?", KEEP_CHANGES_TEXT, DISCARD_CHANGES_TEXT, OptionDialog.QUESTION_MESSAGE); @@ -469,7 +455,9 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { // choice = OptionDialog.showOptionDialog(scrollPane, CHANGE_DESTINATION_TITLE, "You can save your current changes to another file or " + - "overwrite the contents of the file on disk.", + "overwrite the contents of the file on disk.", SAVE_CHANGES_AS_TEXT, OVERWRITE_CHANGES_TEXT, OptionDialog.QUESTION_MESSAGE); // @@ -515,18 +503,11 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { } } - private void doSelectFont() { - FontPropertyEditor editor = new FontPropertyEditor(); - editor.setValue(defaultFont); + protected void doSelectFont() { + FontEditor editor = new FontEditor(); + editor.setValue(Gui.getFont(FONT_ID)); editor.showDialog(); - defaultFont = (Font) editor.getValue(); - - Collectionvalues = provider.getEditorMap().values(); - Iterator iterator = values.iterator(); - while (iterator.hasNext()) { - GhidraScriptEditorComponentProvider editorComponent = iterator.next(); - editorComponent.textArea.setFont(defaultFont); - } + ThemeManager.getInstance().setFont(FONT_ID, (Font) editor.getValue()); } private void save() { @@ -676,7 +657,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider { private KeyMasterTextArea(String text) { super(text); - setFont(defaultFont); + Gui.registerFont(this, FONT_ID); setName(EDITOR_COMPONENT_NAME); setWrapStyleWord(false); Document document = getDocument(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java index f8d22be170..1aba81aaae 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java @@ -78,14 +78,12 @@ public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScript public void readConfigState(SaveState saveState) { super.readConfigState(saveState); provider.readConfigState(saveState); - GhidraScriptEditorComponentProvider.restoreState(saveState); } @Override public void writeConfigState(SaveState saveState) { super.writeConfigState(saveState); provider.writeConfigState(saveState); - GhidraScriptEditorComponentProvider.saveState(saveState); } GhidraState getCurrentState() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java index eb2f335742..884a93febd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java @@ -24,6 +24,8 @@ import javax.swing.event.TableModelEvent; import docking.widgets.table.*; import generic.jar.ResourceFile; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Tables; import ghidra.app.script.GhidraScriptInfoManager; import ghidra.app.script.ScriptInfo; import ghidra.docking.settings.Settings; @@ -39,7 +41,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel scriptList = new ArrayList<>(); @@ -217,8 +219,8 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel super.fireTableChanged(e)); } - private class StatusColumn extends AbstractDynamicTableColumn { - private Comparator comparator = (i1, i2) -> { + private class StatusColumn extends AbstractDynamicTableColumn { + private Comparator comparator = (i1, i2) -> { if (i1 == i2) { return 0; } @@ -234,12 +236,19 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel renderer = new AbstractGColumnRenderer<>() { + private String getDescription(Icon icon) { + if (icon instanceof ImageIcon imageIcon) { + return imageIcon.getDescription(); + } + return icon.getClass().getName(); + } + + private GColumnRenderer renderer = new AbstractGColumnRenderer<>() { @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { JLabel label = (JLabel) super.getTableCellRendererComponent(data); @@ -269,14 +278,14 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel getColumnRenderer() { + public GColumnRenderer getColumnRenderer() { return renderer; } @@ -286,7 +295,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel getComparator() { + public Comparator getComparator() { return comparator; } } @@ -363,7 +372,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel "); - buffy.append(" "); + buffy.append(" "); buffy.append(keyBinding.toString()); buffy.append(""); buffy.append(" "); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java index 5dcfe23bee..257c23cb7f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java @@ -19,7 +19,7 @@ import java.awt.Color; import java.awt.event.KeyEvent; import java.util.*; -import javax.swing.ImageIcon; +import javax.swing.Icon; import javax.swing.JComponent; import docking.*; @@ -27,6 +27,7 @@ import docking.action.*; import docking.tool.ToolConstants; import docking.widgets.fieldpanel.support.Highlight; import docking.widgets.table.threaded.*; +import generic.theme.GIcon; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; import ghidra.app.context.NavigatableActionContext; @@ -57,7 +58,6 @@ import ghidra.util.bean.opteditor.OptionsVetoException; import ghidra.util.search.memory.*; import ghidra.util.table.GhidraProgramTableModel; import ghidra.util.task.*; -import resources.ResourceManager; /** * Class to handle memory searching of code bytes in a program. @@ -92,10 +92,8 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, private MemSearchDialog searchDialog; private GoToService goToService; private int searchLimit; - private ImageIcon searchIcon; + private static final Icon SEARCH_MARKER_ICON = new GIcon("icon.base.search.marker"); - private Color defaultHighlightColor; - private Color activeHighlightColor; private boolean doHighlight; private int byteGroupSize; private String byteDelimiter; @@ -115,7 +113,6 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, public MemSearchPlugin(PluginTool tool) { super(tool); - searchIcon = ResourceManager.loadImage("images/searchm_obj.gif"); createActions(); initializeOptionListeners(); @@ -390,10 +387,11 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_NAME, true, null, "Toggles highlight search results"); - opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_COLOR, null, "The search result highlight color"); - opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR, null, + opt.registerThemeColorBinding(PluginConstants.SEARCH_HIGHLIGHT_COLOR_OPTION_NAME, + PluginConstants.SEARCH_HIGHLIGHT_COLOR.getId(), null, + "The search result highlight color"); + opt.registerThemeColorBinding(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_OPTION_NAME, + PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR.getId(), null, "The search result highlight color for the currently selected match"); opt.addOptionsChangeListener(this); @@ -414,10 +412,6 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, prepopulateSearch = opt.getBoolean(PluginConstants.PRE_POPULATE_MEM_SEARCH, true); autoRestrictSelection = opt.getBoolean(PluginConstants.AUTO_RESTRICT_SELECTION, true); doHighlight = opt.getBoolean(PluginConstants.SEARCH_HIGHLIGHT_NAME, true); - defaultHighlightColor = opt.getColor(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_COLOR); - activeHighlightColor = opt.getColor(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR); opt = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS); byteGroupSize = opt.getInt(BytesFieldFactory.BYTE_GROUP_SIZE_MSG, 1); @@ -510,7 +504,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, String type = "Search"; if (navigatable.supportsMarkers()) { return tableService.showTableWithMarkers(title, type, model, - PluginConstants.SEARCH_HIGHLIGHT_COLOR, searchIcon, type, navigatable); + PluginConstants.SEARCH_HIGHLIGHT_COLOR, SEARCH_MARKER_ICON, type, navigatable); } return tableService.showTable(title, type, model, type, navigatable); } @@ -748,7 +742,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, private Color getHighlightColor(Address highlightStart, int highlightLength) { ProgramLocation location = navigatable != null ? navigatable.getLocation() : null; if (!(location instanceof BytesFieldLocation)) { - return defaultHighlightColor; + return PluginConstants.SEARCH_HIGHLIGHT_COLOR; } BytesFieldLocation byteLoc = (BytesFieldLocation) location; @@ -756,11 +750,12 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, if (highlightStart.hasSameAddressSpace(byteAddress)) { long diff = byteAddress.subtract(highlightStart); if (diff >= 0 && diff < highlightLength) { - return activeHighlightColor; // the current location is in the highlight + // the current location is in the highlight + return PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR; } } - return defaultHighlightColor; + return PluginConstants.SEARCH_HIGHLIGHT_COLOR; } private boolean checkRemoveHighlights() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java index ee8deba1ec..0981bab88b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java @@ -15,19 +15,21 @@ */ package ghidra.app.plugin.core.searchtext; -import java.awt.*; +import java.awt.Component; +import java.awt.KeyboardFocusManager; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.*; import docking.action.builder.ActionBuilder; import docking.tool.ToolConstants; import docking.widgets.fieldpanel.support.Highlight; import docking.widgets.table.threaded.*; +import generic.theme.GIcon; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; import ghidra.app.context.*; @@ -58,7 +60,6 @@ import ghidra.util.*; import ghidra.util.bean.opteditor.OptionsVetoException; import ghidra.util.table.GhidraProgramTableModel; import ghidra.util.task.*; -import resources.ResourceManager; /** * Plugin to search text as it is displayed in the fields of the Code Browser. @@ -88,7 +89,7 @@ import resources.ResourceManager; public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeListener, TaskListener, NavigatableRemovalListener, DockingContextListener { - private static final ImageIcon searchIcon = ResourceManager.loadImage("images/searchm_obj.gif"); + private static final Icon SEARCH_MARKER_ICON = new GIcon("icon.base.search.marker"); private static final String DESCRIPTION = "Search program text for string"; private final static Highlight[] NO_HIGHLIGHTS = new Highlight[0]; @@ -99,8 +100,6 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList private int searchLimit; private SearchTask currentTask; private String lastSearchedText; - private Color highlightColor; - private Color currentAddrHighlightColor; private boolean doHighlight; private Navigatable navigatable; @@ -182,7 +181,6 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList if (searchDialog != null && searchDialog.isVisible()) { TaskMonitor taskMonitor = searchDialog.getTaskMonitorComponent(); - // TODO this can probably be handled by canceling the task below (or vice versa) taskMonitor.cancel(); searchDialog.dispose(); @@ -332,7 +330,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList if (navigatable.supportsMarkers()) { return query.showTableWithMarkers( "Search Text - \"" + searchString + "\" [" + matchType + "]", "Search", model, - PluginConstants.SEARCH_HIGHLIGHT_COLOR, searchIcon, "Search", navigatable); + PluginConstants.SEARCH_HIGHLIGHT_COLOR, SEARCH_MARKER_ICON, "Search", navigatable); } return query.showTable("Search Text - \"" + searchString + "\" [" + matchType + "]", "Search", model, "Search", navigatable); @@ -425,12 +423,6 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList } searchLimit = newSearchLimit; } - else if (optionName.equals(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME)) { - currentAddrHighlightColor = (Color) newValue; - } - else if (optionName.equals(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME)) { - highlightColor = (Color) newValue; - } else if (optionName.equals(PluginConstants.SEARCH_HIGHLIGHT_NAME)) { doHighlight = ((Boolean) newValue).booleanValue(); } @@ -443,22 +435,17 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_NAME, true, loc, "Determines whether to highlight the matched string for a search in the listing."); - opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_COLOR, loc, - "Color to use when highlighting the matched string for a search in the listing."); - opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_COLOR, loc, - "Color to use for highlighting when the match string occurs at the current address."); + opt.registerThemeColorBinding(PluginConstants.SEARCH_HIGHLIGHT_COLOR_OPTION_NAME, + PluginConstants.SEARCH_HIGHLIGHT_COLOR.getId(), null, + "The search result highlight color"); + opt.registerThemeColorBinding(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_OPTION_NAME, + PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR.getId(), null, + "The search result highlight color for the currently selected match"); searchLimit = opt.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, PluginConstants.DEFAULT_SEARCH_LIMIT); doHighlight = opt.getBoolean(PluginConstants.SEARCH_HIGHLIGHT_NAME, true); - highlightColor = opt.getColor(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_COLOR); - currentAddrHighlightColor = - opt.getColor(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR); opt.setOptionsHelpLocation(new HelpLocation(HelpTopics.SEARCH, "Search_Text")); @@ -662,12 +649,14 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList int start = matcher.start(); int end = matcher.end() - 1; if (start <= cursorTextOffset && end >= cursorTextOffset) { - list.add(new Highlight(start, end, currentAddrHighlightColor)); + list.add(new Highlight(start, end, + PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR)); } else if (loc == null) { // only add in matches around current match if loc is null // meaning that this is a one at a time search and not a table // of results. - list.add(new Highlight(start, end, highlightColor)); + list.add(new Highlight(start, end, + PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR)); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/spaceview/GhidraColorMap.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/spaceview/GhidraColorMap.java deleted file mode 100644 index 3b3cf9c6d9..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/spaceview/GhidraColorMap.java +++ /dev/null @@ -1,107 +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.spaceview; - -import java.awt.Color; -import java.awt.image.IndexColorModel; - -public class GhidraColorMap { - - /* - tier 1 - - undefined (GRAY) - zero (BLACK) - low (DARK ORANGE) - whitespace (PALE BLUE) - digit (LIGHT BLUE) - upper (LIGHT BLUE) - lower (MED BLUE) - symbol (DARK BLUE) - high (DARK RED) - full (-1, 255) (WHITE) - - tier 2 - - float? (GREEN) - double? (GREEN) - int? (ORANGE) - long? (ORANGE) - instruction? (PINK) - address? (YELLOW) - - tier 3 - - SEAFOAM - defined data (simple types) - defined data (structs) - defined data (unions) - - MAGENTA - code (memory) - code (flow) - code (special) - code (normal) - - PURPLE - fun code (memory) - fun code (flow) - fun code (special) - fun code (normal) - - RED - error bookmarks - - tier 4 - - selected (BRIGHT GREEN) - highlighted (BRIGHT YELLOW) - selected and highlighted (BRIGHT YELLOW GREEN) - - immutables needed: - - segmenting - hilbert ordering - maximuming - from array - cache - iterator - - also: - - bijection from address to index in array space - bijection from pixelspace to indexspace - */ - - public IndexColorModel getColorModel() { - Color[] colors = - new Color[] { new Color(190, 255, 0), Color.red, new Color(128, 128, 128), Color.cyan, - Color.magenta, }; - - byte[] red = new byte[colors.length]; - byte[] grn = new byte[colors.length]; - byte[] blu = new byte[colors.length]; - for (int ii = 0; ii < colors.length; ++ii) { - red[ii] = (byte) colors[ii].getRed(); - grn[ii] = (byte) colors[ii].getGreen(); - blu[ii] = (byte) colors[ii].getBlue(); - } - IndexColorModel colorModel = new IndexColorModel(8, colors.length, red, grn, blu); - - return colorModel; - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/spaceview/SpacecurveRasterPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/spaceview/SpacecurveRasterPanel.java deleted file mode 100644 index 566e82fae9..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/spaceview/SpacecurveRasterPanel.java +++ /dev/null @@ -1,99 +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.spaceview; - -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.image.*; -import java.util.Hashtable; - -import javax.swing.JFrame; -import javax.swing.JPanel; - -public class SpacecurveRasterPanel extends JPanel { - protected static final Hashtable, ?> EMPTY_HASHTABLE = new Hashtable
- - Next + � +�Next diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidDebugUtils.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidDebugUtils.java index 4e3b2e2423..e6a27900f4 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidDebugUtils.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidDebugUtils.java @@ -15,7 +15,6 @@ */ package ghidra.feature.fid.debug; -import java.awt.Font; import java.util.*; import javax.swing.*; @@ -29,7 +28,6 @@ import ghidra.util.NumericUtilities; * Utility class to handle some debug functions for the FID database. */ public class FidDebugUtils { - public static final Font MONOSPACED_FONT = new Font("monospaced", Font.PLAIN, 12); /** * Search the FID system for function records by name substring. diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidFunctionDebugPanel.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidFunctionDebugPanel.java index bed86e1b2c..68d6a58835 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidFunctionDebugPanel.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidFunctionDebugPanel.java @@ -21,6 +21,8 @@ import java.awt.event.ActionListener; import javax.swing.*; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults; +import generic.theme.Gui; import ghidra.feature.fid.db.*; import ghidra.feature.fid.service.FidService; import ghidra.program.model.lang.LanguageID; @@ -55,7 +57,7 @@ public class FidFunctionDebugPanel extends JPanel { JButton button = new JButton(text); button.addActionListener(listener); button.setHorizontalAlignment(SwingConstants.LEFT); - button.setFont(FidDebugUtils.MONOSPACED_FONT); + Gui.registerFont(button, GThemeDefaults.Ids.Fonts.MONOSPACED); add(button); } @@ -66,7 +68,7 @@ public class FidFunctionDebugPanel extends JPanel { private void addLabel(String text) { JLabel label = new GDLabel(text); label.setHorizontalAlignment(SwingConstants.LEFT); - label.setFont(FidDebugUtils.MONOSPACED_FONT); + label.setFont(Gui.getFont("font.monospaced")); add(label); } diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchDebugDialog.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchDebugDialog.java index 817ca11cbe..3ba1bb1279 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchDebugDialog.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchDebugDialog.java @@ -21,6 +21,8 @@ import javax.swing.*; import docking.DialogComponentProvider; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults.Ids.Fonts; +import generic.theme.Gui; import ghidra.feature.fid.db.FidFileManager; import ghidra.feature.fid.db.FidQueryService; import ghidra.feature.fid.plugin.FidPlugin; @@ -75,13 +77,13 @@ public class FidSearchDebugDialog extends DialogComponentProvider { private JLabel getPreparedLabel(String text) { JLabel label = new GDLabel(text, SwingConstants.RIGHT); - label.setFont(FidDebugUtils.MONOSPACED_FONT); + label.setFont(Gui.getFont(Fonts.MONOSPACED)); return label; } private JTextField getPreparedTextField() { JTextField textField = new JTextField(25); - textField.setFont(FidDebugUtils.MONOSPACED_FONT); + textField.setFont(Gui.getFont(Fonts.MONOSPACED)); return textField; } diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java index 2824cb401a..1e246cedc7 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java @@ -26,6 +26,8 @@ import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import docking.widgets.table.*; +import generic.theme.GThemeDefaults.Ids.Fonts; +import generic.theme.Gui; import ghidra.feature.fid.db.*; import ghidra.feature.fid.service.FidService; import ghidra.util.Msg; @@ -64,7 +66,7 @@ public class FidSearchResultFrame extends JFrame implements FidQueryCloseListene private void buildFrame() { GTableCellRenderer renderer = new GTableCellRenderer(); - renderer.setFont(FidDebugUtils.MONOSPACED_FONT); + renderer.setFont(Gui.getFont(Fonts.MONOSPACED)); int columnCount = table.getColumnCount(); for (int ii = 0; ii < columnCount; ++ii) { Class> columnClass = table.getColumnClass(ii); diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/ActiveFidConfigureDialog.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/ActiveFidConfigureDialog.java index e9530bb460..2f14e305a9 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/ActiveFidConfigureDialog.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/ActiveFidConfigureDialog.java @@ -24,6 +24,7 @@ import javax.swing.*; import docking.DialogComponentProvider; import docking.widgets.checkbox.GCheckBox; +import generic.theme.GThemeDefaults; import ghidra.feature.fid.db.FidFile; import ghidra.util.HelpLocation; import ghidra.util.layout.VerticalLayout; @@ -89,7 +90,7 @@ public class ActiveFidConfigureDialog extends DialogComponentProvider { private Component buildCheckBoxPanel() { JPanel panel = new JPanel(new VerticalLayout(5)); panel.setOpaque(true); - panel.setBackground(Color.WHITE); + panel.setBackground(GThemeDefaults.Colors.BACKGROUND); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); for (FidFile fidFile : fidFiles) { GCheckBox checkbox = new GCheckBox(fidFile.getName(), fidFile.isActive()); diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java index 9ea0309e4e..5fdb212694 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java @@ -15,7 +15,8 @@ */ package ghidra.feature.fid.plugin; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -279,10 +280,7 @@ public class PopulateFidDialog extends DialogComponentProvider { } private JButton createBrowseButton() { - JButton browseButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE); - Font font = browseButton.getFont(); - browseButton.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - return browseButton; + return ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE); } private static class LibraryChoice { diff --git a/Ghidra/Features/GraphFunctionCalls/certification.manifest b/Ghidra/Features/GraphFunctionCalls/certification.manifest index f6a0d9a87d..90d6cbdf19 100644 --- a/Ghidra/Features/GraphFunctionCalls/certification.manifest +++ b/Ghidra/Features/GraphFunctionCalls/certification.manifest @@ -1,6 +1,7 @@ ##VERSION: 2.0 ##MODULE IP: Oxygen Icons - LGPL 3.0 Module.manifest||GHIDRA||||END| +data/functioncallgraph.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| src/main/help/help/shared/close16.gif||GHIDRA||||END| diff --git a/Ghidra/Features/GraphFunctionCalls/data/functioncallgraph.theme.properties b/Ghidra/Features/GraphFunctionCalls/data/functioncallgraph.theme.properties new file mode 100644 index 0000000000..ff7fa7a791 --- /dev/null +++ b/Ghidra/Features/GraphFunctionCalls/data/functioncallgraph.theme.properties @@ -0,0 +1,29 @@ +[Defaults] + +color.bg.fcg.vertex.default = rgb(110, 197, 174) // chill green +color.bg.fcg.vertex.toobig = color.palette.lightgray + +color.bg.fcg.edge.primary.direct = rgb(143, 197, 143) // light pale green +color.bg.fcg.edge.primary.direct.selected = rgb(68, 171, 96) // lighter green +color.bg.fcg.edge.primary.indirect = rgb(233, 233, 233) // lightGray +color.bg.fcg.edge.primary.indirect.selected = rgb(201, 195, 195) + +// the satellite gets too cluttered, so wash out the edges +color.bg.fcg.edge.satellite.direct = rgba(0,0,0,0.1) // 'washed out black' +color.bg.fcg.edge.satellite.indirect = rgba(125, 125, 125, 25) // 'washed out gray' + +icon.fcg.layout.bow.tie = color_swatch.png + + +[Dark Defaults] + +// TODO dark colors +// TODO color.bg.fcg.vertex.default = rgb(110, 197, 174) // chill green +// TODO color.bg.fcg.vertex.toobig = color.palette.lightGray + +// TODO color.bg.fcg.edge.primary.direct = rgb(143, 197, 143) // lightGreen +// TODO color.bg.fcg.edge.primary.indirect = rgb(233, 233, 233) // lightGray + +// the satellite gets too cluttered, so wash out the edges +// TODO color.bg.fcg.edge.satellite.direct = rgba(0,0,0,0.1) // 'washed out black' +// TODO color.bg.fcg.edge.satellite.indirect = rgba(125, 125, 125, 25) // 'washed out gray' \ No newline at end of file diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java index 2f8a1e73ef..e69ca9448c 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java @@ -28,6 +28,9 @@ import javax.swing.border.LineBorder; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDLabel; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Palette; +import generic.theme.Gui; import ghidra.graph.viewer.vertex.AbstractVisualVertex; import ghidra.graph.viewer.vertex.VertexShapeProvider; import ghidra.program.model.address.Address; @@ -41,9 +44,10 @@ import resources.ResourceManager; */ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvider { - // TODO to be made an option in an upcoming ticket - public static final Color DEFAULT_VERTEX_SHAPE_COLOR = new Color(110, 197, 174); - private static final Color TOO_BIG_VERTEX_SHAPE_COLOR = Color.LIGHT_GRAY; + //@formatter:off + public static final Color DEFAULT_VERTEX_SHAPE_COLOR = new GColor("color.bg.fcg.vertex.default"); + private static final Color TOO_BIG_VERTEX_SHAPE_COLOR = new GColor("color.bg.fcg.vertex.toobig"); + //@formatter:on public static final Icon NOT_ALLOWED_ICON = Icons.ERROR_ICON; private static final Icon EXPAND_ICON = @@ -52,9 +56,9 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid ResourceManager.getScaledIcon(Icons.COLLAPSE_ALL_ICON, 10, 10); // higher numbered layers go on top - private static final Integer VERTEX_SHAPE_LAYER = new Integer(100); - private static final Integer TOGGLE_BUTTON_LAYER = new Integer(200); - private static final Integer LABEL_LAYER = new Integer(300); + private static final Integer VERTEX_SHAPE_LAYER = 100; + private static final Integer TOGGLE_BUTTON_LAYER = 200; + private static final Integer LABEL_LAYER = 300; private static final int GAP = 2; private static final int VERTEX_SHAPE_SIZE = 50; @@ -128,8 +132,8 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid Color vertexShapeColor = getVertexShapeColor(); Color lightColor = vertexShapeColor; - Color darkColor = vertexShapeColor.darker(); - Color darkestColor = darkColor.darker(); + Color darkColor = Gui.darker(vertexShapeColor); + Color darkestColor = Gui.darker(darkColor); int offset = 5 * level.getDistance(); int half = VERTEX_SHAPE_SIZE / 2; int start = 0; @@ -156,7 +160,7 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid // calculate the needed size layeredPane = new JLayeredPane(); - Border border = createDebugBorder(new LineBorder(Color.YELLOW.darker(), 1)); + Border border = createDebugBorder(new LineBorder(Palette.GOLD, 1)); layeredPane.setBorder(border); updateLayeredPaneSize(); @@ -246,7 +250,7 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid compactShape = (Double) vertexShape.clone(); vertexImageLabel.setIcon(new ImageIcon(image)); - Border border = createDebugBorder(new LineBorder(Color.PINK, 1)); + Border border = createDebugBorder(new LineBorder(Palette.PINK, 1)); vertexImageLabel.setBorder(border); } @@ -295,7 +299,7 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid private void addNameLabel() { - Border border = createDebugBorder(new LineBorder(Color.GREEN, 1)); + Border border = createDebugBorder(new LineBorder(Palette.GREEN, 1)); nameLabel.setBorder(border); // assume the vertex label has been bounded @@ -312,8 +316,8 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid private void addToggleButtons() { // hide the button background - toggleInsButton.setBackground(new Color(255, 255, 255, 0)); - toggleOutsButton.setBackground(new Color(255, 255, 255, 0)); + toggleInsButton.setBackground(Palette.NO_COLOR); + toggleOutsButton.setBackground(Palette.NO_COLOR); Rectangle parentBounds = vertexImageLabel.getBounds(); Dimension size = toggleInsButton.getPreferredSize(); @@ -546,7 +550,7 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid /** * Sets whether this vertex has any outgoing references * - * @param hasIncoming true if this vertex has any incoming references + * @param hasOutgoing true if this vertex has any outgoing references */ public void setHasOutgoingReferences(boolean hasOutgoing) { diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/layout/BowTieLayoutProvider.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/layout/BowTieLayoutProvider.java index 3d5985820a..ad87a802e2 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/layout/BowTieLayoutProvider.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/layout/BowTieLayoutProvider.java @@ -18,11 +18,11 @@ package functioncalls.graph.layout; import javax.swing.Icon; import functioncalls.graph.*; +import generic.theme.GIcon; import ghidra.graph.viewer.layout.AbstractLayoutProvider; import ghidra.graph.viewer.layout.VisualGraphLayout; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; /** * A layout provider for the {@link BowTieLayout} @@ -32,7 +32,7 @@ public class BowTieLayoutProvider public static final String NAME = "Bow Tie Layout"; - private static final Icon DEFAULT_ICON = ResourceManager.loadImage("images/color_swatch.png"); + private static final Icon DEFAULT_ICON = new GIcon("icon.fcg.layout.bow.tie"); @Override public VisualGraphLayout
- - Next + � +�Next - Function ID +Function ID� - Function ID Plug-in +�Function ID Plug-in getLayout(FunctionCallGraph graph, diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/renderer/FcgEdgePaintTransformer.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/renderer/FcgEdgePaintTransformer.java index 7b09ef621d..428aa3555e 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/renderer/FcgEdgePaintTransformer.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/renderer/FcgEdgePaintTransformer.java @@ -16,18 +16,17 @@ package functioncalls.graph.renderer; import java.awt.Color; -import java.awt.Paint; import com.google.common.base.Function; import functioncalls.graph.FcgEdge; +import ghidra.util.ColorUtils; /** * Generates colors for a given {@link FcgEdge} */ -public class FcgEdgePaintTransformer implements Function { +public class FcgEdgePaintTransformer implements Function { - // private static final Paint LESS_IMPORTANT_COLOR = new Color(125, 125, 125, 75); private Color directColor; private Color indirectColor; @@ -46,13 +45,13 @@ public class FcgEdgePaintTransformer implements Function { alphad[0] = c; for (int i = 1; i < 10; i++) { double newAlpha = 255 - (i * 25.5); - alphad[i] = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int) newAlpha); + alphad[i] = ColorUtils.withAlpha(c, (int) newAlpha); } return alphad; } @Override - public Paint apply(FcgEdge e) { + public Color apply(FcgEdge e) { if (e.isDirectEdge()) { return getDirectEdgeColor(e); } diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgComponent.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgComponent.java index b39e333a70..a1a516bffc 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgComponent.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/view/FcgComponent.java @@ -15,15 +15,17 @@ */ package functioncalls.graph.view; -import java.awt.Color; - -import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.renderers.Renderer; import functioncalls.graph.*; import functioncalls.graph.renderer.FcgEdgePaintTransformer; import functioncalls.graph.renderer.FcgVertexPaintTransformer; import functioncalls.plugin.FunctionCallGraphPlugin; +import generic.theme.GColor; import ghidra.graph.viewer.*; +import ghidra.graph.viewer.edge.VisualEdgeRenderer; import ghidra.graph.viewer.layout.VisualGraphLayout; +import ghidra.graph.viewer.renderer.VisualVertexSatelliteRenderer; +import ghidra.graph.viewer.vertex.VisualVertexRenderer; /** * A graph component for the {@link FunctionCallGraphPlugin} @@ -33,23 +35,20 @@ public class FcgComponent extends GraphComponent renderContext = viewer.getRenderContext(); - renderContext.setVertexFillPaintTransformer(vertexPaintTransformer); - - // Note: setting the fill for the edges has the effect of drawing a filled-in circle - // instead of just the outer edge. - // renderContext.setEdgeFillPaintTransformer(edgePaintTransformer); - renderContext.setEdgeDrawPaintTransformer(edgePaintTransformer); - renderContext.setArrowFillPaintTransformer(edgePaintTransformer); - renderContext.setArrowDrawPaintTransformer(edgePaintTransformer); + Renderer renderer = viewer.getRenderer(); + VisualVertexRenderer vertexRenderer = + (VisualVertexRenderer ) renderer.getVertexRenderer(); + vertexRenderer.setVertexFillPaintTransformer(vertexPaintTransformer); + VisualEdgeRenderer edgeRenderer = + (VisualEdgeRenderer ) renderer.getEdgeRenderer(); + edgeRenderer.setDrawColorTransformer(edgePaintTransformer); + edgeRenderer.setSelectedColorTransformer(selectedEdgePaintTransformer); } @Override @@ -83,12 +81,14 @@ public class FcgComponent extends GraphComponent renderContext = viewer.getRenderContext(); - renderContext.setVertexFillPaintTransformer(vertexPaintTransformer); - //renderContext.setEdgeFillPaintTransformer(satelliteEdgePaintTransformer); - renderContext.setEdgeDrawPaintTransformer(satelliteEdgePaintTransformer); - renderContext.setArrowFillPaintTransformer(satelliteEdgePaintTransformer); - renderContext.setArrowDrawPaintTransformer(satelliteEdgePaintTransformer); + Renderer renderer = viewer.getRenderer(); + VisualVertexSatelliteRenderer vertexRenderer = + (VisualVertexSatelliteRenderer ) renderer.getVertexRenderer(); + vertexRenderer.setVertexFillPaintTransformer(vertexPaintTransformer); + + VisualEdgeRenderer edgeRenderer = + (VisualEdgeRenderer ) renderer.getEdgeRenderer(); + edgeRenderer.setDrawColorTransformer(satelliteEdgePaintTransformer); } @Override diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java index b35dea5d95..3e95ee994e 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/plugin/FunctionCallGraphPlugin.java @@ -146,9 +146,6 @@ public class FunctionCallGraphPlugin extends ProgramPlugin implements OptionsCha } }; -// TODO create icon from scratch: bow-tie -// ImageIcon icon = ResourceManager.loadImage("images/applications-development.png"); -// showProviderAction.setToolBarData(new ToolBarData(icon, "View")); tool.addAction(showProviderAction); } diff --git a/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java b/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java index ea448159ba..3750614fd2 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java +++ b/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java @@ -116,7 +116,7 @@ public class FunctionCallGraphPluginScreenShots extends GhidraScreenShotGenerato area.width += (2 * offset); area.height += (2 * offset); - // drawRectangle(Color.ORANGE, area, 5); + // drawRectangle(Palette.ORANGE, area, 5); crop(area); } diff --git a/Ghidra/Features/GraphServices/certification.manifest b/Ghidra/Features/GraphServices/certification.manifest index 5e1c86fb2f..60b91eadd8 100644 --- a/Ghidra/Features/GraphServices/certification.manifest +++ b/Ghidra/Features/GraphServices/certification.manifest @@ -8,6 +8,7 @@ ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| +data/graphservices.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||||END| src/main/help/help/shared/note.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| diff --git a/Ghidra/Features/GraphServices/data/graphservices.theme.properties b/Ghidra/Features/GraphServices/data/graphservices.theme.properties new file mode 100644 index 0000000000..8597c26296 --- /dev/null +++ b/Ghidra/Features/GraphServices/data/graphservices.theme.properties @@ -0,0 +1,3 @@ +[Defaults] + +color.bg.graph = color.bg \ No newline at end of file diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java index 8112de9a9c..5c41fb824f 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java @@ -30,6 +30,7 @@ import javax.swing.event.EventListenerList; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; +import generic.theme.GThemeDefaults.Colors; import ghidra.service.graph.Attributed; /** @@ -60,8 +61,7 @@ public class AttributeFilters implements ItemSelectable { /** * a {@link Function} to allow custom coloring of the individual toolkit button foreground */ - private Function paintFunction = v -> Color.black; - + private Function paintFunction = v -> Colors.FOREGROUND; /** * @param excluded ignored keys diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 21263deb25..ad1dedf0e0 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -52,6 +52,8 @@ import docking.menu.MultiStateDockingAction; import docking.options.editor.OptionsDialog; import docking.widgets.EventTrigger; import docking.widgets.OptionDialog; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; import generic.util.WindowUtilities; import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; @@ -78,6 +80,8 @@ public class DefaultGraphDisplay implements GraphDisplay { private static final Dimension PREFERRED_VIEW_SIZE = new Dimension(1000, 1000); private static final Dimension PREFERRED_LAYOUT_SIZE = new Dimension(3000, 3000); + private static Color BACKGROUND_COLOR = new GColor("color.bg.graph"); + // layout algorithm categories static final String MIN_CROSS = "Hierarchical MinCross"; static final String VERT_MIN_CROSS = "Vertical Hierarchical MinCross"; @@ -187,8 +191,7 @@ public class DefaultGraphDisplay implements GraphDisplay { if (graphDisplayProvider.getDefaultSatelliteState()) { viewer.getComponent().add(satelliteViewer.getComponent()); } - layoutTransitionManager = - new LayoutTransitionManager(viewer, this::isRoot, graphRenderer); + layoutTransitionManager = new LayoutTransitionManager(viewer, this::isRoot, graphRenderer); viewer.getComponent().addComponentListener(new ComponentAdapter() { @Override @@ -203,9 +206,9 @@ public class DefaultGraphDisplay implements GraphDisplay { } }); - viewer.setInitialDimensionFunction(InitialDimensionFunction - .builder(viewer.getRenderContext().getVertexBoundsFunction()) - .build()); + viewer.setInitialDimensionFunction( + InitialDimensionFunction.builder(viewer.getRenderContext().getVertexBoundsFunction()) + .build()); createToolbarActions(); createPopupActions(); connectSelectionStateListeners(); @@ -260,9 +263,8 @@ public class DefaultGraphDisplay implements GraphDisplay { } }; - MutableTransformer transformer = viewer.getRenderContext() - .getMultiLayerTransformer() - .getTransformer(VIEW); + MutableTransformer transformer = + viewer.getRenderContext().getMultiLayerTransformer().getTransformer(VIEW); MagnifyShapeTransformer shapeTransformer = MagnifyShapeTransformer.builder(lens) // this lens' delegate is the viewer's VIEW layer, abandoned above @@ -283,23 +285,21 @@ public class DefaultGraphDisplay implements GraphDisplay { viewer.removePostRenderPaintable(singleSelectedVertexPaintable); // for highlighting of multiple selected vertices - this.multiSelectedVertexPaintable = - MultiSelectedVertexPaintable.builder(viewer) - .selectionStrokeMin(15.f) - .selectionPaint(getSelectedVertexColor()) - .useBounds(true) - .useOval(true) - .highlightScale(1.15) - .fillHighlight(false) - .build(); + this.multiSelectedVertexPaintable = MultiSelectedVertexPaintable.builder(viewer) + .selectionStrokeMin(15.f) + .selectionPaint(getSelectedVertexColor()) + .useBounds(true) + .useOval(true) + .highlightScale(1.15) + .fillHighlight(false) + .build(); // manages highlight painting of a single selected vertex - this.singleSelectedVertexPaintable = - SingleSelectedVertexPaintable.builder(viewer) - .selectionStrokeMin(4.f) - .selectionPaint(getSelectedVertexColor()) - .selectedVertexFunction(vs -> this.focusedVertex) - .build(); + this.singleSelectedVertexPaintable = SingleSelectedVertexPaintable.builder(viewer) + .selectionStrokeMin(4.f) + .selectionPaint(getSelectedVertexColor()) + .selectedVertexFunction(vs -> this.focusedVertex) + .build(); // draws the selection highlights viewer.addPreRenderPaintable(multiSelectedVertexPaintable); @@ -352,8 +352,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .buildAndInstallLocal(componentProvider); // create an icon button to reset the view transformations to identity (scaled to layout) - new ActionBuilder("Reset View", ACTION_OWNER) - .description("Fit Graph to Window") + new ActionBuilder("Reset View", ACTION_OWNER).description("Fit Graph to Window") .toolBarIcon(DefaultDisplayGraphIcons.FIT_TO_WINDOW) .onAction(context -> centerAndScale()) .buildAndInstallLocal(componentProvider); @@ -363,8 +362,8 @@ public class DefaultGraphDisplay implements GraphDisplay { ToggleDockingAction lensToggle = new ToggleActionBuilder("View Magnifier", ACTION_OWNER) .description("Show View Magnifier") .toolBarIcon(DefaultDisplayGraphIcons.VIEW_MAGNIFIER_ICON) - .onAction(context -> magnifyViewSupport.activate( - ((AbstractButton) context.getSourceObject()).isSelected())) + .onAction(context -> magnifyViewSupport + .activate(((AbstractButton) context.getSourceObject()).isSelected())) .build(); magnifyViewSupport.addItemListener( itemEvent -> lensToggle.setSelected(itemEvent.getStateChange() == ItemEvent.SELECTED)); @@ -388,40 +387,35 @@ public class DefaultGraphDisplay implements GraphDisplay { } private void createPopupActions() { - new ActionBuilder("Select Vertex", ACTION_OWNER) - .popupMenuPath("Select Vertex") + new ActionBuilder("Select Vertex", ACTION_OWNER).popupMenuPath("Select Vertex") .popupMenuGroup("selection", "1") .withContext(VertexGraphActionContext.class) .enabledWhen(c -> !isSelected(c.getClickedVertex())) .onAction(c -> viewer.getSelectedVertexState().select(c.getClickedVertex())) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Deselect Vertex", ACTION_OWNER) - .popupMenuPath("Deselect Vertex") + new ActionBuilder("Deselect Vertex", ACTION_OWNER).popupMenuPath("Deselect Vertex") .popupMenuGroup("selection", "2") .withContext(VertexGraphActionContext.class) .enabledWhen(c -> isSelected(c.getClickedVertex())) .onAction(c -> viewer.getSelectedVertexState().deselect(c.getClickedVertex())) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Select Edge", ACTION_OWNER) - .popupMenuPath("Select Edge") + new ActionBuilder("Select Edge", ACTION_OWNER).popupMenuPath("Select Edge") .popupMenuGroup("selection", "1") .withContext(EdgeGraphActionContext.class) .enabledWhen(c -> !isSelected(c.getClickedEdge())) .onAction(c -> selectEdge(c.getClickedEdge())) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Deselect Edge", ACTION_OWNER) - .popupMenuPath("Deselect Edge") + new ActionBuilder("Deselect Edge", ACTION_OWNER).popupMenuPath("Deselect Edge") .popupMenuGroup("selection", "2") .withContext(EdgeGraphActionContext.class) .enabledWhen(c -> isSelected(c.getClickedEdge())) .onAction(c -> deselectEdge(c.getClickedEdge())) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Edge Source", ACTION_OWNER) - .popupMenuPath("Go To Edge Source") + new ActionBuilder("Edge Source", ACTION_OWNER).popupMenuPath("Go To Edge Source") .popupMenuGroup("Go To") .withContext(EdgeGraphActionContext.class) .onAction(c -> { @@ -430,8 +424,7 @@ public class DefaultGraphDisplay implements GraphDisplay { }) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Edge Target", ACTION_OWNER) - .popupMenuPath("Go To Edge Target") + new ActionBuilder("Edge Target", ACTION_OWNER).popupMenuPath("Go To Edge Target") .popupMenuGroup("Go To") .withContext(EdgeGraphActionContext.class) .onAction(c -> { @@ -440,12 +433,12 @@ public class DefaultGraphDisplay implements GraphDisplay { }) .buildAndInstallLocal(componentProvider); - hideSelectedAction = new ToggleActionBuilder("Hide Selected", ACTION_OWNER) - .popupMenuPath("Hide Selected") - .popupMenuGroup("z", "1") - .description("Toggles whether or not to show selected vertices and edges") - .onAction(c -> manageVertexDisplay()) - .buildAndInstallLocal(componentProvider); + hideSelectedAction = + new ToggleActionBuilder("Hide Selected", ACTION_OWNER).popupMenuPath("Hide Selected") + .popupMenuGroup("z", "1") + .description("Toggles whether or not to show selected vertices and edges") + .onAction(c -> manageVertexDisplay()) + .buildAndInstallLocal(componentProvider); hideUnselectedAction = new ToggleActionBuilder("Hide Unselected", ACTION_OWNER) .popupMenuPath("Hide Unselected") @@ -454,8 +447,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .onAction(c -> manageVertexDisplay()) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Invert Selection", ACTION_OWNER) - .popupMenuPath("Invert Selection") + new ActionBuilder("Invert Selection", ACTION_OWNER).popupMenuPath("Invert Selection") .popupMenuGroup("z", "3") .description("Inverts the current selection") .onAction(c -> invertSelection()) @@ -493,8 +485,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .onAction(c -> growSelection(getAllComponentVerticesFromSelected())) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Clear Selection", ACTION_OWNER) - .popupMenuPath("Clear Selection") + new ActionBuilder("Clear Selection", ACTION_OWNER).popupMenuPath("Clear Selection") .popupMenuGroup("z", "5") .keyBinding("escape") .enabledWhen(c -> hasSelection()) @@ -516,8 +507,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .onAction(c -> groupSelectedVertices()) .buildAndInstallLocal(componentProvider); - new ActionBuilder("Expand Selected", ACTION_OWNER) - .popupMenuPath("Expand Selected Vertices") + new ActionBuilder("Expand Selected", ACTION_OWNER).popupMenuPath("Expand Selected Vertices") .popupMenuGroup("zz", "6") .description("Expands all selected collapsed vertices into their previous form") .onAction(c -> ungroupSelectedVertices()) @@ -579,8 +569,8 @@ public class DefaultGraphDisplay implements GraphDisplay { private void askToNameGroupVertex(AttributedVertex vertex) { String name = vertex.getName(); - String userName = OptionDialog.showInputMultilineDialog(null, "Enter Group Vertex Text", - "Text", name); + String userName = + OptionDialog.showInputMultilineDialog(null, "Enter Group Vertex Text", "Text", name); updateVertexName(vertex, userName != null ? userName : name); } @@ -602,8 +592,7 @@ public class DefaultGraphDisplay implements GraphDisplay { } private boolean hasSelection() { - return !(viewer.getSelectedVertices().isEmpty() && - viewer.getSelectedEdges().isEmpty()); + return !(viewer.getSelectedVertices().isEmpty() && viewer.getSelectedEdges().isEmpty()); } private boolean isSelected(AttributedVertex v) { @@ -648,15 +637,11 @@ public class DefaultGraphDisplay implements GraphDisplay { // select all the edges that connect the supplied vertices private void selectEdgesConnecting(Collection vertices) { - Set edges = graph.edgeSet() - .stream() - .filter( - e -> { - AttributedVertex source = graph.getEdgeSource(e); - AttributedVertex target = graph.getEdgeTarget(e); - return vertices.contains(source) && vertices.contains(target); - }) - .collect(Collectors.toSet()); + Set edges = graph.edgeSet().stream().filter(e -> { + AttributedVertex source = graph.getEdgeSource(e); + AttributedVertex target = graph.getEdgeTarget(e); + return vertices.contains(source) && vertices.contains(target); + }).collect(Collectors.toSet()); viewer.getSelectedEdgeState().select(edges); } @@ -813,12 +798,9 @@ public class DefaultGraphDisplay implements GraphDisplay { private SatelliteVisualizationViewer createSatelliteViewer( VisualizationViewer parentViewer) { Dimension viewerSize = parentViewer.getSize(); - Dimension satelliteSize = new Dimension( - viewerSize.width / 4, viewerSize.height / 4); + Dimension satelliteSize = new Dimension(viewerSize.width / 4, viewerSize.height / 4); final SatelliteVisualizationViewer satellite = - SatelliteVisualizationViewer.builder(parentViewer) - .viewSize(satelliteSize) - .build(); + SatelliteVisualizationViewer.builder(parentViewer).viewSize(satelliteSize).build(); // // JUNGRAPHT CHANGE 3 @@ -1044,7 +1026,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .elements(vertices) .maxFactor(.05) .buttonSupplier(JRadioButton::new) - .paintFunction(v -> Color.BLACK) + .paintFunction(v -> Colors.FOREGROUND) .build(); vertexFilters.addItemListener(item -> { @@ -1062,7 +1044,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .elements(edges) .maxFactor(.01) .buttonSupplier(JRadioButton::new) - .paintFunction(e -> Color.BLACK) + .paintFunction(e -> Colors.FOREGROUND) .build(); edgeFilters.addItemListener(item -> { @@ -1124,10 +1106,8 @@ public class DefaultGraphDisplay implements GraphDisplay { componentProvider.setTitle(title); int count = graph.getVertexCount(); if (count > options.getMaxNodeCount()) { - Msg.showWarn(this, null, "Graph Not Rendered - Too many nodes!", - "Exceeded limit of " + options.getMaxNodeCount() + " nodes.\n\n Graph contained " + - count + - " nodes!"); + Msg.showWarn(this, null, "Graph Not Rendered - Too many nodes!", "Exceeded limit of " + + options.getMaxNodeCount() + " nodes.\n\n Graph contained " + count + " nodes!"); graph = new AttributedGraph("Aborted", graph.getGraphType(), "Too Many Nodes"); graph.addVertex("1", "Graph Aborted"); } @@ -1293,7 +1273,7 @@ public class DefaultGraphDisplay implements GraphDisplay { graphRenderer.initializeViewer(vv); vv.getComponent().requestFocus(); - vv.setBackground(Color.WHITE); + vv.setBackground(BACKGROUND_COLOR); MouseListener[] mouseListeners = vv.getComponent().getMouseListeners(); for (MouseListener mouseListener : mouseListeners) { vv.getComponent().removeMouseListener(mouseListener); @@ -1334,8 +1314,8 @@ public class DefaultGraphDisplay implements GraphDisplay { public void addAction(DockingActionIf action) { if (containsAction(action)) { - Msg.warn(this, "Action with same name and owner already exixts in graph: " + - action.getFullName()); + Msg.warn(this, + "Action with same name and owner already exixts in graph: " + action.getFullName()); return; } @@ -1387,20 +1367,17 @@ public class DefaultGraphDisplay implements GraphDisplay { MutableSelectedState selectedVertexState = viewer.getSelectedVertexState(); if (hideSelected && hideUnselected) { - viewer.getRenderContext() - .setVertexIncludePredicate(v -> false); + viewer.getRenderContext().setVertexIncludePredicate(v -> false); } else if (hideSelected) { viewer.getRenderContext() .setVertexIncludePredicate(Predicate.not(selectedVertexState::isSelected)); } else if (hideUnselected) { - viewer.getRenderContext() - .setVertexIncludePredicate(selectedVertexState::isSelected); + viewer.getRenderContext().setVertexIncludePredicate(selectedVertexState::isSelected); } else { - viewer.getRenderContext() - .setVertexIncludePredicate(v -> true); + viewer.getRenderContext().setVertexIncludePredicate(v -> true); } viewer.repaint(); } @@ -1467,8 +1444,7 @@ public class DefaultGraphDisplay implements GraphDisplay { @Override public AttributedVertex getVertex(MouseEvent event) { - LayoutModel layoutModel = - vv.getVisualizationModel().getLayoutModel(); + LayoutModel layoutModel = vv.getVisualizationModel().getLayoutModel(); Point2D p = vv.getTransformSupport().inverseTransform(vv, event.getPoint()); AttributedVertex vertex = vv.getPickSupport().getVertex(layoutModel, p.getX(), p.getY()); @@ -1477,8 +1453,7 @@ public class DefaultGraphDisplay implements GraphDisplay { @Override public AttributedEdge getEdge(MouseEvent event) { - LayoutModel layoutModel = - vv.getVisualizationModel().getLayoutModel(); + LayoutModel layoutModel = vv.getVisualizationModel().getLayoutModel(); Point2D p = vv.getTransformSupport().inverseTransform(vv, event.getPoint()); AttributedEdge edge = vv.getPickSupport().getEdge(layoutModel, p.getX(), p.getY()); return edge; diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java index a4bf465f4b..5cee638e1d 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java @@ -37,6 +37,7 @@ import org.jungrapht.visualization.renderers.Renderer; import org.jungrapht.visualization.renderers.Renderer.VertexLabel.Position; import org.jungrapht.visualization.util.RectangleUtils; +import generic.theme.GThemeDefaults.Colors; import generic.util.image.ImageUtils; import ghidra.service.graph.*; import ghidra.util.HTMLUtilities; @@ -78,8 +79,8 @@ public class DefaultGraphRenderer implements GraphRenderer { this.options = options; renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); label = new JLabel(); - label.setForeground(Color.black); - label.setBackground(Color.white); + label.setForeground(Colors.FOREGROUND); + label.setBackground(Colors.BACKGROUND); label.setOpaque(false); Border marginBorder = BorderFactory.createEmptyBorder(labelBorderSize, 2 * labelBorderSize, labelBorderSize, 2 * labelBorderSize); @@ -163,7 +164,7 @@ public class DefaultGraphRenderer implements GraphRenderer { } renderContext.setVertexFontFunction(this::getFont); - renderContext.setVertexLabelRenderer(new JLabelVertexLabelRenderer(Color.black)); + renderContext.setVertexLabelRenderer(new JLabelVertexLabelRenderer(Colors.FOREGROUND)); renderContext.setVertexDrawPaintFunction(this::getVertexColor); renderContext.setVertexFillPaintFunction(this::getVertexColor); renderContext.setVertexStrokeFunction(n -> new BasicStroke(3.0f)); @@ -290,7 +291,7 @@ public class DefaultGraphRenderer implements GraphRenderer { // shapes are centered at the origin, so translate the graphics to compensate graphics.translate(-bounds.x + strokeThickness, -bounds.y + strokeThickness); - graphics.setPaint(Color.WHITE); + graphics.setPaint(Colors.BACKGROUND); graphics.fill(scaledShape); graphics.setPaint(vertexColor); graphics.setStroke(new BasicStroke(strokeThickness)); @@ -304,7 +305,7 @@ public class DefaultGraphRenderer implements GraphRenderer { int yOffset = (int) ((iconHeight - label.getHeight()) * labelOffsetRatio); graphics.translate(xOffset, yOffset); - graphics.setPaint(Color.black); + graphics.setPaint(Colors.FOREGROUND); label.paint(graphics); graphics.setTransform(graphicsTransform); // restore the original transform diff --git a/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java index 92db3e6e08..2052a80b00 100644 --- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java +++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java @@ -41,6 +41,9 @@ import docking.widgets.label.GIconLabel; import docking.widgets.label.GLabel; import docking.widgets.textfield.HexOrDecimalInput; import docking.widgets.textfield.HintTextField; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.util.bin.format.pdb.PdbParser; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbIdentifiers; import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl; @@ -56,7 +59,6 @@ import ghidra.util.task.*; import pdb.PdbPlugin; import pdb.symbolserver.*; import resources.Icons; -import resources.ResourceManager; /** * A dialog that allows the user to pick or search for a Pdb file for a program. @@ -64,10 +66,8 @@ import resources.ResourceManager; public class LoadPdbDialog extends DialogComponentProvider { private static final String LAST_PDBFILE_PREFERENCE_KEY = "Pdb.LastFile"; - static final Icon MATCH_OK_ICON = - ResourceManager.loadImage("images/checkmark_green.gif", 16, 16); - static final Icon MATCH_BAD_ICON = - ResourceManager.loadImage("images/emblem-important.png", 16, 16); + static final Icon MATCH_OK_ICON = new GIcon("icon.checkmark.green"); + static final Icon MATCH_BAD_ICON = Icons.ERROR_ICON; public static final GhidraFileFilter PDB_FILES_FILTER = ExtensionFileFilter.forExtensions("Microsoft Program Databases", "pdb", "pd_", "pdb.xml"); @@ -172,7 +172,7 @@ public class LoadPdbDialog extends DialogComponentProvider { protected void dialogShown() { cancelButton.requestFocusInWindow(); - if ( getCurrentSymbolFileInfo() != null ) { + if (getCurrentSymbolFileInfo() != null) { searchForPdbs(false); } } @@ -377,7 +377,7 @@ public class LoadPdbDialog extends DialogComponentProvider { programNameTextField.setEditable(false); programNameTextField.setText(program.getName()); - pdbPathTextField = new BetterNonEditableTextField(20, "Missing", Color.red); + pdbPathTextField = new BetterNonEditableTextField(20, "Missing", Colors.ERROR); pdbPathTextField.setEditable(false); pdbPathTextField.setText(programSymbolFileInfo.getPath()); pdbPathTextField.getDocument().addDocumentListener(docListener); @@ -399,7 +399,7 @@ public class LoadPdbDialog extends DialogComponentProvider { new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, SymbolFilePanel.SEARCH_OPTIONS_HELP_ANCHOR)); - pdbUniqueIdTextField = new BetterNonEditableTextField(36, "Missing", Color.red); + pdbUniqueIdTextField = new BetterNonEditableTextField(36, "Missing", Colors.ERROR); pdbUniqueIdTextField.setEditable(false); pdbUniqueIdTextField.setText(programSymbolFileInfo.getUniqifierString()); pdbUniqueIdTextField.setToolTipText( @@ -889,10 +889,9 @@ public class LoadPdbDialog extends DialogComponentProvider { Container parent = getParent(); if (parent != null && !isEditable()) { Color bg = parent.getBackground(); - // mint a new Color object to avoid it being - // ignored because the parent handed us a DerivedColor - // instance - return new Color(bg.getRGB()); + // mint a new Color object to avoid it being ignored because the parent handed us a + // DerivedColor instance + return ColorUtils.getColor(bg.getRGB()); } return super.getBackground(); } @@ -909,7 +908,7 @@ public class LoadPdbDialog extends DialogComponentProvider { } Graphics2D g2 = (Graphics2D) g; - g2.setColor(hintColor != null ? hintColor : Color.LIGHT_GRAY); + g2.setColor(hintColor != null ? hintColor : Messages.HINT); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Dimension size = getSize(); @@ -931,10 +930,9 @@ public class LoadPdbDialog extends DialogComponentProvider { Container parent = getParent(); if (parent != null && !isEditable()) { Color bg = parent.getBackground(); - // mint a new Color object to avoid it being - // ignored because the parent handed us a DerivedColor - // instance - return new Color(bg.getRGB()); + // mint a new Color object to avoid it being ignored because the parent handed us a + // DerivedColor instance + return ColorUtils.getColor(bg.getRGB()); } return super.getBackground(); } diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolFilePanel.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolFilePanel.java index c060524041..559065001e 100644 --- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolFilePanel.java +++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolFilePanel.java @@ -27,6 +27,7 @@ import docking.DockingWindowManager; import docking.widgets.checkbox.GCheckBox; import docking.widgets.label.GHtmlLabel; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors; import ghidra.util.HelpLocation; import ghidra.util.table.GhidraTable; import pdb.PdbPlugin; @@ -40,6 +41,7 @@ class SymbolFilePanel extends JPanel { interface SearchCallback { void searchForPdbs(boolean allowRemote); } + static final String SEARCH_OPTIONS_HELP_ANCHOR = "PDB_Search_Search_Options"; private SymbolFileTableModel tableModel; private GhidraTable table; @@ -117,7 +119,8 @@ class SymbolFilePanel extends JPanel { private JPanel buildWelcomePanel() { welcomePanel = new JPanel(); welcomePanel.add(new GHtmlLabel( - " Configuration must be set first!")); + " Configuration must be set first!")); welcomePanel.setPreferredSize(tablePanel.getPreferredSize()); return welcomePanel; diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java index 423f6e0325..712a6340e1 100644 --- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java +++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java @@ -36,6 +36,7 @@ import docking.widgets.label.GHtmlLabel; import docking.widgets.label.GLabel; import docking.widgets.table.GTable; import docking.widgets.textfield.HintTextField; +import generic.theme.GThemeDefaults.Colors; import ghidra.framework.preferences.Preferences; import ghidra.util.*; import ghidra.util.layout.PairLayout; @@ -107,13 +108,11 @@ class SymbolServerPanel extends JPanel { JPanel buttonPanel = buildButtonPanel(); JScrollPane tableScrollPane = buildTable(); defaultConfigNotice = new JPanel(); - defaultConfigNotice.add( - new GHtmlLabel( - "
" + - "Missing / invalid configuration.
" + - "Using default search location:
" + - "Program's Import Location
", - SwingConstants.CENTER)); + defaultConfigNotice.add(new GHtmlLabel( + "
" + "Missing / invalid configuration.
" + + "Using default search location:
" + "Program's Import Location
", + SwingConstants.CENTER)); defaultConfigNotice.setPreferredSize(tableScrollPane.getPreferredSize()); additionalSearchLocationsPanel = new JPanel(); @@ -199,55 +198,47 @@ class SymbolServerPanel extends JPanel { } private JPanel buildButtonPanel() { - refreshSearchLocationsStatusButton = createImageButton(Icons.REFRESH_ICON, "Refresh Status", - ButtonPanelFactory.ARROW_SIZE); + refreshSearchLocationsStatusButton = + createImageButton(Icons.REFRESH_ICON, "Refresh Status", ButtonPanelFactory.ARROW_SIZE); refreshSearchLocationsStatusButton.addActionListener(e -> refreshSearchLocationStatus()); DockingWindowManager.getHelpService() - .registerHelp(refreshSearchLocationsStatusButton, - new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, - "SymbolServerConfig Refresh Status")); + .registerHelp(refreshSearchLocationsStatusButton, new HelpLocation( + PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "SymbolServerConfig Refresh Status")); moveLocationUpButton = ButtonPanelFactory.createButton(ButtonPanelFactory.ARROW_UP_TYPE); moveLocationUpButton.addActionListener(e -> moveLocation(-1)); moveLocationUpButton.setToolTipText("Move location up"); DockingWindowManager.getHelpService() - .registerHelp(moveLocationUpButton, - new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, - "SymbolServerConfig MoveUpDown")); + .registerHelp(moveLocationUpButton, new HelpLocation( + PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "SymbolServerConfig MoveUpDown")); moveLocationDownButton = ButtonPanelFactory.createButton(ButtonPanelFactory.ARROW_DOWN_TYPE); moveLocationDownButton.addActionListener(e -> moveLocation(1)); moveLocationDownButton.setToolTipText("Move location down"); DockingWindowManager.getHelpService() - .registerHelp(moveLocationDownButton, - new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, - "SymbolServerConfig MoveUpDown")); + .registerHelp(moveLocationDownButton, new HelpLocation( + PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "SymbolServerConfig MoveUpDown")); - deleteLocationButton = createImageButton(Icons.DELETE_ICON, "Delete", - ButtonPanelFactory.ARROW_SIZE); + deleteLocationButton = + createImageButton(Icons.DELETE_ICON, "Delete", ButtonPanelFactory.ARROW_SIZE); deleteLocationButton.addActionListener(e -> deleteLocation()); DockingWindowManager.getHelpService() .registerHelp(deleteLocationButton, - new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, - "SymbolServerConfig Delete")); + new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "SymbolServerConfig Delete")); - addLocationButton = createImageButton(Icons.ADD_ICON, "Add", - ButtonPanelFactory.ARROW_SIZE); + addLocationButton = createImageButton(Icons.ADD_ICON, "Add", ButtonPanelFactory.ARROW_SIZE); addLocationButton.addActionListener(e -> addLocation()); DockingWindowManager.getHelpService() .registerHelp(addLocationButton, - new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, - "SymbolServerConfig Add")); + new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "SymbolServerConfig Add")); - saveSearchLocationsButton = - ButtonPanelFactory.createImageButton(Icons.get("images/disk.png"), - "Save Configuration", ButtonPanelFactory.ARROW_SIZE); + saveSearchLocationsButton = ButtonPanelFactory.createImageButton( + Icons.get("images/disk.png"), "Save Configuration", ButtonPanelFactory.ARROW_SIZE); saveSearchLocationsButton.addActionListener(e -> saveConfig()); DockingWindowManager.getHelpService() .registerHelp(saveSearchLocationsButton, - new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, - "SymbolServerConfig Save")); + new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "SymbolServerConfig Save")); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); @@ -325,8 +316,7 @@ class SymbolServerPanel extends JPanel { } if (allowGUIPrompt && isEmptyDirectory(symbolStorageDir)) { - if (OptionDialog.showYesNoDialog(this, - "Initialize Symbol Storage Directory?", + if (OptionDialog.showYesNoDialog(this, "Initialize Symbol Storage Directory?", "Initialize new directory as Microsoft symbol storage directory?") == OptionDialog.YES_OPTION) { try { LocalSymbolStore.create(symbolStorageDir, @@ -407,8 +397,8 @@ class SymbolServerPanel extends JPanel { String[] envParts = envString.split("[*;]"); Listresults = new ArrayList<>(); Set locationStringDeduplicationSet = new HashSet<>(); - for (int i = 0; i < envParts.length; i++) { - String locationString = envParts[i].trim(); + for (String envPart : envParts) { + String locationString = envPart.trim(); if (!locationString.isBlank() && !locationString.equalsIgnoreCase("srv") && !locationStringDeduplicationSet.contains(locationString)) { results.add(locationString); @@ -495,8 +485,8 @@ class SymbolServerPanel extends JPanel { } private void addDirectoryLocation() { - File dir = FilePromptDialog.chooseDirectory("Enter Path", "Symbol Storage Location: ", - null); + File dir = + FilePromptDialog.chooseDirectory("Enter Path", "Symbol Storage Location: ", null); if (dir == null) { return; } @@ -574,7 +564,7 @@ class SymbolServerPanel extends JPanel { return false; } - private static JButton createImageButton(ImageIcon buttonIcon, String alternateText, + private static JButton createImageButton(Icon buttonIcon, String alternateText, Dimension preferredSize) { JButton button = ButtonPanelFactory.createButton(""); @@ -584,7 +574,7 @@ class SymbolServerPanel extends JPanel { return button; } - + static StatusText getSymbolServerWarnings(List symbolServers) { Map warningsByLocation = new HashMap<>(); for (WellKnownSymbolServerLocation ssloc : knownSymbolServers) { @@ -592,8 +582,7 @@ class SymbolServerPanel extends JPanel { warningsByLocation.put(ssloc.getLocation(), ssloc.getWarning()); } } - String warning = symbolServers - .stream() + String warning = symbolServers.stream() .map(symbolServer -> warningsByLocation.get(symbolServer.getName())) .filter(Objects::nonNull) .distinct() diff --git a/Ghidra/Features/ProgramDiff/certification.manifest b/Ghidra/Features/ProgramDiff/certification.manifest index 94046642d7..cc80bd6c37 100644 --- a/Ghidra/Features/ProgramDiff/certification.manifest +++ b/Ghidra/Features/ProgramDiff/certification.manifest @@ -6,6 +6,7 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| +data/programdiff.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/shared/arrow.gif||GHIDRA||reviewed||END| src/main/help/help/shared/close16.gif||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/ProgramDiff/data/programdiff.theme.properties b/Ghidra/Features/ProgramDiff/data/programdiff.theme.properties new file mode 100644 index 0000000000..26beada9ae --- /dev/null +++ b/Ghidra/Features/ProgramDiff/data/programdiff.theme.properties @@ -0,0 +1,16 @@ +[Defaults] + +color.bg.programdiff.highlight = moccasin + +icon.plugin.programdiff.apply = pencil16.png +icon.plugin.programdiff.apply.next = pencil_arrow16.png +icon.plugin.programdiff.ignore = eraser_arrow16.png +icon.plugin.programdiff.get.diffs = Diff16.png +icon.plugin.programdiff.select.by.program = DiffSelect16.png +icon.plugin.programdiff.open.close.program = table_relationship.png +icon.plugin.programdiff.settings = settings16.gif +icon.plugin.programdiff.cursor.location = cursor_arrow.gif + +[Dark Defaults] + +color.bg.programdiff.highlight = darkRed diff --git a/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java index 63c481b60b..3d96eb7732 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffActionManager.java @@ -18,19 +18,20 @@ package ghidra.app.plugin.core.diff; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; import docking.widgets.OptionDialog; +import generic.theme.GIcon; import ghidra.app.plugin.core.codebrowser.OtherPanelContext; import ghidra.app.services.CodeViewerService; import ghidra.app.util.HelpTopics; import ghidra.program.model.listing.Program; import ghidra.util.HTMLUtilities; import ghidra.util.HelpLocation; -import resources.ResourceManager; +import resources.Icons; /** * Creates the actions for the program diff plugin. @@ -41,7 +42,6 @@ class DiffActionManager { private static final String GET_DIFF_GROUP = "GetDiff"; private static final String DIFF_INFO_GROUP = "DiffInfo"; private static final String DIFF_NAVIGATE_GROUP = "DiffNavigate"; - private static final String TOGGLE_VIEW_ICON_NAME = "images/table_relationship.png"; private static final String GROUP = "Diff"; private ProgramDiffPlugin plugin; private CodeViewerService codeViewerService; @@ -251,7 +251,7 @@ class DiffActionManager { plugin.applyDiff(); } }; - ImageIcon icon = ResourceManager.loadImage("images/pencil16.png"); + Icon icon = new GIcon("icon.plugin.programdiff.apply"); applyDiffsAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F3, 0)); applyDiffsAction.setPopupMenuData( new MenuData(new String[] { "Apply Selection" }, icon, GROUP)); @@ -265,7 +265,7 @@ class DiffActionManager { plugin.applyDiffAndGoNext(); } }; - icon = ResourceManager.loadImage("images/pencil_arrow16.png"); + icon = new GIcon("icon.plugin.programdiff.apply.next"); String[] applyDiffsPath = { "Apply Selection and Goto Next Difference" }; applyDiffsNextAction.setPopupMenuData(new MenuData(applyDiffsPath, icon, GROUP)); applyDiffsNextAction.setKeyBindingData( @@ -281,7 +281,7 @@ class DiffActionManager { plugin.ignoreDiff(); } }; - icon = ResourceManager.loadImage("images/eraser_arrow16.png"); + icon = new GIcon("icon.plugin.programdiff.ignore"); ignoreDiffsAction.setPopupMenuData(new MenuData( new String[] { "Ignore Selection and Goto Next Difference" }, icon, GROUP)); ignoreDiffsAction.setDescription( @@ -294,9 +294,9 @@ class DiffActionManager { plugin.nextDiff(); } }; - icon = ResourceManager.loadImage("images/down.png"); + icon = Icons.DOWN_ICON; nextDiffAction.setKeyBindingData( - new KeyBindingData('N', InputEvent.CTRL_MASK | InputEvent.ALT_MASK)); + new KeyBindingData('N', InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK)); nextDiffAction.setPopupMenuData( new MenuData(new String[] { "Next Difference" }, icon, DIFF_NAVIGATE_GROUP)); nextDiffAction.setToolBarData(new ToolBarData(icon, DIFF_NAVIGATE_GROUP)); @@ -308,9 +308,9 @@ class DiffActionManager { plugin.previousDiff(); } }; - icon = ResourceManager.loadImage("images/up.png"); + icon = Icons.UP_ICON; previousDiffAction.setKeyBindingData( - new KeyBindingData('P', InputEvent.CTRL_MASK | InputEvent.ALT_MASK)); + new KeyBindingData('P', InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK)); previousDiffAction.setPopupMenuData( new MenuData(new String[] { "Previous Difference" }, icon, DIFF_NAVIGATE_GROUP)); previousDiffAction.setToolBarData(new ToolBarData(icon, DIFF_NAVIGATE_GROUP)); @@ -322,7 +322,7 @@ class DiffActionManager { plugin.showDiffDetails(); } }; - icon = ResourceManager.loadImage("images/xmag.png"); + icon = new GIcon("icon.search"); diffDetailsAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F5, 0)); diffDetailsAction.setPopupMenuData( new MenuData(new String[] { "Location Details..." }, icon, DIFF_INFO_GROUP)); @@ -349,7 +349,7 @@ class DiffActionManager { plugin.diff(); } }; - icon = ResourceManager.loadImage("images/Diff16.png"); + icon = new GIcon("icon.plugin.programdiff.get.diffs"); getDiffsAction.setPopupMenuData( new MenuData(new String[] { "Get Differences..." }, icon, GET_DIFF_GROUP)); getDiffsAction.setToolBarData(new ToolBarData(icon, GET_DIFF_GROUP)); @@ -372,7 +372,7 @@ class DiffActionManager { plugin.setP1SelectionOnP2(); } }; - icon = ResourceManager.loadImage("images/DiffSelect16.png"); + icon = new GIcon("icon.plugin.programdiff.select.by.program"); p1SelectToP2Action.setDescription( "Select Program 2 highlights using selection in Program 1."); p1SelectToP2Action.setToolBarData(new ToolBarData(icon, SELECT_GROUP)); @@ -434,10 +434,10 @@ class DiffActionManager { return true; } }; - icon = ResourceManager.loadImage(TOGGLE_VIEW_ICON_NAME); + icon = new GIcon("icon.plugin.programdiff.open.close.program"); openCloseProgram2Action.setEnabled(false); openCloseProgram2Action.setKeyBindingData( - new KeyBindingData('C', InputEvent.CTRL_MASK | InputEvent.ALT_MASK)); + new KeyBindingData('C', InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK)); openCloseProgram2Action.setToolBarData(new ToolBarData(icon, "zzz")); openCloseProgram2Action.setHelpLocation( new HelpLocation(HelpTopics.DIFF, OPEN_CLOSE_PROGRAM2_ACTION)); diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffApplySettingsProvider.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffApplySettingsProvider.java index dd6ec26035..510009c51d 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffApplySettingsProvider.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffApplySettingsProvider.java @@ -28,12 +28,12 @@ import docking.WindowPosition; import docking.widgets.VariableHeightPanel; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GDLabel; +import generic.theme.GIcon; import ghidra.app.plugin.core.diff.DiffApplySettingsOptionManager.*; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.Plugin; import ghidra.program.util.ProgramMergeFilter; import ghidra.util.HelpLocation; -import resources.ResourceManager; /** * The DiffSettingsDialog is used to change the types of differences currently @@ -43,7 +43,7 @@ import resources.ResourceManager; public class DiffApplySettingsProvider extends ComponentProviderAdapter { public static final String APPLY_FILTER_CHANGED_ACTION = "Apply Filter Changed"; - public static final ImageIcon ICON = ResourceManager.loadImage("images/settings16.gif"); + public static final Icon ICON = new GIcon("icon.plugin.programdiff.settings"); public static final String TITLE = "Diff Apply Settings"; private ProgramDiffPlugin plugin; @@ -106,8 +106,9 @@ public class DiffApplySettingsProvider extends ComponentProviderAdapter { } public void addActions() { - plugin.getTool().addLocalAction(this, - new SaveApplySettingsAction(this, plugin.applySettingsMgr)); + plugin.getTool() + .addLocalAction(this, + new SaveApplySettingsAction(this, plugin.applySettingsMgr)); plugin.getTool().addLocalAction(this, new DiffIgnoreAllAction(this)); plugin.getTool().addLocalAction(this, new DiffReplaceAllAction(this)); plugin.getTool().addLocalAction(this, new DiffMergeAllAction(this)); @@ -351,10 +352,6 @@ public class DiffApplySettingsProvider extends ComponentProviderAdapter { listenerList.remove(listener); } - /** - * Return true if at least one of the checkboxes for the filter - * has been selected. - */ boolean hasApplySelection() { return ((applyProgramContext | applyBytes | applyCodeUnits | applyReferences | applyPlateComments | applyPreComments | applyEolComments | applyRepeatableComments | @@ -366,8 +363,7 @@ public class DiffApplySettingsProvider extends ComponentProviderAdapter { if (adjustingApplyFilter) { return; } - for (int i = 0; i < listenerList.size(); i++) { - ActionListener listener = listenerList.get(i); + for (ActionListener listener : listenerList) { listener.actionPerformed(new ActionEvent(this, 0, APPLY_FILTER_CHANGED_ACTION)); } } @@ -383,9 +379,6 @@ public class DiffApplySettingsProvider extends ComponentProviderAdapter { return applyPanel; } - /** - * Gets the plugin associated with this provider. - */ Plugin getPlugin() { return plugin; } diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffDetailsProvider.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffDetailsProvider.java index 4450d1687f..8042e9a026 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffDetailsProvider.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/DiffDetailsProvider.java @@ -29,6 +29,9 @@ import docking.WindowPosition; import docking.action.DockingAction; import docking.action.ToolBarData; import docking.widgets.checkbox.GCheckBox; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Ids.Fonts; +import generic.theme.Gui; import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.Plugin; @@ -40,7 +43,6 @@ import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.task.SwingUpdateManager; import resources.Icons; -import resources.ResourceManager; /** * The DiffDetailsProvider is used to view the differences for an address or @@ -52,8 +54,8 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { public static final String FILTER_DIFFS_CHECK_BOX = "Filter Diffs Check Box"; public static final String DIFF_DETAILS_TEXT_AREA = "Diff Details Text Area"; public static final String DIFF_DETAILS_PANEL = "Diff Location Details Panel"; - public static final ImageIcon ICON = ResourceManager.loadImage("images/xmag.png"); - public static final ImageIcon REFRESH_ICON = Icons.REFRESH_ICON; + public static final Icon ICON = new GIcon("icon.search"); + public static final Icon REFRESH_ICON = Icons.REFRESH_ICON; public static final String TITLE = "Diff Details"; private ProgramDiffPlugin plugin; @@ -72,9 +74,6 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { private SwingUpdateManager updateManager; private ProgramLocation currentLocation; - /** - * @param plugin - */ public DiffDetailsProvider(ProgramDiffPlugin plugin) { super(plugin.getTool(), "Diff Location Details", plugin.getName()); setTitle(TITLE); @@ -91,17 +90,11 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { setUpRefreshDetailsUpdateManager(); } - /** - * @param selected - */ public void setAutoUpdate(boolean selected) { autoUpdateCB.setSelected(selected); autoUpdate = selected; } - /** - * @param selected - */ public void setFilterDiffs(boolean selected) { filterDiffsCB.setSelected(selected); filterDiffs = selected; @@ -121,8 +114,8 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { refreshDetailsAction.setEnabled(true); refreshDetailsAction.setToolBarData(new ToolBarData(REFRESH_ICON, "Diff")); - refreshDetailsAction.setHelpLocation( - new HelpLocation(HelpTopics.DIFF, "Refresh Diff Details")); + refreshDetailsAction + .setHelpLocation(new HelpLocation(HelpTopics.DIFF, "Refresh Diff Details")); plugin.getTool().addLocalAction(this, refreshDetailsAction); // plugin.getTool().addLocalAction(this, new DiffIgnoreAllAction(this)); } @@ -159,9 +152,6 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { } - /** - * @param p1Location - */ protected void locationChanged(ProgramLocation p1Location) { if (isDisplayed && autoUpdate) { refreshDetails(p1Location); @@ -300,13 +290,12 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { } private JScrollPane createDetailsPane() { - Font font = new Font("Monospaced", Font.PLAIN, 12); textPane = new JTextPane(); doc = textPane.getStyledDocument(); textPane.setName(DIFF_DETAILS_TEXT_AREA); textPane.setEditable(false); textPane.setMargin(new Insets(5, 5, 5, 5)); - textPane.setFont(font); + Gui.registerFont(textPane, Fonts.MONOSPACED); textPane.setOpaque(true); textPane.setCaretPosition(0); JScrollPane scrolledDetails = new JScrollPane(textPane); @@ -321,8 +310,7 @@ public class DiffDetailsProvider extends ComponentProviderAdapter { @Override public void componentHidden() { - for (int i = 0; i < listenerList.size(); i++) { - ActionListener listener = listenerList.get(i); + for (ActionListener listener : listenerList) { listener.actionPerformed(new ActionEvent(this, 0, DIFF_DETAILS_HIDDEN_ACTION)); } isDisplayed = false; diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java index 77fc090912..770f47d818 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java @@ -32,6 +32,8 @@ import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.listener.FieldMouseListener; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; import ghidra.app.events.*; @@ -62,7 +64,6 @@ import ghidra.util.exception.VersionException; import ghidra.util.task.*; import help.Help; import help.HelpService; -import resources.ResourceManager; /** * Plugin that shows the differences between two programs, and allows the user to apply differences @@ -91,12 +92,13 @@ public class ProgramDiffPlugin extends ProgramPlugin implements ProgramLocationListener, ProgramSelectionListener, DiffControllerListener, DiffService, OptionsChangeListener, DomainObjectListener { - private ImageIcon CURSOR_LOC_ICON = ResourceManager.loadImage("images/cursor_arrow.gif"); + private static final Icon CURSOR_LOC_ICON = + new GIcon("icon.plugin.programdiff.cursor.location"); private static final String SELECTION_GROUP = "Selection Colors"; private static final String DIFF_HIGHLIGHT_COLOR_NAME = SELECTION_GROUP + Options.DELIMITER + "Difference Color"; - private Color diffHighlightColor = new Color(255, 230, 180); // light orange - private Color cursorHighlightColor; + private GColor diffHighlightColor = new GColor("color.bg.programdiff.highlight"); + private Color cursorHighlightColor = GhidraOptions.DEFAULT_CURSOR_LINE_COLOR; protected static final HelpService help = Help.getHelpService(); private GoToService goToService; @@ -374,11 +376,9 @@ public class ProgramDiffPlugin extends ProgramPlugin boolean diffHighlightChanged = false; if (options.getName().equals(GhidraOptions.CATEGORY_BROWSER_FIELDS)) { if (optionsName.equals(DIFF_HIGHLIGHT_COLOR_NAME)) { - diffHighlightColor = ((Color) newValue); diffHighlightChanged = true; } else if (optionsName.equals(GhidraOptions.HIGHLIGHT_CURSOR_LINE_COLOR)) { - cursorHighlightColor = (Color) newValue; if (p2CursorMarkers != null) { p2CursorMarkers.setMarkerColor(cursorHighlightColor); } @@ -395,7 +395,6 @@ public class ProgramDiffPlugin extends ProgramPlugin } if (diffHighlightChanged) { - diffHighlightColor = ((Color) newValue); MarkerSet diffMarkers = getDiffMarkers(); diffMarkers.setMarkerColor(diffHighlightColor); @@ -1396,14 +1395,11 @@ public class ProgramDiffPlugin extends ProgramPlugin private void setupOptions() { String OPTIONS_TITLE = GhidraOptions.CATEGORY_BROWSER_FIELDS; ToolOptions opt = tool.getOptions(OPTIONS_TITLE); - opt.registerOption(DIFF_HIGHLIGHT_COLOR_NAME, diffHighlightColor, + opt.registerThemeColorBinding(DIFF_HIGHLIGHT_COLOR_NAME, diffHighlightColor.getId(), new HelpLocation("CodeBrowserPlugin", "Browser_Fields"), "Color used to highlight differences between two programs."); - Color c = opt.getColor(DIFF_HIGHLIGHT_COLOR_NAME, diffHighlightColor); - diffHighlightColor = c; opt.addOptionsChangeListener(this); - cursorHighlightColor = opt.getColor(GhidraOptions.HIGHLIGHT_CURSOR_LINE_COLOR, null); isHighlightCursorLine = opt.getBoolean(GhidraOptions.HIGHLIGHT_CURSOR_LINE, false); } diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/SaveApplySettingsAction.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/SaveApplySettingsAction.java index f32674487a..c9ade4e2b2 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/SaveApplySettingsAction.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/SaveApplySettingsAction.java @@ -22,7 +22,7 @@ import docking.action.DockingAction; import docking.action.ToolBarData; import ghidra.app.util.HelpTopics; import ghidra.util.HelpLocation; -import resources.ResourceManager; +import resources.Icons; /** * Action to save the current Diff Apply Settings as the new defaults to be used when new Diffs are started. @@ -45,7 +45,7 @@ class SaveApplySettingsAction extends DockingAction { super(ACTION_NAME, settingsProvider.getPlugin().getName()); this.settingsProvider = settingsProvider; this.settingsOptionMgr = settingsOptionMgr; - setToolBarData(new ToolBarData(ResourceManager.loadImage("images/disk.png"), GROUP_NAME)); + setToolBarData(new ToolBarData(Icons.SAVE_ICON, GROUP_NAME)); setEnabled(true); setDescription(DESCRIPTION); setHelpLocation(new HelpLocation(HelpTopics.DIFF, ACTION_NAME)); @@ -61,8 +61,10 @@ class SaveApplySettingsAction extends DockingAction { @Override public void actionPerformed(ActionContext context) { settingsOptionMgr.saveDefaultApplyFilter(settingsProvider.getApplyFilter()); - settingsProvider.getPlugin().getTool().setStatusInfo( - "Diff Apply Settings have been saved to the tool as the new defaults."); + settingsProvider.getPlugin() + .getTool() + .setStatusInfo( + "Diff Apply Settings have been saved to the tool as the new defaults."); } } diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java index 95d9bbbf56..ac7f16fff2 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java @@ -33,6 +33,7 @@ import docking.action.ToggleDockingAction; import docking.tool.ToolConstants; import docking.widgets.fieldpanel.FieldPanel; import generic.test.AbstractGenericTest; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.events.ProgramLocationPluginEvent; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.marker.MarkerManagerPlugin; @@ -271,10 +272,10 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { builder.setIntProperty("10018ff", "Space", 1); builder.setIntProperty("100248c", "Space", 1); - builder.setObjectProperty("100248c", "testColor", new SaveableColor(Color.CYAN)); - builder.setObjectProperty("10039dd", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Color.RED)); + builder.setObjectProperty("100248c", "testColor", new SaveableColor(Palette.CYAN)); + builder.setObjectProperty("10039dd", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Palette.RED)); AbstractGenericTest.setInstanceField("recordChanges", builder.getProgram(), Boolean.TRUE); @@ -450,10 +451,10 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { builder.setIntProperty("1002428", "Space", 1); builder.setIntProperty("100248c", "Space", 1); - builder.setObjectProperty("100248c", "testColor", new SaveableColor(Color.WHITE)); - builder.setObjectProperty("10039f1", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Color.GREEN)); + builder.setObjectProperty("100248c", "testColor", new SaveableColor(Palette.WHITE)); + builder.setObjectProperty("10039f1", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Palette.GREEN)); AbstractGenericTest.setInstanceField("recordChanges", builder.getProgram(), Boolean.TRUE); diff --git a/Ghidra/Features/Python/certification.manifest b/Ghidra/Features/Python/certification.manifest index bbb9356524..412c40104c 100644 --- a/Ghidra/Features/Python/certification.manifest +++ b/Ghidra/Features/Python/certification.manifest @@ -2,6 +2,7 @@ ##MODULE IP: Jython License ##MODULE IP: LGPL 2.1 Module.manifest||GHIDRA||||END| +data/python.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/topics/Python/images/erase16.png||GHIDRA||||END| src/main/help/help/topics/Python/interpreter.html||GHIDRA||||END| diff --git a/Ghidra/Features/Python/data/python.theme.properties b/Ghidra/Features/Python/data/python.theme.properties new file mode 100644 index 0000000000..52757dc295 --- /dev/null +++ b/Ghidra/Features/Python/data/python.theme.properties @@ -0,0 +1,19 @@ + +[Defaults] + +color.fg.plugin.python.syntax.class = blue +color.fg.plugin.python.syntax.code = darkgreen +color.fg.plugin.python.syntax.function = green +color.fg.plugin.python.syntax.instance = purple +color.fg.plugin.python.syntax.map = steelblue +color.fg.plugin.python.syntax.method = teal +color.fg.plugin.python.syntax.null = red +color.fg.plugin.python.syntax.number = darkgray +color.fg.plugin.python.syntax.package = darkred +color.fg.plugin.python.syntax.sequence = rgb(128, 96, 64) +color.fg.plugin.python.syntax.special = darkgreen + +icon.plugin.python = python.png + +[Dark Defaults] + diff --git a/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java index 5e254f8efc..6943b2cbd2 100644 --- a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java +++ b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java @@ -25,6 +25,7 @@ import org.python.core.PyInstance; import org.python.core.PyObject; import docking.widgets.label.GDLabel; +import generic.theme.GColor; import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.framework.options.Options; import ghidra.util.Msg; @@ -57,19 +58,21 @@ public class PythonCodeCompletionFactory { private final static boolean INCLUDE_TYPES_DEFAULT = true; private static boolean includeTypes = INCLUDE_TYPES_DEFAULT; - public static final Color NULL_COLOR = new Color(255, 0, 0); - public static final Color FUNCTION_COLOR = new Color(0, 128, 0); - public static final Color PACKAGE_COLOR = new Color(128, 0, 0); - public static final Color CLASS_COLOR = new Color(0, 0, 255); - public static final Color METHOD_COLOR = new Color(0, 128, 128); + //@formatter:off + public static final Color NULL_COLOR = new GColor("color.fg.plugin.python.syntax.null"); + public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.python.syntax.function"); + public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.python.syntax.package"); + public static final Color CLASS_COLOR = new GColor("color.fg.plugin.python.syntax.class"); + public static final Color METHOD_COLOR = new GColor("color.fg.plugin.python.syntax.method"); /* anonymous code chunks */ - public static final Color CODE_COLOR = new Color(0, 64, 0); - public static final Color INSTANCE_COLOR = new Color(128, 0, 128); - public static final Color SEQUENCE_COLOR = new Color(128, 96, 64); - public static final Color MAP_COLOR = new Color(64, 96, 128); - public static final Color NUMBER_COLOR = new Color(64, 64, 64); + public static final Color CODE_COLOR = new GColor("color.fg.plugin.python.syntax.code"); + public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.python.syntax.instance"); + public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.python.syntax.sequence"); + public static final Color MAP_COLOR = new GColor("color.fg.plugin.python.syntax.map"); + public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.python.syntax.number"); /* for weird Jython-specific stuff */ - public static final Color SPECIAL_COLOR = new Color(64, 96, 64); + public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.python.syntax.special"); + //@formatter:on static { /* Order matters! This is the order in which classes are checked for diff --git a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java index 0dcbe75b7c..c0da0b8734 100644 --- a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java +++ b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonPlugin.java @@ -19,7 +19,7 @@ import java.awt.event.KeyEvent; import java.io.*; import java.util.List; -import javax.swing.ImageIcon; +import javax.swing.Icon; import org.python.core.PySystemState; @@ -27,6 +27,7 @@ import docking.ActionContext; import docking.DockingUtils; import docking.action.*; import generic.jar.ResourceFile; +import generic.theme.GIcon; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.ProgramPlugin; @@ -40,7 +41,7 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginStatus; import ghidra.util.HelpLocation; import ghidra.util.task.*; -import resources.ResourceManager; +import resources.Icons; /** * This plugin provides the interactive Python interpreter. @@ -59,8 +60,6 @@ import resources.ResourceManager; public class PythonPlugin extends ProgramPlugin implements InterpreterConnection, OptionsChangeListener { - private final static int INPUT_THREAD_SHUTDOWN_TIMEOUT_MS = 1000; - private InterpreterConsole console; private GhidraPythonInterpreter interpreter; private PythonScript interactiveScript; @@ -72,6 +71,9 @@ public class PythonPlugin extends ProgramPlugin private final static String INCLUDE_BUILTINS_DESCRIPTION = "Whether or not to include Python's built-in functions and properties in the pop-up code completion window."; private final static boolean INCLUDE_BUILTINS_DEFAULT = true; + + private static final Icon ICON = new GIcon("icon.plugin.python"); + private boolean includeBuiltins = INCLUDE_BUILTINS_DEFAULT; /** @@ -134,7 +136,7 @@ public class PythonPlugin extends ProgramPlugin * Creates various actions for the plugin. */ private void createActions() { - + // Interrupt Interpreter DockingAction interruptAction = new DockingAction("Interrupt Interpreter", getName()) { @Override @@ -144,7 +146,7 @@ public class PythonPlugin extends ProgramPlugin }; interruptAction.setDescription("Interrupt Interpreter"); interruptAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/dialog-cancel.png"), null)); + new ToolBarData(Icons.NOT_ALLOWED_ICON, null)); interruptAction.setEnabled(true); interruptAction.setKeyBindingData( new KeyBindingData(KeyEvent.VK_I, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); @@ -160,7 +162,7 @@ public class PythonPlugin extends ProgramPlugin }; resetAction.setDescription("Reset Interpreter"); resetAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage("images/reload3.png"), null)); + new ToolBarData(Icons.REFRESH_ICON, null)); resetAction.setEnabled(true); resetAction.setKeyBindingData( new KeyBindingData(KeyEvent.VK_D, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); @@ -345,8 +347,8 @@ public class PythonPlugin extends ProgramPlugin } @Override - public ImageIcon getIcon() { - return ResourceManager.loadImage("images/python.png"); + public Icon getIcon() { + return ICON; } /** diff --git a/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Features/VersionTracking/certification.manifest b/Ghidra/Features/VersionTracking/certification.manifest index 1c3c497aa1..927370bc2b 100644 --- a/Ghidra/Features/VersionTracking/certification.manifest +++ b/Ghidra/Features/VersionTracking/certification.manifest @@ -5,6 +5,7 @@ ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||reviewed||END| +data/version.tracking.theme.properties||GHIDRA||||END| src/main/docs/VTClasses.png||GHIDRA||reviewed||END| src/main/docs/VTGuiImpl.png||GHIDRA||reviewed||END| src/main/help/help/TOC_Source.xml||GHIDRA||reviewed||END| diff --git a/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties b/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties new file mode 100644 index 0000000000..345e342482 --- /dev/null +++ b/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties @@ -0,0 +1,164 @@ +[Defaults] + +color.fg.version.tracking.tooltip = gray + +color.bg.version.tracking.dual.listing.highlight.markup.applied = rgb(150, 220, 150) // green +color.bg.version.tracking.dual.listing.highlight.markup.unapplied = rgb(255, 170, 85) // orange +color.bg.version.tracking.dual.listing.highlight.markup.ignored = gainsboro // gray +color.bg.version.tracking.dual.listing.highlight.markup.rejected = rgb(250, 200, 200) // pink +color.bg.version.tracking.dual.listing.highlight.markup.failed = rgb(255, 80, 80) // red +color.bg.version.tracking.dual.listing.highlight.markup.no.address = rgb(205, 185, 220) // purple +color.bg.version.tracking.dual.listing.highlight.markup.same = rgb(175, 225, 255) // light blue +color.bg.version.tracking.dual.listing.highlight.markup.conflict = rgb(255, 225, 105) // gold + +color.bg.version.tracking.filter.formatted.field.error = rgb(218, 217, 206) // grayish +color.bg.version.tracking.filter.formatted.field.editing = rgb(243, 242, 131) // yellowish + +color.bg.version.tracking.match.table.locked.out = whitesmoke +color.bg.version.tracking.match.table.markup.status.applied = rgb(0, 180, 0) // green +color.bg.version.tracking.match.table.markup.status.rejected = red +color.bg.version.tracking.match.table.markup.status.dont.care = royalblue +color.bg.version.tracking.match.table.markup.status.dont.know = orange +color.bg.version.tracking.match.table.markup.status.tooltip.unexamined = black +color.fg.version.tracking.match.table.error = color.fg.error + +color.fg.version.tracking.markup.items.table.error = color.fg.error +color.fg.version.tracking.markup.items.table.user.defined.address = cyan +color.fg.version.tracking.markup.items.table.user.defined.address.selected = lightseagreen + +color.bg.version.tracking.related.matches.table.good = green +color.bg.version.tracking.related.matches.table.medium = yellow +color.bg.version.tracking.related.matches.table.bad = red + +color.fg.version.tracking.function.match.local.info = green + +icon.version.tracking.session.content.type = start-here_16.png +icon.version.tracking.package = start-here_16.png + +icon.version.tracking.provider.function = functions.gif +icon.version.tracking.provider.implied.match = application_view_detail.png +icon.version.tracking.provider.markup = application_view_detail.png +icon.version.tracking.provider.one.to.many = text_list_bullets.png +icon.version.tracking.provider.related.matches = user-online.png + +icon.version.tracking.unfiltered = lightbulb_off.png +icon.version.tracking.filtered = lightbulb.png +icon.version.tracking.replaced = sync_enabled.png +icon.version.tracking.unignored = EMPTY_ICON{dialog-cancel.png[size(13,13)][move(3,4)]}{undo.png[move(0,-4)]} + +icon.version.tracking.accept.match = flag.png +icon.version.tracking.add = Plus.png +icon.version.tracking.substract = list-remove.png +icon.version.tracking.replace = sync_enabled.png +icon.version.tracking.auto = wizard.png + +icon.version.tracking.action.clear.match = undo-apply.png +icon.version.tracking.action.create.implied.match = flag.png +icon.version.tracking.action.create.manual.match = Plus.png +icon.version.tracking.action.create.and.accept.manual.match = flag.png +icon.version.tracking.action.create.accept.and.apply.manual.match = checkmark_green.gif +icon.version.tracking.action.create.selection = text_align_justify.png +icon.version.tracking.action.create.session = start-here_16.png +icon.version.tracking.action.choose.tag = tag_blue.png +icon.version.tracking.action.edit.all.tags = tag_blue_edit.png +icon.version.tracking.action.accept.match = icon.version.tracking.accept.match +icon.version.tracking.action.add.to.session = Plus.png +icon.version.tracking.action.save.session = disk.png +icon.version.tracking.action.match.reject = dialog-cancel.png +icon.version.tracking.action.match.remove = edit-delete.png +icon.version.tracking.action.match.select.existing = text_align_justify.png +icon.version.tracking.action.match.tag.remove = tag_blue_delete.png +icon.version.tracking.action.markup.reset = undo-apply.png +icon.version.tracking.action.match.one.to.many = text_align_justify.png +icon.version.tracking.action.show.listings = application_tile_horizontal.png +icon.version.tracking.action.show.settings = settings16.gif +icon.version.tracking.action.edit.markup.address = edit-rename.png + + +icon.version.tracking.tag.status.new = tag_blue_add.png +icon.version.tracking.tag.status.deleted = tag_blue_delete.png +icon.version.tracking.tag.status.existing = tag_blue.png +icon.version.tracking.tag.button.undo = undo-apply.png + +icon.version.tracking.filter.status.changed = bullet_black.png +icon.version.tracking.filter.status.invalid = no_small.png +icon.version.tracking.filter.status.applied = bullet_green.png + +icon.version.tracking.markup.status.applied = checkmark_green.gif +icon.version.tracking.markup.status.rejected = dialog-cancel.png +icon.version.tracking.markup.status.dont.care = asterisk_orange.png +icon.version.tracking.markup.status.dont.know = unknown.gif +icon.version.tracking.markup.status.failed = edit-delete.png +icon.version.tracking.markup.status.conflict = cache.png + +icon.version.tracking.filter = view-filter.png +icon.version.tracking.empty = EmptyIcon16.gif + +icon.version.tracking.function.filter.all = function.png +icon.version.tracking.function.filter.unmatched = filter_matched.png + + +icon.version.tracking.match.table.status.accepted.some.unexamined = flag.png {bullet_error.png[move(10,8)]} +icon.version.tracking.match.table.status.accepted.error = flag.png {edit-delete.png[size(8,8)][move(10,8)]} +icon.version.tracking.match.table.status.accepted.fully.applied = flag.png {checkmark_green.gif[size(8,8)][move(10,8)]} +icon.version.tracking.match.table.status.accepted.fully.considered = flag.png {checkmark_yellow.gif[size(8,8)][move(10,8)]} +icon.version.tracking.match.table.status.rejected = dialog-cancel.png +icon.version.tracking.match.table.status.blocked = kgpg.png + +icon.version.tracking.match.table.markup.status.disabled = ledgreen.png[size(8,8)][disabled] +icon.version.tracking.match.table.markup.status.not.applied = ledorange.png[size(8,8)][move(0,4)] +icon.version.tracking.match.table.markup.status.applied = ledgreen.png[size(8,8)][move(9,4)] +icon.version.tracking.match.table.markup.status.rejected = ledpurple.png[size(8,8)][move(18,4)] +icon.version.tracking.match.table.markup.status.ignored = ledblue.png[size(8,8)][move(27,4)] +icon.version.tracking.match.table.markup.status.error = ledred.png[size(8,8)][move(36,4)] + +icon.version.tracking.related.match.target = user-online.png +icon.version.tracking.related.match.caller = go-down.png +icon.version.tracking.related.match.callee = go-next.png +icon.version.tracking.related.match.unrelated = user-busy.png +icon.version.tracking.related.match.accepted = accept.png +icon.version.tracking.related.match.available = media-playback-stop.png +icon.version.tracking.related.match.locked.out = edit-delete.png + +icon.version.tracking.match.table.selection.track.row = table_gear.png +icon.version.tracking.match.table.selection.track.match = table_go.png +icon.version.tracking.match.table.selection.track.none = table_delete.png + +icon.version.tracking.table.renderer.multiple.symbols = application_view_detail.png + +icon.version.tracking.new.session.swap = doubleArrowUpDown.png +icon.version.tracking.new.session.info = information.png +icon.version.tracking.correlator.status.already.run = flag-green.png + + +[Dark Defaults] + + +color.bg.version.tracking.dual.listing.highlight.markup.applied = rgb(150, 220, 150) // green +color.bg.version.tracking.dual.listing.highlight.markup.unapplied = rgb(255, 170, 85) // orange +color.bg.version.tracking.dual.listing.highlight.markup.ignored = rgb(220, 220, 220) // gray +color.bg.version.tracking.dual.listing.highlight.markup.rejected = rgb(250, 200, 200) // pink +color.bg.version.tracking.dual.listing.highlight.markup.failed = rgb(255, 80, 80) // red +color.bg.version.tracking.dual.listing.highlight.markup.no.address = rgb(205, 185, 220) // purple +color.bg.version.tracking.dual.listing.highlight.markup.same = rgb(175, 225, 255) // light blue +color.bg.version.tracking.dual.listing.highlight.markup.conflict = rgb(255, 225, 105) // gold + +color.bg.version.tracking.filter.formatted.field.error = rgb(218, 217, 206) // grayish +color.bg.version.tracking.filter.formatted.field.editing = rgb(243, 242, 131) // yellowish + +color.bg.version.tracking.match.table.locked.out = whitesmoke +color.bg.version.tracking.match.table.markup.status.applied = rgb(0, 180, 0) // green +color.bg.version.tracking.match.table.markup.status.rejected = red +color.bg.version.tracking.match.table.markup.status.dont.care = royalblue +color.bg.version.tracking.match.table.markup.status.dont.know = orange +color.fg.version.tracking.match.table.error = color.fg.error + +color.fg.version.tracking.markup.items.table.error = color.fg.error +color.fg.version.tracking.markup.items.table.user.defined.address = cyan +color.fg.version.tracking.markup.items.table.user.defined.address.selected = lightseagreen + +color.bg.version.tracking.related.matches.table.good = green +color.bg.version.tracking.related.matches.table.medium = yellow +color.bg.version.tracking.related.matches.table.bad = red + +color.fg.version.tracking.function.match.local.info = green \ No newline at end of file diff --git a/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java index 513ce83b4b..ef12f97735 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java @@ -18,11 +18,11 @@ package ghidra.feature.vt.api.impl; import java.io.IOException; import javax.swing.Icon; -import javax.swing.ImageIcon; import db.DBHandle; import db.OpenMode; import db.buffers.BufferFile; +import generic.theme.GIcon; import ghidra.feature.vt.api.db.VTSessionDB; import ghidra.framework.data.*; import ghidra.framework.model.ChangeSet; @@ -33,11 +33,9 @@ import ghidra.util.Msg; import ghidra.util.exception.CancelledException; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; public class VTSessionContentHandler extends DBContentHandler { - private static ImageIcon ICON = ResourceManager - .getScaledIcon(ResourceManager.loadImage("images/start-here_16.png"), 16, 16); + private static Icon ICON = new GIcon("icon.version.tracking.session.content.type"); public final static String CONTENT_TYPE = "VersionTracking"; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java index 00d8139af2..9527b8cf65 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,14 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -24,15 +31,6 @@ import ghidra.feature.vt.gui.provider.onetomany.VTMatchOneToManyContext; import ghidra.feature.vt.gui.task.AcceptMatchTask; import ghidra.util.HelpLocation; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - public class AcceptMatchAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.EDIT_MENU_GROUP; @@ -43,7 +41,7 @@ public class AcceptMatchAction extends DockingAction { super("Accept", VTPlugin.OWNER); this.controller = controller; - Icon icon = ResourceManager.loadImage("images/flag.png"); + Icon icon = new GIcon("icon.version.tracking.action.accept.match"); setToolBarData(new ToolBarData(icon, MENU_GROUP)); setPopupMenuData(new MenuData(new String[] { "Accept" }, icon, MENU_GROUP)); setEnabled(false); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java index 6f02ce2f38..64ee1c57dd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java @@ -15,18 +15,17 @@ */ package ghidra.feature.vt.gui.actions; -import ghidra.feature.vt.gui.plugin.VTController; -import ghidra.feature.vt.gui.plugin.VTPlugin; -import ghidra.feature.vt.gui.wizard.VTAddToSessionWizardManager; -import ghidra.util.HelpLocation; - import javax.swing.Icon; -import resources.ResourceManager; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; import docking.wizard.WizardManager; +import generic.theme.GIcon; +import ghidra.feature.vt.gui.plugin.VTController; +import ghidra.feature.vt.gui.plugin.VTPlugin; +import ghidra.feature.vt.gui.wizard.VTAddToSessionWizardManager; +import ghidra.util.HelpLocation; public class AddToVersionTrackingSessionAction extends DockingAction { @@ -37,13 +36,8 @@ public class AddToVersionTrackingSessionAction extends DockingAction { super("Add To Session", VTPlugin.OWNER); this.controller = controller; String[] menuPath = { ToolConstants.MENU_FILE, "Add to Session..." }; - Icon plusIcon = ResourceManager.loadImage("images/Plus.png"); - + Icon plusIcon = new GIcon("icon.version.tracking.action.add.to.session"); setMenuBarData(new MenuData(menuPath, plusIcon, "AAA")); - -// Icon baseNewIcon = ResourceManager.loadImage("images/start-here_16.png"); -// MultiIcon addToIcon = new MultiIcon(baseNewIcon, false); -// addToIcon.addIcon(plusIcon); setToolBarData(new ToolBarData(plusIcon, "View")); setDescription("Add additional correlations to the current version tracking session"); setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Add_To_Session")); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java index b6d9b918cb..48531b562e 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,20 +15,19 @@ */ package ghidra.feature.vt.gui.actions; -import ghidra.feature.vt.api.main.VTMatch; -import ghidra.feature.vt.gui.plugin.VTController; -import ghidra.feature.vt.gui.plugin.VTPlugin; -import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; -import ghidra.feature.vt.gui.task.ApplyMatchTask; -import ghidra.util.HelpLocation; - import java.util.List; import javax.swing.Icon; -import resources.ResourceManager; import docking.ActionContext; import docking.action.*; +import ghidra.feature.vt.api.main.VTMatch; +import ghidra.feature.vt.gui.plugin.VTController; +import ghidra.feature.vt.gui.plugin.VTPlugin; +import ghidra.feature.vt.gui.provider.markuptable.MarkupStatusIcons; +import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; +import ghidra.feature.vt.gui.task.ApplyMatchTask; +import ghidra.util.HelpLocation; public class ApplyMatchAction extends DockingAction { @@ -42,7 +40,7 @@ public class ApplyMatchAction extends DockingAction { super(NAME, VTPlugin.OWNER); this.controller = controller; - Icon icon = ResourceManager.loadImage("images/checkmark_green.gif"); + Icon icon = MarkupStatusIcons.APPLIED_ICON; setToolBarData(new ToolBarData(icon, MENU_GROUP)); setPopupMenuData(new MenuData(new String[] { NAME }, icon, MENU_GROUP)); setEnabled(false); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java index 6906cf6e7b..6a9651cbfe 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java @@ -20,19 +20,19 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTSession; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.util.HTMLUtilities; import ghidra.util.HelpLocation; import ghidra.util.task.TaskLauncher; -import resources.ResourceManager; /** * This action runs the {@link AutoVersionTrackingTask} */ public class AutoVersionTrackingAction extends DockingAction { - public static Icon AUTO_VT_ICON = ResourceManager.loadImage("images/wizard.png"); + public static Icon AUTO_VT_ICON = new GIcon("icon.version.tracking.auto"); private final VTController controller; public AutoVersionTrackingAction(VTController controller) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java index 0beb435c0b..3a796e2898 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java @@ -24,18 +24,18 @@ import javax.swing.*; import docking.ActionContext; import docking.DialogComponentProvider; import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.*; import ghidra.feature.vt.gui.editors.MatchTagComboBox; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class ChooseMatchTagAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.TAG_MENU_GROUP; - private static final Icon EDIT_TAG_ICON = ResourceManager.loadImage("images/tag_blue.png"); + private static final Icon EDIT_TAG_ICON = new GIcon("icon.version.tracking.action.choose.tag"); private static final String ACTION_NAME = "Choose Match Tag"; private final VTController controller; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java index 5fe2a61213..5c2105d7ee 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,14 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -24,19 +31,10 @@ import ghidra.feature.vt.gui.provider.onetomany.VTMatchOneToManyContext; import ghidra.feature.vt.gui.task.ClearMatchTask; import ghidra.util.HelpLocation; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - public class ClearMatchAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.UNEDIT_MENU_GROUP; - private static final Icon ICON = ResourceManager.loadImage("images/undo-apply.png"); + private static final Icon ICON = new GIcon("icon.version.tracking.action.clear.match"); private final VTController controller; public ClearMatchAction(VTController controller) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java index e57d71fc76..9bb9d73856 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java @@ -17,10 +17,11 @@ package ghidra.feature.vt.gui.actions; import java.util.List; -import javax.swing.ImageIcon; +import javax.swing.Icon; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -30,7 +31,6 @@ import ghidra.feature.vt.gui.task.*; import ghidra.util.HelpLocation; import ghidra.util.task.Task; import ghidra.util.task.TaskListener; -import resources.ResourceManager; public class CreateImpliedMatchAction extends DockingAction { @@ -43,7 +43,7 @@ public class CreateImpliedMatchAction extends DockingAction { this.controller = controller; this.provider = provider; - ImageIcon icon = ResourceManager.loadImage("images/flag.png"); + Icon icon = new GIcon("icon.version.tracking.action.create.implied.match"); setToolBarData(new ToolBarData(icon, "1")); setPopupMenuData(new MenuData(new String[] { "Accept Implied Match" }, icon, "1")); setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Accept_Implied_Match")); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java index 4353ac7f90..e00fbb5916 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java @@ -15,6 +15,12 @@ */ package ghidra.feature.vt.gui.actions; +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.MenuData; +import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTSession; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -25,19 +31,13 @@ import ghidra.util.HelpLocation; import ghidra.util.task.Task; import ghidra.util.task.TaskListener; -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - /** * Action that creates a manual match for the currently selected source and destination functions * in the function association tables. */ public class CreateManualMatchAction extends AbstractCreateManualMatchAction { - public static final Icon ICON = ResourceManager.loadImage("images/Plus.png"); + public static final Icon ICON = new GIcon("icon.version.tracking.action.create.manual.match"); /** * Creates a manual match action. diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java index ca1655f3d6..9a6cec4144 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java @@ -15,6 +15,12 @@ */ package ghidra.feature.vt.gui.actions; +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.MenuData; +import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.functionassociation.FunctionAssociationContext; @@ -24,19 +30,14 @@ import ghidra.util.HelpLocation; import ghidra.util.task.Task; import ghidra.util.task.TaskListener; -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - /** * Action that creates a manual match for the currently selected source and destination functions * in the function association tables and then accepts the match. */ public class CreateManualMatchAndAcceptAction extends AbstractCreateManualMatchAction { - public static final Icon ICON = ResourceManager.loadImage("images/flag.png"); + public static final Icon ICON = + new GIcon("icon.version.tracking.action.create.and.accept.manual.match"); /** * Creates a manual match action that also does an accept of that match. @@ -48,7 +49,8 @@ public class CreateManualMatchAndAcceptAction extends AbstractCreateManualMatchA setToolBarData(new ToolBarData(ICON, MENU_GROUP)); setPopupMenuData(new MenuData(new String[] { "Create And Accept Manual Match" }, ICON)); setEnabled(false); - setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Create_And_Accept_Manual_Match")); + setHelpLocation( + new HelpLocation("VersionTrackingPlugin", "Create_And_Accept_Manual_Match")); } @Override diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java index 5804aff3f5..baa117c068 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java @@ -15,6 +15,12 @@ */ package ghidra.feature.vt.gui.actions; +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.MenuData; +import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.functionassociation.FunctionAssociationContext; @@ -24,19 +30,14 @@ import ghidra.util.HelpLocation; import ghidra.util.task.Task; import ghidra.util.task.TaskListener; -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - /** * Action that creates a manual match for the currently selected source and destination functions * in the function association tables and then applies the match. */ public class CreateManualMatchAndAcceptAndApplyAction extends AbstractCreateManualMatchAction { - public static final Icon ICON = ResourceManager.loadImage("images/checkmark_green.gif"); + public static final Icon ICON = + new GIcon("icon.version.tracking.action.create.accept.and.apply.manual.match"); /** * Creates a manual match action that also does an apply of that match. diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java index dad1804b93..73be37bffd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java @@ -21,6 +21,7 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTAssociation; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.gui.plugin.VTController; @@ -29,12 +30,11 @@ import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; import ghidra.program.model.address.AddressSet; import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class CreateSelectionAction extends DockingAction { public static final String NAME = "Create Match Table Selection"; private static final String MENU_GROUP = "Selection"; - private static final Icon ICON = ResourceManager.loadImage("images/text_align_justify.png"); + private static final Icon ICON = new GIcon("icon.version.tracking.action.create.selection"); private final VTController controller; public CreateSelectionAction(VTController controller) { @@ -44,7 +44,8 @@ public class CreateSelectionAction extends DockingAction { setPopupMenuData(new MenuData(new String[] { "Make Selections" }, ICON, MENU_GROUP)); setEnabled(false); setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Make Selections")); - setDescription("Makes selections in both the source and destination tools for the selected matches."); + setDescription( + "Makes selections in both the source and destination tools for the selected matches."); } @Override diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java index 2e56d1553c..b31b823e4c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java @@ -15,22 +15,21 @@ */ package ghidra.feature.vt.gui.actions; -import ghidra.feature.vt.gui.plugin.VTController; -import ghidra.feature.vt.gui.plugin.VTPlugin; -import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager; -import ghidra.util.HelpLocation; - import javax.swing.Icon; -import resources.ResourceManager; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; import docking.widgets.OptionDialog; import docking.wizard.WizardManager; +import generic.theme.GIcon; +import ghidra.feature.vt.gui.plugin.VTController; +import ghidra.feature.vt.gui.plugin.VTPlugin; +import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager; +import ghidra.util.HelpLocation; public class CreateVersionTrackingSessionAction extends DockingAction { - public static Icon NEW_ICON = ResourceManager.loadImage("images/start-here_16.png"); + public static Icon NEW_ICON = new GIcon("icon.version.tracking.action.create.session"); private final VTController controller; public CreateVersionTrackingSessionAction(VTController controller) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java index b89305b931..e22adc3c5d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,22 +15,22 @@ */ package ghidra.feature.vt.gui.actions; +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.gui.editors.TagEditorDialog; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; import ghidra.util.HelpLocation; -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - public class EditAllTagsAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.TAG_MENU_GROUP; - private static final Icon EDIT_TAG_ICON = ResourceManager.loadImage("images/tag_blue_edit.png"); + private static final Icon EDIT_TAG_ICON = + new GIcon("icon.version.tracking.action.edit.all.tags"); private static final String ACTION_NAME = "Edit VTMatch Tags"; private final VTController controller; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java index ab9ebc31af..e07b112ad6 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,15 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.*; + +import docking.ActionContext; +import docking.DialogComponentProvider; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMarkupItem; import ghidra.feature.vt.api.main.VTMarkupItemDestinationAddressEditStatus; import ghidra.feature.vt.gui.editors.*; @@ -28,21 +36,11 @@ import ghidra.program.model.listing.Program; import ghidra.util.*; import ghidra.util.exception.InvalidInputException; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.*; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.DialogComponentProvider; -import docking.action.*; - public class EditMarkupAddressAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.ADDRESS_EDIT_MENU_GROUP; private static final Icon EDIT_ADDRESS_ICON = - ResourceManager.loadImage("images/edit-rename.png"); + new GIcon("icon.version.tracking.action.edit.markup.address"); private static final String ACTION_NAME = "Edit Markup Destination Address"; final VTController controller; @@ -55,7 +53,8 @@ public class EditMarkupAddressAction extends DockingAction { setToolBarData(new ToolBarData(EDIT_ADDRESS_ICON, MENU_GROUP)); } MenuData menuData = - new MenuData(new String[] { "Edit Destination Address" }, EDIT_ADDRESS_ICON, MENU_GROUP); + new MenuData(new String[] { "Edit Destination Address" }, EDIT_ADDRESS_ICON, + MENU_GROUP); setPopupMenuData(menuData); setEnabled(false); setHelpLocation(new HelpLocation("VersionTrackingPlugin", diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java index ee2ed7903b..c935c00de9 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java @@ -27,11 +27,12 @@ import ghidra.util.HelpLocation; import ghidra.util.Msg; import help.Help; import help.HelpService; +import resources.Icons; import resources.ResourceManager; public class HelpAction extends DockingAction { - private static Icon ICON = ResourceManager.loadImage("images/help-browser.png"); + private static Icon ICON = Icons.HELP_ICON; public HelpAction() { super("Version Tracking Help Action", VTPlugin.OWNER); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java index 14749bd31b..35e405ce44 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java @@ -23,10 +23,10 @@ import docking.action.ToolBarData; import docking.menu.ActionState; import docking.menu.MultiStateDockingAction; import docking.widgets.EventTrigger; +import generic.theme.GIcon; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class MatchTableSelectionAction extends MultiStateDockingAction { @@ -49,9 +49,12 @@ public class MatchTableSelectionAction new HelpLocation("VersionTrackingPlugin", "Match_Table_Selection"); setHelpLocation(helpLocation); - Icon noSelectionTrackingIcon = ResourceManager.loadImage("images/table_delete.png"); - Icon trackMatchSelectionIcon = ResourceManager.loadImage("images/table_go.png"); - Icon trackRowIndexSelectionIcon = ResourceManager.loadImage("images/table_gear.png"); + Icon noSelectionTrackingIcon = + new GIcon("icon.version.tracking.match.table.selection.track.none"); + Icon trackMatchSelectionIcon = + new GIcon("icon.version.tracking.match.table.selection.track.match"); + Icon trackRowIndexSelectionIcon = + new GIcon("icon.version.tracking.match.table.selection.track.row"); ActionState trackSelectedIndexActionState = new ActionState<>("Track Selected Index", diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java index 5a6b422f7e..3e56e4e832 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java @@ -23,12 +23,12 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.feature.vt.api.db.VTSessionDB; import ghidra.feature.vt.api.main.VTSession; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.util.*; -import resources.ResourceManager; public class RedoAction extends DockingAction { private final VTController controller; @@ -39,7 +39,7 @@ public class RedoAction extends DockingAction { setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Redo")); String[] menuPath = { ToolConstants.MENU_EDIT, "&Redo" }; String group = "ZZUndo"; - Icon icon = ResourceManager.loadImage("images/redo.png"); + Icon icon = new GIcon("icon.redo"); MenuData menuData = new MenuData(menuPath, icon, group); menuData.setMenuSubGroup("2Redo"); // make this appear below the undo menu item setMenuBarData(menuData); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java index dad1e1cc4e..c04619dd94 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,13 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.List; + +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.api.main.VTSession; import ghidra.feature.vt.gui.plugin.VTController; @@ -24,18 +30,10 @@ import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; import ghidra.feature.vt.gui.task.RejectMatchTask; import ghidra.util.HelpLocation; -import java.util.List; - -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - public class RejectMatchAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.EDIT_MENU_GROUP; - private static final Icon ICON = ResourceManager.loadImage("images/dialog-cancel.png"); + private static final Icon ICON = new GIcon("icon.version.tracking.action.match.reject"); private final VTController controller; public RejectMatchAction(VTController controller) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java index 760fa1b9d9..77483d07d7 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,14 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.List; + +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.DockingAction; +import docking.action.MenuData; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.api.main.VTSession; import ghidra.feature.vt.gui.plugin.VTController; @@ -24,19 +31,10 @@ import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext; import ghidra.feature.vt.gui.task.RemoveMatchTask; import ghidra.util.HelpLocation; -import java.util.List; - -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.DockingAction; -import docking.action.MenuData; - public class RemoveMatchAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.UNEDIT_MENU_GROUP; - private static final Icon ICON = ResourceManager.loadImage("images/edit-delete.png"); + private static final Icon ICON = new GIcon("icon.version.tracking.action.match.remove"); private final VTController controller; public RemoveMatchAction(VTController controller) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java index ed63f3ca24..92318bf62a 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,16 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.List; + +import javax.swing.Icon; +import javax.swing.JComponent; + +import docking.ActionContext; +import docking.ComponentProvider; +import docking.action.*; +import docking.widgets.OptionDialog; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.api.main.VTMatchTag; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -24,22 +33,11 @@ import ghidra.feature.vt.gui.task.ClearMatchTagTask; import ghidra.util.HelpLocation; import ghidra.util.task.TaskLauncher; -import java.util.List; - -import javax.swing.Icon; -import javax.swing.JComponent; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.ComponentProvider; -import docking.action.*; -import docking.widgets.OptionDialog; - public class RemoveMatchTagAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.TAG_MENU_GROUP; private static final Icon EDIT_TAG_ICON = - ResourceManager.loadImage("images/tag_blue_delete.png"); + new GIcon("icon.version.tracking.action.match.tag.remove"); private static final String ACTION_NAME = "Remove VTMatch Tags"; private int tagCount = 0; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java index 09e1e1eb79..ff6203ba7a 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java @@ -18,10 +18,10 @@ package ghidra.feature.vt.gui.actions; import static ghidra.feature.vt.gui.util.VTOptionDefines.*; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.action.MenuData; import docking.action.ToolBarData; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMarkupItemApplyActionType; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -40,7 +40,7 @@ public class ReplaceDefaultMarkupItemAction extends AbstractMarkupItemAction { super(controller, "Apply (Replace Default Only)"); Icon replacedIcon = VTPlugin.REPLACED_ICON; - ImageIcon warningIcon = ResourceManager.loadImage("images/warning.png"); + Icon warningIcon = new GIcon("icon.warning"); warningIcon = ResourceManager.getScaledIcon(warningIcon, 12, 12); int warningIconWidth = warningIcon.getIconWidth(); int warningIconHeight = warningIcon.getIconHeight(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java index 0303cfde1c..cd32f9a58c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java @@ -15,10 +15,9 @@ */ package ghidra.feature.vt.gui.actions; -import static ghidra.feature.vt.gui.util.VTOptionDefines.DATA_MATCH_DATA_TYPE; +import static ghidra.feature.vt.gui.util.VTOptionDefines.*; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.action.MenuData; import docking.action.ToolBarData; @@ -28,9 +27,6 @@ import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.util.VTMatchApplyChoices.ReplaceDataChoices; import ghidra.framework.options.ToolOptions; import ghidra.util.HelpLocation; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.TranslateIcon; /** * Action that replaces Data for a version tracking data match, but only if no defined data @@ -54,22 +50,9 @@ public class ReplaceFirstMarkupItemAction extends AbstractMarkupItemAction { super(controller, "Apply (Replace First Only)"); Icon replacedIcon = VTPlugin.REPLACED_ICON; - ImageIcon warningIcon = ResourceManager.loadImage("images/warning_obj.png"); - warningIcon = ResourceManager.getScaledIcon(warningIcon, 12, 12); - MultiIcon multiIcon = new MultiIcon(replacedIcon, false); - int refreshIconWidth = replacedIcon.getIconWidth(); - int refreshIconHeight = replacedIcon.getIconHeight(); - int warningIconWidth = warningIcon.getIconWidth(); - int warningIconHeight = warningIcon.getIconHeight(); - - int x = refreshIconWidth - warningIconWidth; - int y = refreshIconHeight - warningIconHeight; - - TranslateIcon translateIcon = new TranslateIcon(warningIcon, x, y); - multiIcon.addIcon(translateIcon); if (addToToolbar) { - setToolBarData(new ToolBarData(multiIcon, MENU_GROUP)); + setToolBarData(new ToolBarData(replacedIcon, MENU_GROUP)); } MenuData menuData = new MenuData(new String[] { "Apply (Replace First Only)" }, replacedIcon, MENU_GROUP); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java index 9c5889a31d..9e95518f77 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,13 @@ */ package ghidra.feature.vt.gui.actions; +import java.util.List; + +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.*; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; @@ -26,17 +32,9 @@ import ghidra.util.HelpLocation; import ghidra.util.task.Task; import ghidra.util.task.TaskListener; -import java.util.List; - -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - public class ResetMarkupItemAction extends DockingAction { - public static final Icon RESET_ICON = ResourceManager.loadImage("images/undo-apply.png"); + public static final Icon RESET_ICON = new GIcon("icon.version.tracking.action.markup.reset"); private static final String MENU_GROUP = VTPlugin.UNEDIT_MENU_GROUP; final VTController controller; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java index 227f831f45..84bd93597f 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java @@ -15,13 +15,14 @@ */ package ghidra.feature.vt.gui.actions; -import static ghidra.feature.vt.gui.plugin.VTPlugin.VT_MAIN_MENU_GROUP; +import static ghidra.feature.vt.gui.plugin.VTPlugin.*; import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.feature.vt.api.db.VTSessionDB; import ghidra.feature.vt.api.main.VTSession; import ghidra.feature.vt.gui.plugin.VTController; @@ -31,11 +32,10 @@ import ghidra.framework.model.DomainFile; import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; import ghidra.util.task.TaskLauncher; -import resources.ResourceManager; public class SaveVersionTrackingSessionAction extends DockingAction { - static final Icon ICON = ResourceManager.loadImage("images/disk.png"); + static final Icon ICON = new GIcon("icon.version.tracking.action.save.session"); private final VTController controller; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java index de612ee9fd..c60586094d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java @@ -19,12 +19,12 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.functionassociation.FunctionAssociationContext; import ghidra.util.HelpLocation; -import resources.ResourceManager; /** * Action that selects the function match, if it exists, for the currently selected source and @@ -32,7 +32,8 @@ import resources.ResourceManager; */ public class SelectExistingMatchAction extends DockingAction { - private static final Icon ICON = ResourceManager.loadImage("images/text_align_justify.png"); + private static final Icon ICON = + new GIcon("icon.version.tracking.action.match.select.existing"); private static final String MENU_GROUP = "Create"; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java index 82703c20ee..0a2aa62dac 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java @@ -21,18 +21,18 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTMatch; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.feature.vt.gui.provider.onetomany.VTMatchOneToManyContext; import ghidra.util.HelpLocation; -import resources.ResourceManager; public class SetVTMatchFromOneToManyAction extends DockingAction { private static final String MENU_GROUP = VTPlugin.VT_MAIN_MENU_GROUP; public static final Icon SET_MATCH_ICON = - ResourceManager.loadImage("images/text_align_justify.png"); + new GIcon("icon.version.tracking.action.match.one.to.many"); final VTController controller; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java index 600c3cd30f..b234c78b20 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java @@ -23,11 +23,11 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.*; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.feature.vt.api.db.VTSessionDB; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.util.*; -import resources.ResourceManager; public class UndoAction extends DockingAction { private final VTController controller; @@ -38,7 +38,7 @@ public class UndoAction extends DockingAction { setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Undo")); String[] menuPath = { ToolConstants.MENU_EDIT, "&Undo" }; String group = "ZZUndo"; - Icon icon = ResourceManager.loadImage("images/undo.png"); + Icon icon = new GIcon("icon.undo"); MenuData menuData = new MenuData(menuPath, icon, group); menuData.setMenuSubGroup("1Undo"); // make this appear above the redo menu item setMenuBarData(menuData); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/duallisting/VTDualListingHighlightProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/duallisting/VTDualListingHighlightProvider.java index f144b618a1..07a21479b5 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/duallisting/VTDualListingHighlightProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/duallisting/VTDualListingHighlightProvider.java @@ -15,6 +15,11 @@ */ package ghidra.feature.vt.gui.duallisting; +import java.awt.Color; +import java.util.*; + +import docking.widgets.fieldpanel.support.Highlight; +import generic.theme.GColor; import ghidra.app.plugin.core.codebrowser.ListingHighlightProvider; import ghidra.app.util.HighlightProvider; import ghidra.app.util.viewer.field.*; @@ -32,24 +37,27 @@ import ghidra.program.model.listing.*; import ghidra.util.Msg; import ghidra.util.exception.AssertException; -import java.awt.Color; -import java.util.*; - -import docking.widgets.fieldpanel.support.Highlight; - public class VTDualListingHighlightProvider implements HighlightProvider { - private static Color APPLIED_MARKUP_COLOR = new Color(150, 220, 150); // green - private static Color UNAPPLIED_MARKUP_COLOR = new Color(255, 170, 85); // orange - private static Color IGNORED_MARKUP_COLOR = new Color(220, 220, 220); // gray - private static Color REJECTED_MARKUP_COLOR = new Color(250, 200, 200); // pink - private static Color FAILED_MARKUP_COLOR = new Color(255, 80, 80); // red - private static Color NO_ADDRESS_MARKUP_COLOR = new Color(205, 185, 220); // purple - private static Color SAME_MARKUP_COLOR = new Color(175, 225, 255); // light blue - private static Color CONFLICT_MARKUP_COLOR = new Color(255, 225, 105); // gold + private static Color APPLIED_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.applied"); + private static Color UNAPPLIED_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.unapplied"); + private static Color IGNORED_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.ignored"); + private static Color REJECTED_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.rejected"); + private static Color FAILED_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.failed"); + private static Color NO_ADDRESS_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.no.address"); + private static Color SAME_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.same"); + private static Color CONFLICT_MARKUP_COLOR = + new GColor("color.bg.version.tracking.dual.listing.highlight.markup.conflict"); private HashMap> map = - new HashMap>(); + new HashMap<>(); private final VTController controller; private ListingPanel listingPanel; private ListingHighlightProvider listingHighlighter; @@ -112,7 +120,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { HashMap typeMap = map.get(address); if (typeMap == null) { - typeMap = new HashMap (); + typeMap = new HashMap<>(); map.put(address, typeMap); } @@ -203,7 +211,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { cursorTextOffset, highlights); } - List highlightList = new ArrayList (); + List highlightList = new ArrayList<>(); for (Highlight highlight : highlights) { highlightList.add(highlight); @@ -274,7 +282,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { } return highlightColor; } - + /** * Creates a darker shade of the color passed-in, based on the given amount. * @@ -285,22 +293,22 @@ public class VTDualListingHighlightProvider implements HighlightProvider { * * @param color the color to shade * @param amount number between 0..1 (the smaller the number, the darker the shade) - * @return + * @return the new color */ private static Color shade(Color color, double amount) { if (color != null) { - + int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); - + double newR = (r * amount); double newG = (g * amount); double newB = (b * amount); - - return new Color((int)newR, (int)newG, (int)newB); + + return new Color((int) newR, (int) newG, (int) newB); } - + return null; } @@ -315,7 +323,8 @@ public class VTDualListingHighlightProvider implements HighlightProvider { if (markupItem != null) { VTMarkupItemStatus status = markupItem.getStatus(); StringStringable value = - (StringStringable) ((isSource || markupItem.canUnapply()) ? markupItem.getSourceValue() + (StringStringable) ((isSource || markupItem.canUnapply()) + ? markupItem.getSourceValue() : markupItem.getOriginalDestinationValue()); String comment = value.getString(); if (comment != null) { @@ -418,7 +427,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { CodeUnit codeUnit = (CodeUnit) obj; address = codeUnit.getMinAddress(); } - ArrayList highlightList = new ArrayList (); + ArrayList highlightList = new ArrayList<>(); HashMap typeMap = map.get(address); if (typeMap != null) { VTMarkupItem markupItem = typeMap.get(RepeatableCommentMarkupType.INSTANCE); @@ -429,7 +438,8 @@ public class VTDualListingHighlightProvider implements HighlightProvider { return highlightList.toArray(new Highlight[highlightList.size()]); } - private Highlight[] getFunctionSignatureHighlights(String text, Object obj, int cursorTextOffset) { + private Highlight[] getFunctionSignatureHighlights(String text, Object obj, + int cursorTextOffset) { Function function = null; if (obj instanceof Function) { function = (Function) obj; @@ -445,7 +455,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { Address address = function.getEntryPoint(); HashMap typeMap = map.get(address); if (typeMap != null) { - ArrayList highlightList = new ArrayList (); + ArrayList highlightList = new ArrayList<>(); // // Check if the text is in the Return Type // addFunctionHighlight(FunctionReturnTypeMarkupType.INSTANCE, text, cursorTextOffset, @@ -485,7 +495,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { Address address = function.getEntryPoint(); HashMap typeMap = map.get(address); if (typeMap != null) { - ArrayList highlightList = new ArrayList (); + ArrayList highlightList = new ArrayList<>(); VTMarkupItem markupItem = typeMap.get(FunctionSignatureMarkupType.INSTANCE); if (markupItem == null) { @@ -544,7 +554,8 @@ public class VTDualListingHighlightProvider implements HighlightProvider { if (startIndex >= 0) { int endIndex = startIndex + displayString.length() - 1; Color highlightColor = - getMarkupBackgroundColor(cursorTextOffset, markupItem, startIndex, endIndex); + getMarkupBackgroundColor(cursorTextOffset, markupItem, startIndex, + endIndex); Highlight highlight = new Highlight(startIndex, endIndex, highlightColor); highlightList.add(highlight); } @@ -557,7 +568,8 @@ public class VTDualListingHighlightProvider implements HighlightProvider { VTMarkupItem markupItem = typeMap.get(FunctionNameMarkupType.INSTANCE); if (markupItem != null) { FunctionNameStringable value = - (isSource || markupItem.canUnapply()) ? (FunctionNameStringable) markupItem.getSourceValue() + (isSource || markupItem.canUnapply()) + ? (FunctionNameStringable) markupItem.getSourceValue() : (FunctionNameStringable) markupItem.getOriginalDestinationValue(); if (value != null) { int parameterStart = text.indexOf("("); @@ -569,7 +581,8 @@ public class VTDualListingHighlightProvider implements HighlightProvider { if (startIndex >= 0) { int endIndex = startIndex + name.length() - 1; Color highlightColor = - getMarkupBackgroundColor(cursorTextOffset, markupItem, startIndex, endIndex); + getMarkupBackgroundColor(cursorTextOffset, markupItem, startIndex, + endIndex); Highlight highlight = new Highlight(startIndex, endIndex, highlightColor); highlightList.add(highlight); } @@ -832,7 +845,7 @@ public class VTDualListingHighlightProvider implements HighlightProvider { if (storageAddress == null) { return new Highlight[0]; } - ArrayList highlightList = new ArrayList (); + ArrayList highlightList = new ArrayList<>(); HashMap typeMap = map.get(storageAddress); if (typeMap != null) { VTMarkupItem markupItem = typeMap.get(markupType); @@ -914,16 +927,18 @@ public class VTDualListingHighlightProvider implements HighlightProvider { if (typeMap != null) { VTMarkupItem markupItem = typeMap.get(LabelMarkupType.INSTANCE); if (markupItem != null) { - ArrayList highlightList = new ArrayList (); + ArrayList highlightList = new ArrayList<>(); MultipleSymbolStringable value = - (MultipleSymbolStringable) ((isSource || markupItem.canUnapply()) ? markupItem.getSourceValue() + (MultipleSymbolStringable) ((isSource || markupItem.canUnapply()) + ? markupItem.getSourceValue() : markupItem.getOriginalDestinationValue()); if (value != null) { // Highlight the entire labels field. int startIndex = 0; int endIndex = text.length() - 1; Color highlightColor = - getMarkupBackgroundColor(cursorTextOffset, markupItem, startIndex, endIndex); + getMarkupBackgroundColor(cursorTextOffset, markupItem, startIndex, + endIndex); Highlight highlight = new Highlight(startIndex, endIndex, highlightColor); highlightList.add(highlight); return highlightList.toArray(new Highlight[highlightList.size()]); @@ -942,9 +957,10 @@ public class VTDualListingHighlightProvider implements HighlightProvider { if (typeMap != null) { VTMarkupItem markupItem = typeMap.get(DataTypeMarkupType.INSTANCE); if (markupItem != null) { - ArrayList highlightList = new ArrayList (); + ArrayList highlightList = new ArrayList<>(); DataTypeStringable value = - (DataTypeStringable) ((isSource || markupItem.canUnapply()) ? markupItem.getSourceValue() + (DataTypeStringable) ((isSource || markupItem.canUnapply()) + ? markupItem.getSourceValue() : markupItem.getOriginalDestinationValue()); if (value != null) { Program sourceProgram = diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java index 870f93b6f3..6626309f97 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java @@ -15,7 +15,7 @@ */ package ghidra.feature.vt.gui.editors; -import static ghidra.feature.vt.gui.editors.TagEditorDialog.TagState.Action.ADD; +import static ghidra.feature.vt.gui.editors.TagEditorDialog.TagState.Action.*; import java.awt.*; import java.awt.event.MouseAdapter; @@ -25,18 +25,19 @@ import javax.swing.*; import docking.widgets.label.GDLabel; import docking.widgets.list.GListCellRenderer; +import generic.theme.GIcon; import ghidra.feature.vt.gui.editors.TagEditorDialog.TagState; import ghidra.feature.vt.gui.editors.TagEditorDialog.TagStateListModel; import ghidra.util.exception.AssertException; -import resources.ResourceManager; public class TagEditorRenderer extends GListCellRenderer { - private static final Icon NEW_TAG_ICON = ResourceManager.loadImage("images/tag_blue_add.png"); + private static final Icon NEW_TAG_ICON = new GIcon("icon.version.tracking.tag.status.new"); private static final Icon DELETED_TAG_ICON = - ResourceManager.loadImage("images/tag_blue_delete.png"); - private static final Icon EXISTING_TAG_ICON = ResourceManager.loadImage("images/tag_blue.png"); - private static final Icon UNDO_ICON = ResourceManager.loadImage("images/undo-apply.png"); + new GIcon("icon.version.tracking.tag.status.deleted"); + private static final Icon EXISTING_TAG_ICON = + new GIcon("icon.version.tracking.tag.status.existing"); + private static final Icon UNDO_ICON = new GIcon("icon.version.tracking.tag.button.undo"); private final JList list; private final TagStateListModel listModel; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/AbstractAddressRangeFilter.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/AbstractAddressRangeFilter.java index 5474428836..ea095b9100 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/AbstractAddressRangeFilter.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/AbstractAddressRangeFilter.java @@ -30,11 +30,14 @@ import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.GDLabel; import docking.widgets.label.GHtmlLabel; import docking.widgets.textfield.HexIntegerFormatter; +import generic.theme.GColor; import ghidra.feature.vt.api.main.VTAssociation; import ghidra.feature.vt.gui.provider.matchtable.NumberRangeProducer; import ghidra.feature.vt.gui.provider.matchtable.NumberRangeSubFilterChecker; import ghidra.framework.options.SaveState; import ghidra.program.model.address.Address; +import ghidra.util.ColorUtils; +import ghidra.util.WebColors; public abstract class AbstractAddressRangeFilter extends AncillaryFilter implements NumberRangeSubFilterChecker, NumberRangeProducer { @@ -46,6 +49,8 @@ public abstract class AbstractAddressRangeFilter extends AncillaryFilter private static final String UPPER_RANGE_SELECTED_VALUE_KEY = "upper.range.selected.value.key"; private static final String IS_ENABLED_VALUE_KEY = "is.enabled.value.key"; + private static final Color FG_TOOLTIP_DEFAULT = new GColor("color.fg.version.tracking.tooltip"); + private static final Integer BASE_COMPONENT_LAYER = 1; private static final Integer HOVER_COMPONENT_LAYER = 2; private static final Integer DISABLED_COMPONENT_LAYER = 3; @@ -118,8 +123,10 @@ public abstract class AbstractAddressRangeFilter extends AncillaryFilter // // Lower Score Panel // + String fgColor = WebColors.toString(FG_TOOLTIP_DEFAULT); lowerRangePanel = new JPanel(new GridLayout(2, 1)); - JLabel lowLabel = new GHtmlLabel("low"); + JLabel lowLabel = + new GHtmlLabel("low"); lowLabel.setHorizontalAlignment(SwingConstants.CENTER); lowLabel.setVerticalAlignment(SwingConstants.BOTTOM); lowerRangePanel.add(lowLabel); @@ -138,7 +145,8 @@ public abstract class AbstractAddressRangeFilter extends AncillaryFilter // Upper Score Panel // upperRangePanel = new JPanel(new GridLayout(2, 1)); - JLabel upperLabel = new GHtmlLabel("high"); + JLabel upperLabel = + new GHtmlLabel("high"); upperLabel.setHorizontalAlignment(SwingConstants.CENTER); upperLabel.setVerticalAlignment(SwingConstants.BOTTOM); upperRangePanel.add(upperLabel); @@ -201,7 +209,7 @@ public abstract class AbstractAddressRangeFilter extends AncillaryFilter @Override protected void paintComponent(Graphics g) { Color bg = getBackground(); - Color disabledColor = new Color(bg.getRed(), bg.getGreen(), bg.getBlue(), 100); + Color disabledColor = ColorUtils.withAlpha(bg, 100); g.setColor(disabledColor); g.fillRect(0, 0, getWidth(), getHeight()); } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java index 732f53ddf9..32c3b177b3 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java @@ -22,9 +22,9 @@ import java.util.Set; import javax.swing.Icon; import javax.swing.JComponent; +import generic.theme.GIcon; import ghidra.framework.options.SaveState; import ghidra.util.exception.AssertException; -import resources.ResourceManager; /** * An interface to allow clients to provide a mechanism for filtering objects and to notify @@ -74,10 +74,11 @@ public abstract class Filter { public enum FilterEditingStatus { NONE("", null), - DIRTY("Filter contents have changed, but are not yet applied", ResourceManager.loadImage( - "images/bullet_black.png")), - ERROR("Filter contents are not valid", ResourceManager.loadImage("images/no_small.png")), - APPLIED("Filter applied", ResourceManager.loadImage("images/bullet_green.png")); + DIRTY("Filter contents have changed, but are not yet applied", new GIcon( + "icon.version.tracking.filter.status.changed")), + ERROR("Filter contents are not valid", new GIcon( + "icon.version.tracking.filter.status.invalid")), + APPLIED("Filter applied", new GIcon("icon.version.tracking.filter.status.applied")); private final String description; private final Icon icon; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/FilterFormattedTextField.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/FilterFormattedTextField.java index bdcf2965dd..499bf810bd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/FilterFormattedTextField.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/FilterFormattedTextField.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +15,10 @@ */ package ghidra.feature.vt.gui.filters; -import static ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus.APPLIED; -import static ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus.NONE; -import ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus; -import ghidra.util.SystemUtilities; +import static ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus.*; import java.awt.Color; import java.awt.event.FocusEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.text.ParseException; import java.util.HashSet; import java.util.Set; @@ -33,12 +27,18 @@ import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -public class FilterFormattedTextField extends JFormattedTextField { - private static final Color ERROR_BACKGROUND_COLOR = new Color(218, 217, 206); - private static final String TEXT_FIELD_BACKGROUND_COLOR_KEY = "TextField.background"; - protected static final Color EDITING_BACKGROUND_COLOR = new Color(243, 242, 131); +import generic.theme.GColor; +import ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus; +import ghidra.util.SystemUtilities; - private Set listeners = new HashSet (); +public class FilterFormattedTextField extends JFormattedTextField { + private static final Color ERROR_BACKGROUND_COLOR = + new GColor("color.bg.version.tracking.filter.formatted.field.error"); + protected static final Color EDITING_BACKGROUND_COLOR = + new GColor("color.bg.version.tracking.filter.formatted.field.editing"); + private static final String TEXT_FIELD_BACKGROUND_COLOR_KEY = "TextField.background"; + + private Set listeners = new HashSet<>(); private FilterEditingStatus currentStatus = NONE; private final Object defaultValue; @@ -57,24 +57,23 @@ public class FilterFormattedTextField extends JFormattedTextField { this.currentStatus = NONE; getDocument().addDocumentListener(new DocumentListener() { + @Override public void removeUpdate(DocumentEvent e) { updateText(); } + @Override public void insertUpdate(DocumentEvent e) { updateText(); } + @Override public void changedUpdate(DocumentEvent e) { updateText(); } }); - addPropertyChangeListener("value", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - editingFinished(); - } - }); + addPropertyChangeListener("value", evt -> editingFinished()); } public void disableFocusEventProcessing() { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java index 320e025640..62c1a94e02 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java @@ -19,11 +19,13 @@ import java.net.URL; import java.util.List; import java.util.Set; -import javax.swing.*; +import javax.swing.Icon; +import javax.swing.JFrame; import docking.action.DockingActionIf; import docking.tool.ToolConstants; import docking.wizard.WizardManager; +import generic.theme.GIcon; import ghidra.GhidraOptions; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.colorizer.ColorizingService; @@ -48,9 +50,7 @@ import ghidra.program.util.ProgramLocation; import ghidra.util.*; import help.Help; import help.HelpService; -import resources.MultiIcon; import resources.ResourceManager; -import resources.icons.*; //@formatter:off @PluginInfo( @@ -80,25 +80,10 @@ public class VTPlugin extends Plugin { public static final String UNEDIT_MENU_GROUP = "A_VT_UnEdit"; public static final String VT_SETTINGS_MENU_GROUP = "ZZ_VT_SETTINGS"; - public static final Icon UNFILTERED_ICON = - ResourceManager.loadImage("images/lightbulb_off.png"); - public static final Icon FILTERED_ICON = ResourceManager.loadImage("images/lightbulb.png"); - public static final Icon REPLACED_ICON = ResourceManager.loadImage("images/sync_enabled.png"); - public static final Icon UNIGNORED_ICON = new IconWrapper() { - @Override - protected Icon createIcon() { - MultiIcon icon = new MultiIcon(new EmptyIcon(16, 16)); - ImageIcon cancelIcon = ResourceManager.loadImage("images/dialog-cancel.png"); - ScaledImageIcon scaledCancelIcon = - new ScaledImageIcon(cancelIcon, 13, 13); - TranslateIcon translatedCancelIcon = new TranslateIcon(scaledCancelIcon, 3, 4); - ImageIcon undoIcon = ResourceManager.loadImage("images/undo.png"); - TranslateIcon translatedUndoIcon = new TranslateIcon(undoIcon, 0, -4); - icon.addIcon(translatedUndoIcon); - icon.addIcon(translatedCancelIcon); - return icon; - } - }; + public static final Icon UNFILTERED_ICON = new GIcon("icon.version.tracking.unfiltered"); + public static final Icon FILTERED_ICON = new GIcon("icon.version.tracking.filtered"); + public static final Icon REPLACED_ICON = new GIcon("icon.version.tracking.replaced"); + public static final Icon UNIGNORED_ICON = new GIcon("icon.version.tracking.unignored"); private VTController controller; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java index 5c145b0f1e..7007883487 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,19 +15,18 @@ */ package ghidra.feature.vt.gui.plugin; -import ghidra.framework.plugintool.util.PluginPackage; - import javax.swing.Icon; -import resources.ResourceManager; +import generic.theme.GIcon; +import ghidra.framework.plugintool.util.PluginPackage; public class VersionTrackingPluginPackage extends PluginPackage { public static final String NAME = "Version Tracking"; - public static final Icon ICON = ResourceManager.loadImage("images/start-here.png"); - + public static final Icon ICON = new GIcon("icon.version.tracking.package"); + public VersionTrackingPluginPackage() { - super(NAME, ICON, - "These plugins provide feature for performing version tracking between programs." ); + super(NAME, ICON, + "These plugins provide feature for performing version tracking between programs."); } } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java index a05c432e0f..535fc4160c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java @@ -37,6 +37,8 @@ import docking.widgets.EventTrigger; import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.label.GDLabel; import docking.widgets.table.threaded.ThreadedTableModel; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.app.plugin.core.functioncompare.FunctionComparisonPanel; import ghidra.app.services.GoToService; import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel; @@ -60,7 +62,6 @@ import ghidra.util.HelpLocation; import ghidra.util.SystemUtilities; import ghidra.util.table.*; import resources.Icons; -import resources.ResourceManager; /** * Provider for the version tracking function association table. @@ -70,15 +71,16 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter private static final String FILTER_SETTINGS_KEY = "FUNCTION_FILTER_SETTINGS"; private static final String BASE_TITLE = "Version Tracking Functions"; - private static final ImageIcon PROVIDER_ICON = - ResourceManager.loadImage("images/functions.gif"); + private static final Icon PROVIDER_ICON = new GIcon("icon.version.tracking.provider.function"); private static final String SOURCE_TITLE = "Source"; private static final String DESTINATION_TITLE = "Destination"; private static final String NO_SESSION = "None"; private static final Icon SHOW_LISTINGS_ICON = - ResourceManager.loadImage("images/application_tile_horizontal.png"); + new GIcon("icon.version.tracking.action.show.listings"); private static final String SHOW_COMPARE_ACTION_GROUP = "A9_ShowCompare"; // "A9_" forces to right of other dual view actions in toolbar. + private static final Color FG_ERROR = new GColor("color.fg.error"); + private GhidraTable sourceFunctionsTable; private GhidraTable destinationFunctionsTable; private VTFunctionAssociationTableModel sourceFunctionsModel; @@ -155,13 +157,13 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter filterAction.setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Functions_Filter")); - Icon allFunctionsIcon = ResourceManager.loadImage("images/function.png"); + Icon allFunctionsIcon = new GIcon("icon.version.tracking.function.filter.all"); ActionState allFunctionsActionState = new ActionState<>("Show All Functions", allFunctionsIcon, SHOW_ALL); allFunctionsActionState.setHelpLocation( new HelpLocation("VersionTrackingPlugin", "Show_All_Functions")); - Icon unmatchedIcon = ResourceManager.loadImage("images/filter_matched.png"); + Icon unmatchedIcon = new GIcon("icon.version.tracking.function.filter.unmatched"); ActionState unmatchedOnlyActionState = new ActionState<>("Show Only Unmatched Functions", unmatchedIcon, SHOW_UNMATCHED); unmatchedOnlyActionState.setHelpLocation( @@ -358,7 +360,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter JPanel statusPanel = new JPanel(new BorderLayout()); statusLabel = new GDLabel(NO_ERROR_MESSAGE); statusLabel.setHorizontalAlignment(SwingConstants.CENTER); - statusLabel.setForeground(Color.RED.darker()); + statusLabel.setForeground(FG_ERROR); statusLabel.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java index a2c0625018..51ee6a9699 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java @@ -30,6 +30,7 @@ import docking.action.*; import docking.widgets.table.GTable; import docking.widgets.table.RowObjectTableModel; import docking.widgets.table.threaded.GThreadedTablePanel; +import generic.theme.GIcon; import ghidra.feature.vt.api.db.DeletedMatch; import ghidra.feature.vt.api.impl.VTChangeManager; import ghidra.feature.vt.api.impl.VersionTrackingChangeRecord; @@ -47,7 +48,6 @@ import ghidra.util.HelpLocation; import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.GhidraThreadedTablePanel; import resources.Icons; -import resources.ResourceManager; public class VTImpliedMatchesTableProvider extends ComponentProviderAdapter implements VTControllerListener { @@ -70,7 +70,7 @@ public class VTImpliedMatchesTableProvider extends ComponentProviderAdapter this.controller = controller; controller.addListener(this); setWindowGroup(VTPlugin.WINDOW_GROUP); - setIcon(ResourceManager.loadImage("images/application_view_detail.png")); + setIcon(new GIcon("icon.version.tracking.provider.implied.match")); setDefaultWindowPosition(WindowPosition.BOTTOM); setIntraGroupPosition(WindowPosition.STACK); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java index 6f310bb115..64dbd4909d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java @@ -100,7 +100,7 @@ public class MarkupItemStatusRenderer extends AbstractGhidraColumnRenderer > allFilters = new ArrayList<>(); private final VTController controller; @@ -336,7 +344,7 @@ public class VTMarkupItemsTableModel extends AddressBasedTableModel { - private static ImageIcon DISABLED_ICON = - ResourceManager.getDisabledIcon(ResourceManager.loadImage("images/ledgreen.png"), 50); - private static final ImageIcon APPLIED_BASE_ICON = - ResourceManager.loadImage("images/ledgreen.png", 8, 8); - private static final ImageIcon REJECTED_BASE_ICON = - ResourceManager.loadImage("images/ledpurple.png", 8, 8); - private static final ImageIcon NOT_APPLIED_BASE_ICON = - ResourceManager.loadImage("images/ledorange.png", 8, 8); - private static final ImageIcon IGNORED_BASE_ICON = - ResourceManager.loadImage("images/ledblue.png", 8, 8); - private static final ImageIcon ERROR_BASE_ICON = - ResourceManager.loadImage("images/ledred.png", 8, 8); + private static final Color FG_TOOLTIP_DEFAULT = new GColor("color.fg.version.tracking.tooltip"); + private static final Color FG_TOOLTIP_UNEXAMINED = + new GColor("color.bg.version.tracking.match.table.markup.status.tooltip.unexamined"); - private static Icon NOT_APPLIED_ICON = new TranslateIcon(NOT_APPLIED_BASE_ICON, 0, 4); - private static Icon APPLIED_ICON = new TranslateIcon(APPLIED_BASE_ICON, 9, 4); - private static Icon REJECTED_ICON = new TranslateIcon(REJECTED_BASE_ICON, 18, 4); - private static Icon IGNORED_ICON = new TranslateIcon(IGNORED_BASE_ICON, 27, 4); - private static Icon ERROR_ICON = new TranslateIcon(ERROR_BASE_ICON, 36, 4); + private static Icon EMPTY_ICON = new GIcon("icon.empty"); + private static Icon DISABLED_ICOL = + new GIcon("icon.version.tracking.match.table.markup.status.disabled"); + private static final Icon NOT_APPLIED_ICON = + new GIcon("icon.version.tracking.match.table.markup.status.not.applied"); + private static final Icon APPLIED_ICON = + new GIcon("icon.version.tracking.match.table.markup.status.applied"); + private static final Icon REJECTED_ICON = + new GIcon("icon.version.tracking.match.table.markup.status.rejected"); + private static final Icon IGNORED_ICON = + new GIcon("icon.version.tracking.match.table.markup.status.ignored"); + private static final Icon ERROR_ICON = + new GIcon("icon.version.tracking.match.table.markup.status.error"); - private static Icon DISABLED_NOT_APPLIED_ICON = new TranslateIcon(DISABLED_ICON, 0, 4); - private static Icon DISABLED_APPLIED_ICON = new TranslateIcon(DISABLED_ICON, 9, 4); - private static Icon DISABLED_REJECTED_ICON = new TranslateIcon(DISABLED_ICON, 18, 4); - private static Icon DISABLED_IGNORED_ICON = new TranslateIcon(DISABLED_ICON, 27, 4); - private static Icon DISABLED_ERROR_ICON = new TranslateIcon(DISABLED_ICON, 36, 4); + private static Icon DISABLED_NOT_APPLIED_ICON = new TranslateIcon(DISABLED_ICOL, 0, 4); + private static Icon DISABLED_APPLIED_ICON = new TranslateIcon(DISABLED_ICOL, 9, 4); + private static Icon DISABLED_REJECTED_ICON = new TranslateIcon(DISABLED_ICOL, 18, 4); + private static Icon DISABLED_IGNORED_ICON = new TranslateIcon(DISABLED_ICOL, 27, 4); + private static Icon DISABLED_ERROR_ICON = new TranslateIcon(DISABLED_ICOL, 36, 4); @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { @@ -81,7 +83,7 @@ public class MatchMarkupStatusRenderer extends AbstractGhidraColumnRenderer "); - if (!status.isInitialized()) { buf.append("Match has not been accepted; unknown markup status"); return buf.toString(); } - ImageIcon icon = DISABLED_ICON; + Icon icon = EMPTY_ICON; String message = "Has one or more \"Unexamined\" markup items"; - String fontColor = "gray"; + Color color = FG_TOOLTIP_DEFAULT; if (status.hasUnexaminedMarkup()) { - icon = NOT_APPLIED_BASE_ICON; - fontColor = "black"; + icon = NOT_APPLIED_ICON; + color = FG_TOOLTIP_UNEXAMINED; } - buf.append(" "); + + String fontColor = WebColors.toString(color, false); + buf.append("
"); buf.append(""); buf.append(message).append("
"); - icon = DISABLED_ICON; + icon = EMPTY_ICON; + message = "Has one or more \"Applied\" markup items"; fontColor = "gray"; if (status.hasAppliedMarkup()) { - icon = APPLIED_BASE_ICON; + icon = APPLIED_ICON; fontColor = "black"; } - buf.append(""); + buf.append("
"); buf.append(""); buf.append(message).append("
"); - icon = DISABLED_ICON; + icon = EMPTY_ICON; + message = "Has one or more \"Rejected\" markup items to apply"; fontColor = "gray"; if (status.hasRejectedMarkup()) { - icon = REJECTED_BASE_ICON; + icon = REJECTED_ICON; fontColor = "black"; } - buf.append(""); + buf.append("
"); buf.append(""); buf.append(message).append("
"); - icon = DISABLED_ICON; + icon = EMPTY_ICON; message = "Has one or more \"Ignored (Don't Know or Don't Care)\" markup items"; fontColor = "gray"; if (status.hasDontCareMarkup() || status.hasDontKnowMarkup()) { - icon = IGNORED_BASE_ICON; + icon = IGNORED_ICON; fontColor = "black"; } - buf.append(""); + buf.append("
"); buf.append(""); buf.append(message).append("
"); - icon = DISABLED_ICON; + icon = EMPTY_ICON; message = "Has one or more \"Error\" markup items"; fontColor = "gray"; if (status.hasErrors()) { - icon = ERROR_BASE_ICON; + icon = ERROR_ICON; fontColor = "black"; } - buf.append(""); + buf.append("
"); buf.append(""); buf.append(message).append("
"); return buf.toString(); } + private String getIconSource(Icon icon) { + if (icon instanceof GIcon gIcon) { + URL url = gIcon.getUrl(); + if (url != null) { + return url.toString(); + } + } + else if (icon instanceof UrlImageIcon urlIcon) { + return urlIcon.getUrl().toString(); + } + return ""; + } + @Override public String getFilterString(VTMatch t, Settings settings) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MatchTableRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MatchTableRenderer.java index 88ba481fd4..9f12a5edd3 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MatchTableRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MatchTableRenderer.java @@ -21,11 +21,13 @@ import java.awt.Component; import javax.swing.JTable; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GColor; import ghidra.feature.vt.api.main.*; import ghidra.util.table.CompositeGhidraTableCellRenderer; public class MatchTableRenderer extends CompositeGhidraTableCellRenderer { - private static final Color LOCKED_OUT_BACKGROUND_COLOR = new Color(239, 239, 239); + private static final Color LOCKED_OUT_BACKGROUND_COLOR = + new GColor("color.bg.version.tracking.match.table.locked.out"); @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java index fc1591b538..b4f081cc56 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java @@ -20,12 +20,12 @@ import java.awt.Component; import javax.swing.*; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GIcon; import ghidra.docking.settings.Settings; import ghidra.program.model.symbol.Symbol; import ghidra.util.HTMLUtilities; import ghidra.util.exception.AssertException; import ghidra.util.table.column.AbstractGhidraColumnRenderer; -import resources.ResourceManager; /** * This class provides a field renderer for version tracking tables. It is used for indicating @@ -60,7 +60,7 @@ public class MultipleLabelsRenderer extends AbstractGhidraColumnRenderergetColors(VTAssociationMarkupStatus status) { - Color ORANGE = new Color(255, 150, 0); - Color GREEN = new Color(0, 180, 0); - Color BLUE = new Color(80, 80, 240); - List list = new ArrayList (4); - if (status.hasRejectedMarkup()) { - list.add(Color.RED); + private List getColors(VTAssociationMarkupStatus markupStatus) { + + List list = new ArrayList<>(4); + if (markupStatus.hasRejectedMarkup()) { + list.add(BG_REJECTED); } - if (status.hasAppliedMarkup() || status.isFullyApplied()) { - list.add(GREEN); + if (markupStatus.hasAppliedMarkup() || markupStatus.isFullyApplied()) { + list.add(BG_APPLIED); } - if (status.hasDontCareMarkup()) { - list.add(BLUE); + if (markupStatus.hasDontCareMarkup()) { + list.add(BG_DONT_CARE); } - if (status.hasDontKnowMarkup()) { - list.add(ORANGE); + if (markupStatus.hasDontKnowMarkup()) { + list.add(BG_DONT_KNOW); } return list; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchApplySettingsAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchApplySettingsAction.java index 915725cb74..bcd861449f 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchApplySettingsAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchApplySettingsAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +15,22 @@ */ package ghidra.feature.vt.gui.provider.matchtable; +import javax.swing.Icon; + +import docking.ActionContext; +import docking.action.*; +import generic.theme.GIcon; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.OptionsService; import ghidra.util.HelpLocation; -import javax.swing.Icon; - -import resources.ResourceManager; -import docking.ActionContext; -import docking.action.*; - public class VTMatchApplySettingsAction extends DockingAction { public static final String VERSION_TRACKING_OPTIONS_NAME = "Version Tracking"; public static final String VERSION_TRACKING_APPLY_MARKUP_OPTIONS = "Apply Markup Options"; - static final Icon ICON = ResourceManager.loadImage("images/settings16.gif"); + static final Icon ICON = new GIcon("icon.version.tracking.action.show.settings"); private static final String MENU_GROUP = VTPlugin.VT_SETTINGS_MENU_GROUP; private static final String TITLE = "Version Tracking Options"; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java index 754c333c5e..b68fa810dc 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java @@ -30,6 +30,8 @@ import docking.widgets.label.GDLabel; import docking.widgets.table.GTable; import docking.widgets.table.RowObjectTableModel; import docking.widgets.table.threaded.ThreadedTableModel; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.feature.vt.api.impl.VTChangeManager; import ghidra.feature.vt.api.main.*; import ghidra.feature.vt.gui.actions.*; @@ -54,7 +56,6 @@ import ghidra.util.SystemUtilities; import ghidra.util.layout.HorizontalLayout; import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraThreadedTablePanel; -import resources.ResourceManager; /** * The docking window that provides a table of the other tool's function matches for the function @@ -64,9 +65,10 @@ public abstract class VTMatchOneToManyTableProvider extends ComponentProviderAda implements FilterDialogModel , VTControllerListener, VTSubToolManagerListener { private static final String TITLE_PREFIX = "Version Tracking Matches for "; - private static final Icon ICON = ResourceManager.loadImage("images/text_list_bullets.png"); + private static final Icon ICON = new GIcon("icon.version.tracking.provider.one.to.many"); - protected static final Color LOCAL_INFO_FOREGROUND_COLOR = new Color(0, 128, 0); + protected static final Color LOCAL_INFO_FOREGROUND_COLOR = + new GColor("color.fg.version.tracking.function.match.local.info"); private JComponent component; private MatchThreadedTablePanel tablePanel; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java index 458569aab5..927d2a5cdd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java @@ -23,23 +23,32 @@ import javax.swing.*; import docking.widgets.label.GIconLabel; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GColor; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTAssociationStatus; import ghidra.util.table.GhidraTableCellRenderer; -import resources.ResourceManager; public class RelatedMatchRenderer extends GhidraTableCellRenderer { + + private static final Color GOOD = + new GColor("color.bg.version.tracking.related.matches.table.good"); + private static final Color MEDIUM = + new GColor("color.bg.version.tracking.related.matches.table.medium"); + private static final Color BAD = + new GColor("color.bg.version.tracking.related.matches.table.bad"); + static Map sourceMap; static Map destinationMap; static Map statusMap; - static final Icon TARGET_ICON = ResourceManager.loadImage("images/user-online.png"); - static final Icon CALLER_ICON = ResourceManager.loadImage("images/go-down.png"); - static final Icon CALLEE_ICON = ResourceManager.loadImage("images/go-next.png"); - static final Icon UNRELATED_ICON = ResourceManager.loadImage("images/user-busy.png"); + static final Icon TARGET_ICON = new GIcon("icon.version.tracking.related.match.target"); + static final Icon CALLER_ICON = new GIcon("icon.version.tracking.related.match.caller"); + static final Icon CALLEE_ICON = new GIcon("icon.version.tracking.related.match.callee"); + static final Icon UNRELATED_ICON = new GIcon("icon.version.tracking.related.match.unrelated"); - static final Icon ACCEPTED_ICON = ResourceManager.loadImage("images/accept.png"); - static final Icon AVAILABLE_ICON = ResourceManager.loadImage("images/media-playback-stop.png"); - static final Icon LOCKED_OUT_ICON = ResourceManager.loadImage("images/edit-delete.png"); + static final Icon ACCEPTED_ICON = new GIcon("icon.version.tracking.related.match.accepted"); + static final Icon AVAILABLE_ICON = new GIcon("icon.version.tracking.related.match.available"); + static final Icon LOCKED_OUT_ICON = new GIcon("icon.version.tracking.related.match.locked.out"); private JPanel relatedMatchColumnComponent; private GridLayout layout; @@ -99,10 +108,6 @@ public class RelatedMatchRenderer extends GhidraTableCellRenderer { return renderer; } - private static final Color GOOD = Color.green; - private static final Color MEDIUM = Color.yellow; - private static final Color BAD = Color.red; - private Color findBackgroundColor(VTRelatedMatchType value) { double goodness = value.getGoodness() / 100.0; double badness = 1.0 - goodness; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java index 9b2c024417..4e8a90ea51 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java @@ -29,17 +29,17 @@ import docking.ActionContext; import docking.widgets.table.GTable; import docking.widgets.table.RowObjectTableModel; import docking.widgets.table.threaded.ThreadedTableModel; +import generic.theme.GIcon; import ghidra.feature.vt.api.util.VTRelatedMatch; import ghidra.feature.vt.gui.plugin.VTController; import ghidra.feature.vt.gui.plugin.VTPlugin; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.PluginTool; import ghidra.util.table.*; -import resources.ResourceManager; public class VTRelatedMatchesTableProvider extends ComponentProviderAdapter { - private static final Icon ICON = ResourceManager.loadImage("images/user-online.png"); + private static final Icon ICON = new GIcon("icon.version.tracking.provider.related.matches"); private JComponent component; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/AbstractVTMatchTableModel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/AbstractVTMatchTableModel.java index adb8b489a7..ee43ba8ad0 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/AbstractVTMatchTableModel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/AbstractVTMatchTableModel.java @@ -27,6 +27,7 @@ import javax.swing.JLabel; import docking.widgets.table.GTableCellRenderingData; import docking.widgets.table.TableFilter; +import generic.theme.GColor; import ghidra.app.util.SymbolInspector; import ghidra.docking.settings.Settings; import ghidra.feature.vt.api.impl.VTProgramCorrelatorInfo; @@ -56,6 +57,8 @@ public abstract class AbstractVTMatchTableModel extends AddressBasedTableModel markupStatusColumnComparator = new MarkupStatusColumnComparator(); protected VTSession session; + private static final Color FG_ERROR = new GColor("color.fg.version.tracking.match.table.error"); + private Set > allFilters = new HashSet<>(); protected final VTController controller; @@ -589,7 +592,7 @@ public abstract class AbstractVTMatchTableModel extends AddressBasedTableModel extends Timer implements ActionListener { - private static final Icon EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif"); + private static final Icon EMPTY_ICON = new GIcon("icon.version.tracking.empty"); private static final long MINIMUM_TIME_BETWEEN_FLASHES = 20000; private static final int MAX_FLASH_COUNT = 10; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java index 9ec0dbf8a9..756e2acb14 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java @@ -21,32 +21,23 @@ import javax.swing.Icon; import javax.swing.JLabel; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GIcon; import ghidra.util.table.GhidraTableCellRenderer; -import resources.MultiIcon; -import resources.ResourceManager; -import resources.icons.TranslateIcon; public class MatchStatusRenderer extends GhidraTableCellRenderer { -// private static final Icon DISABLED_APPLIED_ICON = -// ResourceManager.getDisabledIcon(ResourceManager.loadImage("images/flag.png")); - private static final Icon ACCEPTED_ICON = ResourceManager.loadImage("images/flag.png"); - private static final Icon REJECTED_ICON = ResourceManager.loadImage("images/dialog-cancel.png"); -// private static final Icon REJECTED_ICON = ResourceManager.loadImage("images/delete.png"); - private static final Icon BLOCKED_ICON = ResourceManager.loadImage("images/kgpg.png"); - -// private static final ImageIcon LOCK_ICON = -// ResourceManager.loadImage("images/lock.png"); - - private static final Icon WARN_ICON = new TranslateIcon( - ResourceManager.loadImage("images/bullet_error.png"), 10, 8); - private static final Icon FAILURE_ICON = new TranslateIcon(ResourceManager.getScaledIcon( - ResourceManager.loadImage("images/edit-delete.png"), 8, 8), 10, 8); - private static final Icon FULLY_APPLIED_ICON = new TranslateIcon(ResourceManager.getScaledIcon( - ResourceManager.loadImage("images/checkmark_green.gif"), 8, 8), 10, 8); - private static final Icon FULLY_CONSIDERED_ICON = new TranslateIcon( - ResourceManager.getScaledIcon(ResourceManager.loadImage("images/checkmark_yellow.gif"), 8, - 8), 10, 8); + private static final Icon ACCEPTED_SOME_UNEXAMINED_ICON = + new GIcon("icon.version.tracking.match.table.status.accepted.some.unexamined"); + private static final Icon ACCEPTED_ERROR_ICON = + new GIcon("icon.version.tracking.match.table.status.accepted.error"); + private static final Icon ACCEPTED_FULLY_APPLIED_ICON = + new GIcon("icon.version.tracking.match.table.status.accepted.fully.applied"); + private static final Icon ACCEPTED_FULLY_CONSIDERED_ICON = + new GIcon("icon.version.tracking.match.table.status.accepted.fully.considered"); + private static final Icon REJECTED_ICON = + new GIcon("icon.version.tracking.match.table.status.rejected"); + private static final Icon BLOCKED_ICON = + new GIcon("icon.version.tracking.match.table.status.blocked"); @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { @@ -74,16 +65,16 @@ public class MatchStatusRenderer extends GhidraTableCellRenderer { Icon icon = null; switch (status) { case ACCEPTED_FULLY_APPLIED: - icon = new MultiIcon(ACCEPTED_ICON, FULLY_APPLIED_ICON); + icon = ACCEPTED_FULLY_APPLIED_ICON; break; case ACCEPTED_HAS_ERRORS: - icon = new MultiIcon(ACCEPTED_ICON, FAILURE_ICON); + icon = ACCEPTED_ERROR_ICON; break; case ACCEPTED_NO_UNEXAMINED: - icon = new MultiIcon(ACCEPTED_ICON, FULLY_CONSIDERED_ICON); + icon = ACCEPTED_FULLY_CONSIDERED_ICON; break; case ACCEPTED_SOME_UNEXAMINED: - icon = new MultiIcon(ACCEPTED_ICON, WARN_ICON); + icon = ACCEPTED_SOME_UNEXAMINED_ICON; break; case AVAILABLE: // no icon diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/VTSymbolRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/VTSymbolRenderer.java index 0ee30ef127..44627b8f85 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/VTSymbolRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/VTSymbolRenderer.java @@ -21,6 +21,7 @@ import java.awt.Component; import javax.swing.JComponent; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.util.SymbolInspector; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.symbol.Symbol; @@ -49,7 +50,7 @@ public class VTSymbolRenderer extends GhidraTableCellRenderer { private void handleSymbol(Object value, boolean isSelected) { setBold(); if (!isSelected) { - Color color = Color.BLACK; + Color color = Colors.FOREGROUND; if (value instanceof Symbol) { Symbol s = (Symbol) value; inspector.setProgram(s.getProgram()); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java index 38dc9bdc3e..16a79b9ab4 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java @@ -27,12 +27,12 @@ import javax.swing.event.*; import docking.widgets.button.GRadioButton; import docking.widgets.label.GLabel; import docking.widgets.list.GList; +import generic.theme.GIcon; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.util.layout.MiddleLayout; import ghidra.util.layout.VerticalLayout; -import resources.ResourceManager; public class ChooseAddressSetEditorPanel extends JPanel { @@ -40,8 +40,8 @@ public class ChooseAddressSetEditorPanel extends JPanel { ENTIRE_PROGRAM, SELECTION, MANUALLY_DEFINED } - private static Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png"); - private static Icon SUBTRACT_ICON = ResourceManager.loadImage("images/list-remove.png"); + private static Icon ADD_ICON = new GIcon("icon.version.tracking.add"); + private static Icon SUBTRACT_ICON = new GIcon("icon.version.tracking.subtract"); private PluginTool tool; private final String name; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java index eb6bb77534..a0b69e6f8c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java @@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils; import docking.options.editor.ButtonPanelFactory; import docking.widgets.label.GDLabel; import docking.wizard.*; +import generic.theme.*; import ghidra.app.util.task.OpenProgramTask; import ghidra.framework.main.DataTreeDialog; import ghidra.framework.model.DomainFile; @@ -36,7 +37,6 @@ import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; import ghidra.util.InvalidNameException; import ghidra.util.task.TaskLauncher; -import resources.ResourceManager; /** * Version tracking wizard panel to create a new session. @@ -44,8 +44,8 @@ import resources.ResourceManager; public class NewSessionPanel extends AbstractMageJPanel { private static final int MAX_LENGTH_FOR_VT_SESSION_NAME = 20; - private static final Icon SWAP_ICON = ResourceManager.loadImage("images/doubleArrowUpDown.png"); - private static final Icon INFO_ICON = ResourceManager.loadImage("images/information.png"); + private static final Icon SWAP_ICON = new GIcon("icon.version.tracking.new.session.swap"); + private static final Icon INFO_ICON = new GIcon("icon.version.tracking.new.session.info"); private JTextField sourceField; private JTextField destinationField; @@ -73,14 +73,12 @@ public class NewSessionPanel extends AbstractMageJPanel { folderLabel.setHorizontalAlignment(SwingConstants.RIGHT); folderLabel.setToolTipText("The folder to store the new Version Tracking Session"); folderNameField = new JTextField(); - folderNameField.setFont(new Font("Monospaced", Font.PLAIN, 12)); + Gui.registerFont(folderNameField, GThemeDefaults.Ids.Fonts.MONOSPACED); folderNameField.setEditable(false); // force user to browse to choose JButton browseFolderButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE); browseFolderButton.addActionListener(e -> browseDataTreeFolders()); - Font font = browseFolderButton.getFont(); - browseFolderButton.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); JLabel newSessionLabel = new GDLabel("New Session Name: "); newSessionLabel.setToolTipText("The name for the new Version Tracking Session"); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java index 573e22167d..a964855841 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java @@ -20,11 +20,11 @@ import java.util.*; import javax.swing.Icon; import docking.widgets.table.AbstractGTableModel; +import generic.theme.GIcon; import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory; import ghidra.feature.vt.api.util.VTAbstractProgramCorrelatorFactory; import ghidra.util.classfinder.ClassSearcher; import ghidra.util.exception.AssertException; -import resources.ResourceManager; public class VTProgramTableCorrelatorModel extends AbstractGTableModel { @@ -40,7 +40,8 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel list; private Set previouslyRunCorrelators; diff --git a/Ghidra/Framework/Docking/Module.manifest b/Ghidra/Framework/Docking/Module.manifest index e69de29bb2..139597f9cb 100644 --- a/Ghidra/Framework/Docking/Module.manifest +++ b/Ghidra/Framework/Docking/Module.manifest @@ -0,0 +1,2 @@ + + diff --git a/Ghidra/Framework/Docking/build.gradle b/Ghidra/Framework/Docking/build.gradle index 139ec36c1f..4cc5963654 100644 --- a/Ghidra/Framework/Docking/build.gradle +++ b/Ghidra/Framework/Docking/build.gradle @@ -26,7 +26,6 @@ eclipse.project.name = 'Framework Docking' dependencies { api project(':Generic') api project(':Help') - // include code from src/test in Generic testImplementation project(path: ':Generic', configuration: 'testArtifacts') diff --git a/Ghidra/Framework/Docking/certification.manifest b/Ghidra/Framework/Docking/certification.manifest index 0c37be739f..bec96bb78a 100644 --- a/Ghidra/Framework/Docking/certification.manifest +++ b/Ghidra/Framework/Docking/certification.manifest @@ -9,25 +9,23 @@ ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| +data/docking.palette.theme.properties||GHIDRA||||END| +data/docking.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| -src/main/help/help/shared/arrow.gif||GHIDRA||||END| -src/main/help/help/shared/close16.gif||GHIDRA||||END| -src/main/help/help/shared/menu16.gif||GHIDRA||||END| -src/main/help/help/shared/note-red.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/note.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/note.yellow.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/redo.png||GHIDRA||||END| -src/main/help/help/shared/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/undo.png||GHIDRA||||END| -src/main/help/help/shared/warning.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/topics/PlacheholderTopic/Placeholder.htm||GHIDRA||||END| +src/main/help/help/topics/Misc/Welcome_to_Help.htm||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingDeveloperDocs.html||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingInternals.html||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingOverview.html||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingUserDocs.html||GHIDRA||||END| +src/main/help/help/topics/Theming/images/ColorEditor.png||GHIDRA||||END| +src/main/help/help/topics/Theming/images/FontEditor.png||GHIDRA||||END| +src/main/help/help/topics/Theming/images/IconEditor.png||GHIDRA||||END| +src/main/help/help/topics/Theming/images/ThemeDialog.png||GHIDRA||||END| src/main/java/docking/dnd/package.html||GHIDRA||reviewed||END| src/main/java/docking/options/editor/package.html||GHIDRA||reviewed||END| src/main/java/docking/widgets/fieldpanel/package.html||GHIDRA||reviewed||END| src/main/java/docking/widgets/filechooser/package.html||GHIDRA||reviewed||END| src/main/java/docking/wizard/package.html||GHIDRA||reviewed||END| -src/main/resources/images/EmptyIcon.gif||GHIDRA||reviewed||END| -src/main/resources/images/EmptyIcon16.gif||GHIDRA||reviewed||END| src/main/resources/images/Plus.png||GHIDRA||reviewed||END| src/main/resources/images/StackFrameElement.png||GHIDRA||reviewed||END| src/main/resources/images/StackFrame_Red.png||GHIDRA||reviewed||END| @@ -36,16 +34,16 @@ src/main/resources/images/application-vnd.oasis.opendocument.spreadsheet-templat src/main/resources/images/application_xp.png||FAMFAMFAM Icons - CC 2.5|||fam fam|END| src/main/resources/images/arrow.gif||GHIDRA||||END| src/main/resources/images/bullet_delete.png||FAMFAMFAM Icons - CC 2.5||||END| +src/main/resources/images/check.png||GHIDRA||||END| src/main/resources/images/checkmark_green.gif||GHIDRA||reviewed||END| src/main/resources/images/close16.gif||GHIDRA||reviewed||END| src/main/resources/images/closedFolder.png||Modified Nuvola Icons - LGPL 2.1||||END| +src/main/resources/images/collapse.gif||GHIDRA||||END| src/main/resources/images/computer.png||Tango Icons - Public Domain|||tango|END| src/main/resources/images/desktop.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| -src/main/resources/images/dialog-cancel.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/dialog-warning.png||Oxygen Icons - LGPL 3.0||||END| -src/main/resources/images/disk.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/document-properties.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/down.png||GHIDRA||reviewed||END| +src/main/resources/images/drive.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/eatbits.gif||GHIDRA||reviewed||END| src/main/resources/images/eatbits1.png||GHIDRA||reviewed||END| src/main/resources/images/eatbits2.png||GHIDRA||reviewed||END| @@ -55,9 +53,9 @@ src/main/resources/images/eatbits5.png||GHIDRA||reviewed||END| src/main/resources/images/eatbits6.png||GHIDRA||reviewed||END| src/main/resources/images/eatbits7.png||GHIDRA||reviewed||END| src/main/resources/images/edit-clear.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/edit-cut22.png||Tango Icons - Public Domain|||original name edit-cut.png in tango 22x22|END| src/main/resources/images/edit-delete.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/edit-undo.png||Tango Icons - Public Domain|||tango icon set|END| +src/main/resources/images/expand.gif||GHIDRA||||END| src/main/resources/images/filter_off.png||GHIDRA||||END| src/main/resources/images/filter_on.png||GHIDRA||||END| src/main/resources/images/folder-open.png||Tango Icons - Public Domain||||END| @@ -77,11 +75,11 @@ src/main/resources/images/hourglass24_11.png||GHIDRA||reviewed||END| src/main/resources/images/image-missing.png||Oxygen Icons - LGPL 3.0||||END| src/main/resources/images/info_small.png||GHIDRA||||END| src/main/resources/images/info_small_hover.png||GHIDRA||||END| -src/main/resources/images/information.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/inode-directory.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/left.alternate.png||GHIDRA||||END| -src/main/resources/images/left.png||GHIDRA||reviewed||END| +src/main/resources/images/list-remove.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/magnifier.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/mail-folder-outbox.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| +src/main/resources/images/mail-receive.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/media-playback-start.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/menu16.gif||GHIDRA||reviewed||END| src/main/resources/images/note-red.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| @@ -92,24 +90,20 @@ src/main/resources/images/page_code.png||FAMFAMFAM Icons - CC 2.5||||END| src/main/resources/images/page_excel.png||FAMFAMFAM Icons - CC 2.5||||END| src/main/resources/images/page_go.png||FAMFAMFAM Icons - CC 2.5||||END| src/main/resources/images/page_green.png||FAMFAMFAM Icons - CC 2.5||||END| +src/main/resources/images/play.png||GHIDRA||||END| src/main/resources/images/preferences-system-windows.png||Tango Icons - Public Domain||||END| -src/main/resources/images/redo.png||GHIDRA||||END| -src/main/resources/images/reload.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| -src/main/resources/images/right.alternate.png||GHIDRA||||END| -src/main/resources/images/right.png||GHIDRA||reviewed||END| +src/main/resources/images/redo.png||Crystal Clear Icons - LGPL 2.1||||END| src/main/resources/images/software-update-available.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/sortascending.png||GHIDRA||reviewed||END| -src/main/resources/images/sortdescending.png||GHIDRA||reviewed||END| src/main/resources/images/table.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/tag.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/text_lowercase.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/textfield_rename.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/trash-empty.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/undo.png||GHIDRA||||END| -src/main/resources/images/up.png||GHIDRA||reviewed||END| +src/main/resources/images/undo.png||Crystal Clear Icons - LGPL 2.1||||END| src/main/resources/images/user-home.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/warning.help.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/warning.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/weather-clear.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/weather-few-clouds-reverse.png||Tango Icons - Public Domain||||END| src/main/resources/images/weather-few-clouds.png||Tango Icons - Public Domain|||tango icon set|END| @@ -120,6 +114,9 @@ src/main/resources/images/www_128.png||Nuvola Icons - LGPL 2.1|||nuvola www.png| src/main/resources/images/www_16.png||Nuvola Icons - LGPL 2.1|||nuvola www 16x16|END| src/main/resources/images/www_32.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| src/main/resources/images/www_64.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| +src/main/resources/images/zoom.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/zoom_in.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/zoom_out.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/svg/images/StackFrameElement.svg||GHIDRA||reviewed||END| src/main/svg/images/StackFrame_Red.svg||GHIDRA||reviewed||END| src/main/svg/images/cause.svg||GHIDRA||reviewed||END| diff --git a/Ghidra/Framework/Docking/data/ExtensionPoint.manifest b/Ghidra/Framework/Docking/data/ExtensionPoint.manifest index a7001f5a80..a6370472eb 100644 --- a/Ghidra/Framework/Docking/data/ExtensionPoint.manifest +++ b/Ghidra/Framework/Docking/data/ExtensionPoint.manifest @@ -1,3 +1,4 @@ ColumnConstraintProvider TypeMapper TableColumn +Theme diff --git a/Ghidra/Framework/Docking/data/docking.palette.theme.properties b/Ghidra/Framework/Docking/data/docking.palette.theme.properties new file mode 100644 index 0000000000..06fa3048d3 --- /dev/null +++ b/Ghidra/Framework/Docking/data/docking.palette.theme.properties @@ -0,0 +1,84 @@ +[Defaults] + +color.palette.nocolor = rgba(255,255,255,0) +color.palette.disabled = rgba(255,255,255,0) + +color.palette.black = black +color.palette.blue = blue +color.palate.cornflowerblue = cornflowerblue +color.palate.cornsilk = cornsilk +color.palette.crimson = crimson +color.palette.cyan = cyan +color.palette.darkblue = DarkBlue +color.palette.darkgray = DarkGray +color.palette.darkgreen = darkgreen +color.palette.darkkhaki = DarkKhaki +color.palette.darkred = DarkRed +color.palette.darkslategray = darkslategray +color.palette.dodgerblue = DodgerBlue +color.palette.fuchsia = fuchsia +color.palette.gold = gold +color.palette.gray = gray +color.palette.green = green +color.palette.greenyellow = greenyellow +color.palette.indigo = indigo +color.palette.khaki = khaki +color.palette.lavender = lavender +color.palette.lime = lime +color.palette.lightcoral = lightcoral +color.palette.lightgray = rgb(192, 192, 192) +color.palette.lightgreen = rgb(127, 255, 127) +color.palette.lightpink = lightpink +color.palette.lightred = rgb(255, 127, 127) +color.palette.lightskyblue = lightskyblue +color.palette.lightsteelblue = lightsteelblue +color.palette.magenta = magenta +color.palette.maroon = maroon +color.palette.mistyrose = mistyrose +color.palette.navy = navy +color.palette.olive = olive +color.palette.orange = orange +color.palette.palegreen = palegreen +color.palette.palevioletred = PaleVioletRed +color.palette.peachpuff = peachpuff +color.palette.pink = pink +color.palette.purple = purple +color.palette.red = red +color.palette.silver = silver +color.palette.steelblue = steelblue +color.palette.tan = tan +color.palette.teal = teal +color.palette.yellow = yellow +color.palette.yellowgreen = yellowgreen +color.palette.white = white + + + +[Dark Defaults] + +color.palette.black = lightgray + +color.palette.blue = #80a0c0 +color.palette.indigo = #c070c0 +color.palette.green = #70c070 +color.palette.darkgreen = #70a070 +color.palette.magenta = #ff80ff +color.palette.pink = #ff80a0 +color.palette.cyan = #80c0c0 +color.palette.darkcyan = #406060 +color.palette.red = #ff8080 +color.palette.teal = #80c0c0 +color.palette.purple = #c080c0 +color.palette.yellow = #ffff80 +color.palette.olive = #c0c080 +color.palette.orange = #ffa070 +color.palette.violetred = #ff7090 + +color.palette.bg.yellow = #404028 +color.palette.bg.yellowgreen = #344028 +color.palette.bg.green = #284028 +color.palette.bg.bluegrey = #282838 + +color.palette.bg.blindingyellow = #ffff00 +color.palette.bg.blindinggreen = #00ff00 +color.palette.bg.blindingorange = #ff8000 diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties new file mode 100644 index 0000000000..e35755127a --- /dev/null +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -0,0 +1,251 @@ +[Defaults] + +color.bg = white // note: this is the text/widget bg color +color.fg = black +color.fg.error = red +color.bg.error = lightcoral +color.fg.disabled = lightGray +color.bg.uneditable = system.color.bg.application // TODO see if there exists an LaF setting for this +color.bg.filtered = yellow +color.fg.hint = gray + +color.fg.messages.hint = color.fg.hint +color.fg.messages.alert = orange +color.fg.messages.error = color.fg.error +color.fg.messages.normal = blue +color.fg.messages.warning = orange + + +color.bg.help.hint = rgba(100, 100, 255, 100) +color.fg.help.selector.h1 = #000080 +color.fg.help.selector.h2 = #984C4C +color.fg.help.selector.h3 = #0000FF +color.fg.help.selector.p.provided.by.plugin = #7F7F7F +color.fg.help.selector.p.related.topic = #800080 +color.fg.help.selector.th = #EDF3FE +color.fg.help.selector.code = black +color.fg.help.selector.code.path = #4682B4 + +color.bg.splashscreen = black + +color.bg.header.active = mintcream +color.bg.header.inactive = rgb(150, 150, 150) +color.fg.header.active = black +color.fg.header.inactive = black +color.header.drag.cursor = black + +color.fg.dialog.status.alert = color.fg.messages.alert +color.fg.dialog.status.error = color.fg.messages.error +color.fg.dialog.status.normal = color.fg.messages.normal +color.fg.dialog.status.warning = color.fg.messages.warning + +color.bg.selection = rgb(180, 255, 180) // pale green +color.bg.highlight = rgb(255,255,150) // pale yellow +color.bg.tooltip = rgb(255, 255, 230) + +color.bg.currentline = rgb(232,242,254) +color.cursor.focused = red +color.cursor.unfocused = pink + +color.bg.table.grid = gray +color.bg.table.row.drag = color.palette.lavender +color.bg.table.row = color.bg +color.bg.table.row.alt = rgb(237,243,254) +color.fg.table.uneditable.selected = yellow +color.fg.table.uneditable.unselected = lightgray +color.fg.table = color.fg +color.fg.table.unselected = white +color.fg.error.table.unselected = color.fg.error +color.fg.error.table.selected = lightpink + +color.bg.tableheader.gradient.start = color.bg +color.bg.tableheader.gradient.end = lightGray +color.bg.tableheader.gradient.start.primary = rgb(205, 227, 244) +color.bg.tableheader.gradient.end.primary = rgb(126, 186, 233) + +color.bg.textfield.hint.valid = color.bg +color.bg.textfield.hint.invalid = rgb(255,225,225) +color.fg.textfield.hint = color.fg.hint + +color.bg.tree.drag = color.palette.lavender +color.bg.tree.drag.no.selection = rgb(204, 204, 255) + +color.bg.filterfield = color.bg.filtered +color.fg.filterfield = black + +color.bg.selection.help = lightsteelblue + +// generic component items +color.border.bevel.highlight = lightGray +color.border.bevel.shadow = gray +color.border.provider.disconnected = orange + +color.bg.filechooser = color.bg +color.fg.filechooser = color.fg +color.bg.filechooser.shortcut = lightGray + +color.bg.fieldpanel = color.bg +color.fg.fieldpanel = color.fg +color.bg.fieldpanel.selection = color.bg.selection +color.bg.fieldpanel.highlight = color.bg.highlight +color.bg.fieldpanel.selection.and.highlight = green + +color.bg.tree = [color]Tree.textBackground +color.bg.tree.selected = [color]Tree.selectionBackground +// docking buttons +color.fg.button = black + +icon.folder.new = folder_add.png +icon.subtract = list-remove.png +icon.toggle.expand = expand.gif +icon.toggle.collapse = collapse.gif + +icon.undo = undo.png +icon.redo = redo.png +icon.font = text_lowercase.png +icon.rename = textfield_rename.png +icon.check = check.png +icon.search = magnifier.png +icon.properties = document-properties.png +icon.table = table.png +icon.drive = drive.png +icon.run = play.png +icon.spreadsheet = application-vnd.oasis.opendocument.spreadsheet-template.png +icon.pulldown = menu16.gif +icon.window = application_xp.png +icon.zoom.in = zoom_in.png +icon.zoom.out = zoom_out.png + +icon.theme.import = mail-receive.png +icon.theme.export = mail-folder-outbox.png + +icon.docking.application.home = www_16.png +icon.docking.application.16 = www_16.png +icon.docking.application.128 = www_128.png + +icon.dragon.256 = GhidraIcon256.png + +icon.help.navigation.aid.disabled.overlay = icon.not.allowed +icon.help.navigation.aid.enabled = software-update-available.png + +icon.filechooser.places.my.computer = computer.png +icon.filechooser.places.desktop = desktop.png +icon.filechooser.places.home = user-home.png +icon.filechooser.places.recent = inode-directory.png {edit-undo.png [move(6,10)]} + +icon.filter.options.contains = page_code.png +icon.filter.options.exact = page_green.png +icon.filter.options.regex = page_excel.png +icon.filter.options.starts.with = page_go.png +icon.filter.options.not = bullet_delete.png + +icon.widget.imagepanel.reset = tag.png +icon.widget.imagepanel.zoom.in = icon.zoom.in +icon.widget.imagepanel.zoom.out = icon.zoom.out +icon.widget.imagepanel.zoom.reset = zoom.png + +icon.widget.filterpanel.filter.off = filter_off.png +icon.widget.filterpanel.filter.on = filter_on.png + +icon.widget.pathmanager.reset = trash-empty.png + +icon.widget.table.header.help = info_small.png +icon.widget.table.header.help.hovered = info_small_hover.png +icon.widget.table.header.pending = hourglass.png + +icon.dialog.error.expandable.report = icon.spreadsheet +icon.dialog.error.expandable.exception = program_obj.png +icon.dialog.error.expandable.frame = StackFrameElement.png +icon.dialog.error.expandable.stack = StackFrame_Red.png +icon.dialog.error.expandable.cause = emblem-important.png + +icon.task.progress.1 = eatbits1.png +icon.task.progress.2 = eatbits2.png +icon.task.progress.3 = eatbits3.png +icon.task.progress.4 = eatbits4.png +icon.task.progress.5 = eatbits5.png +icon.task.progress.6 = eatbits6.png +icon.task.progress.7 = eatbits7.png + +icon.task.progress.hourglass.1 = hourglass24_01.png +icon.task.progress.hourglass.2 = hourglass24_02.png +icon.task.progress.hourglass.3 = hourglass24_03.png +icon.task.progress.hourglass.4 = hourglass24_04.png +icon.task.progress.hourglass.5 = hourglass24_05.png +icon.task.progress.hourglass.6 = hourglass24_06.png +icon.task.progress.hourglass.7 = hourglass24_07.png +icon.task.progress.hourglass.8 = hourglass24_08.png +icon.task.progress.hourglass.9 = hourglass24_09.png +icon.task.progress.hourglass.10 = hourglass24_10.png +icon.task.progress.hourglass.11 = hourglass24_11.png + +// Fonts + +font.splash.header.default = Serif-BOLD-35 +font.splash.status = Serif-BOLD-12 +font.table.header.number = arial-BOLD-12 +font.input.hint = monospaced-PLAIN-10 + +[Dark Defaults] + +color.bg = #1c1d1e +color.fg = lightgray +color.fg.error = indianRed +color.fg.disabled = gray +color.bg.filtered = beige +color.fg.hint = darkgray + +color.fg.help.selector.h1 = #66AAF4 +color.fg.help.selector.h2 = #9999F9 +color.fg.help.selector.h3 = #FF99CC +color.fg.help.selector.p.provided.by.plugin = #CCCCCC +color.fg.help.selector.p.related.topic = #800080 +color.fg.help.selector.th = #EDF3FE +color.fg.help.selector.code = gray +color.fg.help.selector.code.path = #5BA5E3 + +color.bg.splashscreen = black + +color.bg.header.active = #4c87c8 +color.bg.header.inactive = #466a92 +color.fg.header.active = lightGray +color.fg.header.inactive = black +color.header.drag.cursor = lightGray + +color.fg.dialog.status.alert = orange +color.fg.dialog.status.error = color.fg.error +color.fg.dialog.status.warning = orange +color.fg.dialog.status.normal = lightBlue + +color.bg.currentline = rgb(40,40,56) // dark bluish gray + +color.cursor.focused = indianRed +color.cursor.unfocussed = darkGray + +color.bg.textfield.hint.invalid = maroon + +color.bg.filterfield = color.bg.filtered +color.fg.filterfield = darkSlateGray + +color.bg.selection = color.palette.bg.green +color.bg.highlight = color.palette.bg.yellow + +color.bg.fieldpanel.selection.and.highlight = color.palette.bg.yellowgreen + +color.bg.table.row.alt = rgb(45,47,65) +color.fg.table.uneditable.selected = lemonchiffon +color.fg.table.uneditable.unselected = lightgray + +color.bg.tableheader.gradient.start = color.bg +color.bg.tableheader.gradient.end = darkGray +color.bg.tableheader.gradient.start.primary = color.bg +color.bg.tableheader.gradient.end.primary = darkBlue + +// docking buttons +color.fg.button = darkGray + +color.bg.filechooser.shortcut = system.color.bg.widget + +color.bg.tree = color.bg +color.bg.tree.selected = [color]Tree.selectionBackground + diff --git a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml index 8a327c6107..233752f8a2 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml @@ -20,9 +20,9 @@ During the help build time, all TOC_Source.xml files will be parsed and validated to ensure that all tags point to valid tags. From these files will be generated _TOC.xml files, which are table of contents files written in the format - desired by the JavaHelp system. Additionally, the genated files will be merged together + desired by the JavaHelp system. Additionally, the generated files will be merged together as they are loaded by the JavaHelp system. In the end, when displaying help in the Ghidra - help GUI, there will be on table of contents that has been created from the definitions in + help GUI, there will be one table of contents that has been created from the definitions in all of the modules' TOC_Source.xml files. @@ -43,12 +43,25 @@ **The URL for the target is relative and should start with 'help/topics'. This text is used by the Ghidra help system to provide a universal starting point for all links so that they can be resolved at runtime, across modules. - + --> - - + ++ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/DarkStyle.css b/Ghidra/Framework/Docking/src/main/help/help/shared/DarkStyle.css new file mode 100644 index 0000000000..6ff0fe6fb8 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/shared/DarkStyle.css @@ -0,0 +1,58 @@ +/* ### + * 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. + */ +/* + Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but + px (pixel) or with no type marking. +*/ + +body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */ +li { font-family:times new roman; font-size:14pt; } +h1 { color:#80a0c0; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } +h2 { margin: 10px; margin-top: 20px; color:#DDA0DD; font-family:times new roman; font-size:18pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#6495ED; font-family:times new roman; font-size:14pt; font-weight:bold; } +h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } + +/* + P tag code. Most of the help files nest P tags inside of blockquote tags (the was the + way it had been done in the beginning). The net effect is that the text is indented. In + modern HTML we would use CSS to do this. We need to support the Ghidra P tags, nested in + blockquote tags, as well as naked P tags. The following two lines accomplish this. Note + that the 'blockquote p' definition will inherit from the first 'p' definition. +*/ +p { margin-left: 40px; font-family:times new roman; font-size:14pt; } +blockquote p { margin-left: 10px; } + +p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px } +p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px } +p.relatedtopic { color:#9370DB; margin-left: 10px; font-size:14pt; } +p.RelatedTopic { color:#9370DB; margin-left: 10px; font-size:14pt; } + +/* + We wish for a tables to have space between it and the preceding element, so that text + is not too close to the top of the table. Also, nest the table a bit so that it is clear + the table relates to the preceding text. +*/ +table { margin-left: 20px; margin-top: 10px; width: 80%;} +td { font-family:times new roman; font-size:14pt; vertical-align: top; } +th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; color: gray;} + +/* + Code-like formatting for things such as file system paths and proper names of classes, + methods, etc. To apply this to a file path, use this syntax: ++ ++ + + + ...+*/ +code { color: #F5F5F5; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; } +code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; } diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/Frontpage.css b/Ghidra/Framework/Docking/src/main/help/help/shared/Frontpage.css index b8471669f4..557c37ca39 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Framework/Docking/src/main/help/help/shared/Frontpage.css @@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1 li { font-family:times new roman; font-size:14pt; } h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } -h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; } +h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } /* diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/arrow.gif b/Ghidra/Framework/Docking/src/main/help/help/shared/arrow.gif deleted file mode 100644 index bcb3db7057..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/arrow.gif and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/close16.gif b/Ghidra/Framework/Docking/src/main/help/help/shared/close16.gif deleted file mode 100644 index f523864639..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/close16.gif and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/menu16.gif b/Ghidra/Framework/Docking/src/main/help/help/shared/menu16.gif deleted file mode 100644 index 4350a523dd..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/menu16.gif and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/note-red.png b/Ghidra/Framework/Docking/src/main/help/help/shared/note-red.png deleted file mode 100644 index b5f1d5cd1c..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/note-red.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/note.png b/Ghidra/Framework/Docking/src/main/help/help/shared/note.png deleted file mode 100644 index 51e1c8f8c1..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/note.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/note.yellow.png b/Ghidra/Framework/Docking/src/main/help/help/shared/note.yellow.png deleted file mode 100644 index f8ab6489f2..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/note.yellow.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/redo.png b/Ghidra/Framework/Docking/src/main/help/help/shared/redo.png deleted file mode 100644 index 88035efeec..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/redo.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/tip.png b/Ghidra/Framework/Docking/src/main/help/help/shared/tip.png deleted file mode 100644 index 209f1d28c8..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/tip.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/undo.png b/Ghidra/Framework/Docking/src/main/help/help/shared/undo.png deleted file mode 100644 index edd57f5c15..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/undo.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/warning.png b/Ghidra/Framework/Docking/src/main/help/help/shared/warning.png deleted file mode 100644 index 8e9133789b..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/warning.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Misc/Welcome_to_Help.htm b/Ghidra/Framework/Docking/src/main/help/help/topics/Misc/Welcome_to_Help.htm new file mode 100644 index 0000000000..4291313572 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Misc/Welcome_to_Help.htm @@ -0,0 +1,26 @@ + + + +Welcome to Help + + + + + + + + + + + +Welcome to Help...
+ +++ + + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/PlacheholderTopic/Placeholder.htm b/Ghidra/Framework/Docking/src/main/help/help/topics/PlacheholderTopic/Placeholder.htm deleted file mode 100644 index 13961916f5..0000000000 --- a/Ghidra/Framework/Docking/src/main/help/help/topics/PlacheholderTopic/Placeholder.htm +++ /dev/null @@ -1,17 +0,0 @@ - - - - -We provide context sensitive help on menu items, dialogs, buttons, +and tool windows. To access the help, press <F1> or <Help> on +any menu item or dialog. If specific help is not available for an item, +this page will be displayed.
+Placholder Title - - - - -Stub
- -Blah blah
- - - - - diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html new file mode 100644 index 0000000000..086394618e --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html @@ -0,0 +1,465 @@ + + + + + + +Developer's Guide + + + +Developer's Guide to Theming
+ +This document provides information an application developer should know when developing + plugins, actions, scripts, etc., that use colors, fonts, or icons. By following these guidelines, + developers can easily make use of Ghidra's theming capabilities.
+ +Theme Resource Types
+ +When developing application code for Ghidra such as plugins, actions, etc., developers often + want to use colors, fonts, and icons. The key idea to support theming is to never + directly + reference those resources. Instead, the developer should create an ID string for the resource + and then in a
+ +module.theme.propertiesfile, provide a default value for that ID. + (Also, you may define an alternate "dark" default value that will be used if the + current theme is considered a dark theme). The way you + define and use these IDs is a bit different depending on whether the resource is a color, font, + or icon. Colors and icons are similar in that developers use these types by creating either +GColororGIcon. + Unfortunately, because of the way fonts are implemented, there is no equivalent +GFont, so using fonts is a bit more involved.++ + +Colors
+ +For colors, developers should use the
+ +GColorclass. Simply construct a new +GColorobject passing in the color resource ID as the argument. +GColoris a subclass ofColor, so it can be + used anywhere aColorwould be used. The developer then needs to provide a + default value for that ID in the module'smodule.theme.propertiesfile. + So, for example:++ +++ +panel.setBackground(Color.Red);+becomes
+ +++ +panel.setBackground(new GColor("color.bg.abc"));+and
+ +++ +public static final Color MY_COLOR = Color.BLUE;+becomes
+ +++public static final Color MY_COLOR = new + GColor("color.fg.xzy");+The
+ +GColorclass uses a delegation model where all method calls to +GColorget mapped to + its delegate color. If ever the color associated with aGColor's resource ID + changes, theGColoris automatically updated by calling the +refresh()method. This is done whenever the +Gui.setColor(id)is called or a new theme is loaded.Icons
+ +Icons work just like colors, so you can just create a
+ +GIcon(String id). + So, for example,++ +++ +public static final Icon MY_ICON = + ResourceManager("images/balloon.png");+becomes
+ +++public static final Icon MY_ICON = new + GIcon("icon.text.bubble");+Fonts
+ +Unfortunately, fonts are unable to use the delegation model used for colors and icons. + Therefore, there is no
+ +GFontclass. Programming fonts requires a bit more work. + If a font used directly, such as in renderer or in a paint method, simply get the + font each time + from theGuiclass, as shown below. To set a font on a component, use +Gui.registerFont(Component, String). Once the component is registered, the + application will + automatically update the component if the font associated with that ID changes. So, for + example:++ +++ +Font font = new Font("Monospaced", Font.BOLD, 12);+becomes
+ +++ +Font font = Gui.getFont("font.xyz");+or
+ +++ +myLabel.setFont(new Font("Dialog", Font.PLAIN, 14)+becomes
+ +++Gui.registerFont(myLabel, "font.xyz");+Resource ID Strings
+ +++ +Resource IDs are strings used to identify a color, font, or icon. These strings are + created by the developer and should be chosen in a way that it is as self-describing as + possible. So, for example, if you wanted the text color in some error message in some widget + "abc", you might create the color ID "color.fg.abc.error". To help keep resource IDs + consistent, we created a convention for IDs as follows:
+ +++ ++++++ [type].[category[...]].[client].[specialized uses] +++
+ +- type: color, font, or icon.
+ +- category: any value, examples include 'bg'(background), 'fg'(foreground), + 'cursor'. There may be multiple dot-separated values.
+ +- client: the plugin name or feature name.
+ +- specialized uses: any key value here that applies to the client, such as + 'vertex' for a graph client.
+++Examples:
+ ++
+- color.bg
+ +- color.bg.listing
+ +- color.bg.functiongraph.vertex.group
+ +- font.listing
+ +- font.listing.header
+ +- icon.error
+ +- icon.delete
+ +- icon.plugin.byteviewer.provider
+Theme Property Files
+ +++ +The default values for resource IDs are defined in files that reside + a module's data directory (not all modules define this file). These files all + are named to end in
+ +theme.propertiesand begin with the module's name. Some + modules make use of multiple files in order to better manage the volume of IDs. In this + case, the name of each properties file offers a clue as to its contents. Thus, for small + modules, those without many resource IDs in use, one theme properties file is sufficient to + easily define and manage all required IDs. But, we recommend larger modules use multiple + files, one for each sub-feature. The application will find all theme property files as long as + they exist in a module's data directory and are named with the +.theme.propertiessuffix.Theme Properties File Naming Convention
+ +To promote consistency, theme property files should use the following naming + convention:
+ +++ +++ ++++ module name[.additional name]].theme.properties ++Examples:
+ ++
+- base.theme.properties
+ +- base.listing.theme.properties
+Theme Properties File Format
+ +Theme files uses a very simple format for specifying theme property values. Each line + specifies a property ID (sometimes referred to as the key) and a value, separated by an + "=". A theme properties file consists of two sections: the standard defaults section and a + section for specifying defaults for "dark" themes. +
+ +++ ++++[Defaults] + +[property id 1] = [some value] +[property id 2] = [some value] +[property id 3] = [some value] +... + +[Dark Defaults] + +[property id 1] = [some value] +[property id 2] = [some value] +... ++Example:
+ +++ + ++[Defaults] + +color.bg = white +color.bg.listing = color.bg + +color.fg.listing.address = black +color.fg.listing.bytes = #00ff00 + +font.global = courirer-BOLD-12 +font.global.listing = font.global + +icon.error = defaultError.png + + +[Dark Defaults] + +color.bg = black + +color.fg.listing.address = gray +color.fg.listing.bytes = orange ++NOTE: The
+[Dark Defaults]section is for optionally overriding values + defined in the standard[Defaults]section. If a property ID is not given a value + in the defaults section, it is an error. If a value is not defined in the +[Dark Defaults]section, then the value defined in the[Defaults]+ section will be used in a dark theme.Theme Property Values
+ +++ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingInternals.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingInternals.html new file mode 100644 index 0000000000..6a72228954 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingInternals.html @@ -0,0 +1,227 @@ + + + + + + +The values specified in the theme properties files can be specified in a variety of ways, + including ways to modify other property values. For example, an icon's size can be modified + directly in the theme properties file. A font value can specified as a reference to another + defined font, but with a different size or style.
+ +Also, any value can also be a reference to some other ID of the same type. So, for + example, a reference color entry might be something like "color.bg.listing = color.bg". This + says that the listing's background color should be whatever "color.bg" is defined to be. Note + that all of the application's defined properties start with either "color.", "font.", or + "icon.". Properties defined by a Java Look and Feel don't follow this pattern. To reference a + property that does not have a standard prefix, an ID can be prefixed with "[color]", + "[font]", or "[icon] as appropriate to allow the theme property parser to recognize the + values as IDs to other properties. So to refer to a Java property named "table.background", + you would use the following definition: "color.bg.table = [color]table.background".
+ +Color Values
+ +Color values supports the following formats:
+ +++ ++
+- #rrggbb
+ +- #rrggbbaa
+ +- 0xrrggbb
+ +- 0xrrggbbaa
+ +- rgb(red, green, blue)
+ +- rgba(red, green, blue, alpha)
+ +- web color name // the case-insensitive name of a web color such as red, olive, or + purple
+Examples:
++ color.foo = #0000ff // blue + color.foo = #ff000080 // red with half transparency + color.foo = 0x00ff00 // green + color.foo = 0xff000080 // red with half transparency + color.foo = rgb(0, 0, 255) // blue + color.foo = rgba(255,0, 0, 128) // red with half transparency + color.foo = blue // web color defined as 0x0000FF + color.foo = LawnGreen // web color defined as 0x7CFC00 ++ +Font Values
+ +Font values are specified using the following format:
+ +++ +++ ++ family name-style-size +++
+- family name: the font name such as
+ +monospaced,dialog, +courier.- style: One of
+ +PLAIN,BOLD,ITALIC, or +BOLDITALIC.- size: the font point size. 12 is very common.
+Examples:
++ font.foo = monospaced-PLAIN-12 + font.foo = courier-BOLD-14 + font.foo = SansSerif-ITALIC-10 ++ +Font Modifiers
+ +When referencing another font, the referenced font can be modified using the following + format:
+ +++ +++ ++ font.ref[family name][style][size] +++
+- font.ref: the theme property ID of some other font
+ +- family name: use the size and style of the reference font, but use this font + family.
+ +- style: use the same font as the reference font, but with this style. One of +
+ +PLAIN,BOLD,ITALIC, or +BOLDITALIC.- size: use the same font as the reference font, but with this size.
+Examples:
++ font.foo = SansSerif-PLAIN-12 // standard font spec + font.bar = font.foo[BOLD] // results in SansSerif-BOLD-12 + font.bar = font.foo[15] // results in SansSerif-PLAIN-15 + font.bar = font.foo[monospaced] // results in monospaced-PLAIN-12 + font.bar = font.foo[ITALIC][15] // results in SansSerif-ITALIC-15 ++ +Icon Values
+ +Icon are specified by simply entering the name of an icon that is in the classpath. + However, an icon value can get complicated because it can be modified in a number of ways, + such as scaling, disabling, even overlaying other icons. The format is as follows:
+ +++ +++ ++ iconName[size(width,height)][disabled]{iconOverlayName[size(width,height)[disabled][move(x,y)]}{...} + +++
+- iconName: the name the base icon
+ +- size(width,height): optional modifier to scale the image to the given size.
+ +- disabled: optional modifier to create a disabled version of the icon.
+ +- {...}: optional modifier to overlay an icon on the base icon. It is recursively + defined using the standard icon format.
+ +- move(x,y): optional modifier on overlays to position them relative to the base + icon.
+Examples:
++ icon.foo = house.png // using the icon house.png found as an image resource on the classpath + icon.foo = house.png[size(10,10)] // uses the house.png icon, but scales it to 10x10 + icon.foo = house.png[disabled] // creates a disabled version of house.png + icon.foo = house.png[16,16]{hammer.png[size(4,4)][move(12,12)]} + // creates a 16x16 version of the house icon with a 4x4 scaled + // hammer.icon overlayed in its lower right corner ++ +To create stand-alone icon suitable for dynamically overlaying other icons, there is + special syntax for specifying an empty base icon. Use the empty icon along with another + overlay icon in some specific area of the empty icon to create a final icon that can be used + as an overlay for other icons. For example, to + create an overlay icon that would add a flag to the bottom-right corner of any other icon:
++ icon.overlay.flag = EMPTY_ICON[size(16,16)]{flag.png[size(6,6)][move(10,10)]} ++ + +Provided by: Theme Manager
+ + + ++
- Theming Overview
+ +- Theming User's Guide
+ +- Theming Architecture
+
+Theming Architecture + + + + +Theming Architecture
+ +This document describes the API for initializing and managing themes. A theme (the +
+ +GTheme+ class) in Ghidra represents a specific Look and Feel as well the set of values for the color, + font, and icon resource IDs used in the application. Resource IDs are defined in theme properties + files. Application writers refer to these IDs when using colors, fonts and icons. + TheGuiclass provides a set of + static methods that serves as the primary interface for managing all aspects of theming.GTheme Class
+ +The
+ +GThemeclass is the implementation of the theme concept. At any given time, + the application is using resource values as specified by the active theme. The theme specifies + the Java Look and Feel, whether or not the overall theme is "dark" (which determines which default + values to use) and any resource values which have been overridden specifically by that theme. + There are two types of of themes; built-in themes and file-based themes. Built-in + themes are implemented directly as sub-classes ofGThemeand simply specify a + Java Look and Feel + and whether or not the theme is "dark". There is one "built-in" theme for each supported + Look and Feel. File-based themes read their values from a theme file. Theme files are created by + editing and saving existing themes.GThemeValueMap / ThemeValue Classes
+ +These are the base classes for storing values for resource IDs. A
+ +GThemeValueMap+ consists of three maps, one each for colors, fonts, and icons. Each map binds an ID to a + appropriate subclass ofThemeValue, which is the base class for +ColorValue,FontValue, and +IconValue. Resource values are stored in theseThemeValuesub-classes + because the value can be + either a concrete value or be a reference to some other resource of the same type. So, for + example, "color.bg.foo" could map directly to an actual color or its value could be reference + to some other indirect color like "color.bg.bar". In anyThemeValueobject, either + the referenced ID or the direct value must be null. To get the ultimate concrete value, there + is a convenience method calledget()onThemeValues that takes a +GThemeValueMapas an argument. + This method will recursively resolve reference IDs, which is why it needs a value map as an + argument.+ +
GThemeValueMaps have some convenience methods for performing set operations. + You can load + values from otherGThemeValueMaps into this map, which adds to the current map, + replacing values with the same ID with values from the other map. Also, there is a method for + getting the differences from one GThemeValueMap to another.Gui Class
+ +The
+ +Guiclass is a set of static methods that provides the primary API for + managing themes. + It has methods for switching themes, adding themes, deleting themes, saving themes, restoring + themes, getting/setting values for resource IDs, adding theme listeners, and others. This + class is meant to be used by application developers, along withGColorfor colors + andGIconfor icons. Fonts are handled slightly differently by making calls to +Gui.registerFont(Component, Id)+Application Initialization
+ +Applications need to call
+ +Gui.initialize()before any uses of color, fonts, or + icons occur. + This will load all resource defaults from all*.theme.propertiesfiles, read the + last used theme from preferences, and load that theme which includes setting the Look and Feel. +Loading a Theme
+ +Loading a theme consists of two main operations: loading the Look and Feel and building the + set of values for all defined resource IDs.
+ +Loading the Look and Feel
+ +Because each Look and Feel presents different challenges to the theming feature, there is a +
+ +LookandFeelManagerfor each Look and Feel. TheLookandFeelManageris + responsible for installing + the Look and Feel (in the case of Nimbus, we had to install a special subclass of the +NimbusLookandFeel), extracting the Java resources mappings (Java Look and Feel + objects also use a resource ID concept), group the Java resources into common groups, possibly + fix up some issues specific to that Look and Feel, possibly install global properties, and have + specific update techniques to get that Look and Feel to update its component UIs when + values change.Creating the Active Theme Values
+ +After the Look and Feel is loaded and the Java values extracted, the final resource mapping is + created. This is done by loading various resource values sets (each stored in a GThemeValueMap) + in the correct order into a new
+ +GThemeValueMapinThemeManagercalled + "currentValues" . When values are loaded into aGThemeValueMap, they will replace + any existing values with the same ID. The values are loaded in the following order:++ ++
+- Java defaults (values from Look and Feel)
+ +- application defaults (from *.theme.properties files)
+ +- applications dark defaults (if theme is dark)
+ +- theme values (values that were overridden by a specific theme)
+Changing Values Associated With Resource Ids
+ +Whenever the value associated with a resource ID changes, the application gets notified in + various ways to update the display with the new value. The technique used to notify the + application differs depending on the resource type and the Look and Feel (these differences are + captured in the
+ +LookandFeelManagersub-classes for each Look and Feel). It can also + vary depending on whether the value is an application defined resource or a Java defined + resource.Updating Colors
+ +Updating Colors is the easiest of all the resource types. First +
+ +GColor.refreshAll()is called, + which causes everyGColorto refresh its internal delegateColor. + This is the purpose of using theGColorclass, to introduce a level of indirection + that allows us to change runtime behavior without having to recompile. + Next,repaint()is called on all the top-level Java windows in the application. + Also, since color values in theUIDefaultsare actually + replaced with GColor objects, this technique works for both application defined resources and + Java defined resources.Updating Icons
+ +Updating icons is a mixed bag. If the icon is application defined, +
+ +GIcon.refreshAll()is + called which causes everyGIconto refresh its internal delegate icon and then + callrepaint()on all the + windows. If the icon is Java defined, then theUIDefaultshas to be updated and the +updateComponentTreeUI()method on all windows is called.Updating Fonts
+ +Updating Fonts is a bit more involved than updating colors and icons, due to the inability + to use the indirection model when working with fonts. First, if the changed font is Java + defined, the
+ + + +UIDefaultsfor that font ID (and any that derive from it) are updated. + Next, all the components that have calledGui.registeredFont()are updated. (The + registration system for fonts is what allows us to notify components of updates, since fonts + cannot use the indirection model.) + Finally, theupdateComponentTreeUI()method is + called on all windows in the application.Creating/Editing/Saving Themes
+ +New themes can be created and saved to files in the theme directory in the user's + application directory (
+ +<home>/.ghidra/.ghidra-<version>/themes). + When the application is started, this directory is scanned and any +*.themefiles are loaded and available to be selected as the active theme. + TheGuiclass has + methods for setting the value of a color, font, or icon for a given resource ID. If any values + are currently different from the active theme, the theme can be saved. If the active theme is a + built-in theme, then the only choice is to save using a new theme name. Saving the + theme will create a new "xyz.theme" file where "xyz" is the name of the theme. Otherwise, the + existing theme file can be overwritten or a new theme name can be supplied to save to a new + file.External Icons
+ +When setting icons for an icon resource ID, the user has the option of using an icon that + exists in the application (on the classpath) or using any supported icon file (.png or .gif) on + the filesystem. If the user + chooses to use a non-application icon file, then that icon will be copied into an images + directory in their application directory. These icons are considered external in that if the + theme were given to another user, you would also need to give them these icon files, as they + will not exist in other application installations.
+ +Importing/Exporting Themes
+ +Themes can be shared with other users by exporting and importing themes. When exporting a + theme that doesn't use any external icons (icons not on the classpath), the theme can be + exported to a
+ +.themefile of the user's choosing. If the theme does contain + external icons, the + user has the option to save the theme as a .zip file, which would contain both the .theme file + and all the external icon files.Look and Feel Notes
+ +Getting the theming feature to work on all the various Java Look and Feels is a + challenge. Java created the concept of
+ + + + +UIDefaults, which is a mapping of property + names + to values. The implication is that users can change Look and Feel settings by changing values + in theUIDefaults. Unfortunately, not all Look and Feels support this concept. + Nimbus and GTK+, in particular are problematic. Nimbus somewhat honors values in +UIDefaults, but only if those values are + installed before Nimbus is loaded. So for our theming purposes, we had to extend the Nimbus + Look and Feel in order to override thegetDefaults()method (this is the method + where Look and Feels populate theUIDefaults) so that we can install any overridden + values from the selected theme. Also, since Nimbus does not respect changes to these values after + they have been created, every time a Java defined property changes, we have to re-install the + Nimbus Look and Feel. The GTK+ Look and Feel is even more problematic. It gets many of its + properties + from native libraries and there doesn't appear to be anyway of changing them. Therefore, themes + based on GTK+ doesn't allow for changing Java defined values. To compensate for the + differences among Look and Feels, we created aLookandFeelManagerbase class with + sub-classes for each Look and Feel.Provided by: Theme Manager
+ + + +
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingOverview.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingOverview.html new file mode 100644 index 0000000000..d446609d85 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingOverview.html @@ -0,0 +1,137 @@ + + + + + + +General Overivew + + + + +Theming Overview
+ +This document describes Ghidra's support for using and managing UI themes. +
+ +Goal
+ +The primary goal of theming in Ghidra is to allow users to customize the appearance of the UI + and to share that customization with the community. We added infrastructure to Ghidra that + allows users/developers to completely configure the colors, fonts, and icons used within + the application. There are two main motivations for creating this feature. The first is to + provide the much requested "Dark Theme". Many users find Ghidra's current color scheme to be + hard on the eyes and have requested a dark color scheme. The + second motivation for creating this feature is for accessibility purposes. For example, the + theming feature allows the user to create a theme that uses high contrast colors and larger + fonts.
+ + +Background
+ +Before theming, Ghidra used thousands of hard-coded colors, fonts, and icons. They were + defined throughout the code in a somewhat haphazard fashion. Many features use colors to convey + similar concepts, but no effort was made to use similar colors for similar concepts. + Further, these colors were generally chosen to work with one of the common default Java Look and + Feels. (A Java Look and Feel is a grouping of UI settings that define the appearance of the + application.) Those original colors often looked terrible when used in conjunction with other + Look and Feels, especially dark ones.
+ +Ghidra did allow some customization of the current colors using the Ghidra Options API, but + this was inadequate for several reasons. One issue with this approach is that not all colors and + fonts are changeable via the options. Another issue is that the options are tool-based and you + have to make the same customization for each tool. A third problem is that options are unrelated + to the Look and Feel; you couldn't have different option choices depending on the current Look + and Feel.
+ +As mentioned, all of Ghidra's icons were hard-coded, with many not suitable for use in a dark + theme. Overall, the hard-coding of colors, fonts, and icons and the limitation of options made + creating a good dark theme virtually impossible. To address these issues, a new theming + infrastructure was created.
+ +General Concepts and Approach
+ +To achieve a theming capability in Ghidra, we had to make the following changes:
++
+ + +- Replace hard-coded values with a level of indirection for colors, fonts, and icons + using property names/IDs +
+- Create the concept of a theme that allows for the the property values to change + as a group and along with the current Look and Feel in use +
+- Create an API that allows for the introduction of system-level properties that can + be mapped to specific Look and Feel values in order to create reusable groups of properties +
+- Provide methods for changing the property values, along with the ability to create, + edit, save, export and import themes +
+++ + +Indirection
+ +The goal of using indirection is to remove all uses of hard-coded colors, fonts, and icons + when developing a feature in the application. Instead, these objects will be indirectly + referred to by an identifying string such as "color.bg.mywidget", where the string will + follow a known convention that helps indicate its use. Default values for these identifying + strings will be specified in data files that exist in the module where the code that defined + the ID is located. The values associated with these IDs can be either a concrete value such + as an actual color, font, or icon, or the value can be defined using a different property name, + allowing for properties to be defined by other properties. This allows users to change + individual values or entire groups of values with one edit.
+ +Theme
+ +A theme is simply the object that specifies all the values for colors, fonts, and icons + used in the application, as well as the Look and Feel. This allows there to be a set of + themes to choose from and by simply switching the theme, the system will then update the Look + and Feel along with the colors, fonts, and icons, all with one action. The set of themes to + choose from is a mix of built-in themes and saved custom themes. There is one built-in theme + for each supported Look and Feel. The chosen theme will use the UI values defied by the Look + and Feel, as well as all the values for the defined property IDs. Users are able to + create custom themes to change any color, font, or icon defined by the application, along with + UI values supplied by the associated Look and Feel.
+ +Look and Feel Values
+ +The Java Look and Feel is specified by the active theme. These Look and Feel objects + define colors, fonts, and icons indirectly using identifying strings such as "Button.font" + and "Menu.background". The Look and Feel mappings determine the default values used by all + GUI elements + unless overridden by developers when they create the components. With theming, users have the + ability to change these Java Look and Feel defined values in the same way as theme properties + defined created by application code. Another concept used by Java Look and Feels is that of + shared UI patterns. + Look and Feels typically share many of the same colors and those shared colors are defined + by the Look and Feel using a group name/key such as "control", "text", or "menu". This allows + for changes to be made at the group level or for the individual property. The theme + framework captures this Java grouping information when creating a theme that for a given + Look and Feel. +
+ +User Interaction
+ +Users will be able create, edit, delete, import, export, and of course switch the + application's active theme. The GUI theme editor allows users to perform all of these actions. + Using the active theme as a starting point, users will be able to change any color, font, or + icon defined either by the Look and Feel or the application. One or more of these changes can + be saved as a new theme and stored in a file in their application directory. Themes can be + shared with other users by exporting and importing themes.
+Provided by: Theme Manager
+ + + +
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingUserDocs.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingUserDocs.html new file mode 100644 index 0000000000..eb9ff2d102 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingUserDocs.html @@ -0,0 +1,259 @@ + + + + + + +Theming User Documentation + + + + +Editing Themes
+ +Description
+ +The Theming feature allows users to customize the colors, fonts, and icons used throughout + the application. The active theme determines the Java Look and Feel, whether the theme should use + light or dark defaults, and any custom colors, fonts, and icons that override the default + values. Users can can easily switch between any of the built-in themes or any saved themes found + in their home application directory
+ +Users can also edit and create their own themes using the Theme Editor. Custom themes are + stored in the user's
+ +<home>/.ghidra/.ghidra-<version>/themesdirectory. + These theme files are simple text files that can + easily be modified using any text editor. Also, users can share themes by exporting them to a + file that can be given to other users who can them import them into their application.Theme Dialog
+ +The Theme Dialog is the primary means for creating, editing, and saving themes.
+ ++ +
+The Theme Dialog consists of a theme drop-down and a tabbed set of tables that display the + values for every color property, font property, and icon property defined by either the Java + Look and Feel or the application. All application defined properties start with "color.", + "font.", or "icon.", depending on whether the the property is a color, font, or icon + respectively. All other properties are defined by the Java Look and Feel. This naming + convention is not enforced, thus it is possible that 3rd-party Extensions may introduce + property names that do not match this description. See + the Developer Documentation for more details on the property ID + format and naming conventions. +
+ +Each table entry shows the property ID string, the current value, the theme value, + and the default value. Most often, the three values are equal. If the theme value is different + from the default value, that means that the active theme has overridden the default value for + that property. If the current value is different from the theme value, that means the user has + changed that value, but not yet saved the changes back to the theme.
+ +Individual values can be changed by double-clicking the value in the ID or Current Value + column. This will bring up an appropriate editor for changing the value. When editing a value, + the change + takes place immediately in the application so you can see the effect. When you leave the + specific property editor, you have the choice of keeping the change or canceling and having it + revert back to its previous value.
+ +If any values have been changed, the Save button will become enabled, allowing you to save + any changes you have made. (Pressing the Dismiss button will also give the the option to + save.) When saving, if the + current theme is a built-in theme, you will first have to supply a new theme name. If the + current theme is a not a built-in theme, you will have the option to overwrite the existing + theme or supplying a new name to save it as a new theme.
+ +++ +Color Editor
+ +When you double-click on a color value, the Edit Color dialog appears.
+ ++ +
+Any change you make in the editor is applied to the application immediately. If you press + the OK button, the change will stay. If you press the Cancel button, the color + will revert back to the original color.
+ +Font Editor
+ +When you double-click on a font value, the Edit Font dialog appears.
+ ++ +
+Any change you make in the editor is applied to the application immediately. If you press + the OK button, the change will stay. If you press the Cancel button, the font + will revert back to the original font.
+ +Icon Editor
+ +When you double-click on an Icon value, the Edit Icon dialog appears.
+ ++ +
+The Edit Icon dialog has a drop-down text field where you can find any existing icon on + the classpath. If you want to choose an Icon from the file system, press the ... button + and a File Chooser will appear, allowing you to pick an icon file from anywhere on the filesystem. + Any change you make in the editor is applied to the application immediately. If you press the + OK button, the change will stay. If you press the Cancel button, the icon will + revert back to the original icon.
+Theme Actions
+ +++ +Switching Themes
+ +To change the current theme, first bring up the Theme Dialog. + The Theme Dialog can be invoked from the main application menu using the + Edit
+ +Theme menu. From the Theme + Dialog you can select a theme from the combo box at the top.
Modifying Theme Values
+ +All the colors, fonts, and icons that have been registered with the theme API can be + modified using the Theme Dialog. The Theme Dialog can be invoked + from the main application menu using the + Edit
+ +Theme menu. Choose the + tab for the appropriate type and double-click on the ID column or Current Value column of the + item you want to change. An editor for that type will appear.
Reseting Theme Values
+ +To reset an individual value back to its original theme value, from the + main application menu invoke the Theme Dialog using the Edit
+ +Theme menu. Choose the + tab for the appropriate type and right-click on the row of the value you want to reset, then + choose the Restore Value menu item.
Reseting All Theme Values
+ +To reset all values back to the original values established by the current theme, from the + main application menu invoke + the Edit
+ +Theme Actions
Reset Theme Values menu.
Saving Themes
+ +After making changes to one or more theme values, the Theme + Dialog's Save button will be enabled. Pressing the Save button will give + the user the option of creating a new theme or overwriting the current them (if the current + theme is not a built-in theme). Also, users will have the option of saving a theme if they + dismiss the Theme Dialog while there are changes to one or more theme values.
+ +Deleting Themes
+ +To delete a custom saved theme, from the main application menu invoke the + Edit
+ +Theme Actions
Delete Theme... menu. This will bring up a dialog + with a list of themes that can be deleted. Select the theme to delete and press the Ok + button.
Exporting Themes>
+ +To export a theme so that it can be shared with others, from the + main application menu invoke the Edit
+ +Theme Actions
Export Theme... menu. You will first be asked if + you want to export as a regular theme file or as a Zip file. The Zip file option is useful if + the current theme has icon values that are not included with standard application. In that case, + the Zip file will include those non-standard icon files.
Importing Themes
+ +To import a theme, from the main application menu + invoke the Edit
+ +Theme Actions
Import + Theme... menu. A file chooser dialog will appear allowing the user to choose a theme file + to import. The selected file can be either a standard theme file or a Zip file containing the + theme file and any non-standard icon files defined by that theme.
Reloading Default Values
+ +This action causes Ghidra to reload all theme default values. It is really only useful + for developers who are actively making changes to theme.properties files. To activate this + action, press the refresh button
+in the top + right corner of the Theme Dialog.
Theme Property Names
+ +Theme Property Names (also referred to as IDs or keys) that are defined by the application + use a common format to help make sorting and viewing properties more intuitive as to their use. See + the Developer Documentation for more details on the property ID + format and naming conventions.
+ +Theme Files
++ +Theme Files are used to store saved custom themes. They are simple text files and are + stored in the user's home application directory under +
+<home>/.ghidra/.ghidra-<version>/themes. The first three properties are always the + theme name, the Look and Feel name, and whether the theme uses standard defaults or dark + defaults. Finally, there is a list of overridden property "name = value" lines. The format + is:++ ++ name = [theme name] + Look and Feel = [Look and Feel name] + useDarkDefaults = [true or false] + + [theme id 1]= [color, icon, or font value] + [theme id 2]= [color, icon, or font value] + [theme id 3]= [color, icon, or font value] + [theme id 4]= [color, icon, or font value] + ... ++++ + +Example:
++ name = BigFontTheme + Look and Feel = Nimbus + useDarkDefaults = false + + color.bg = Black + color.bg.foo = #012345 + [color]Panel.background = Red + font.button = dialog-PLAIN-14 + icon.refresh = images/reload3.png + color.bg.bar = color.bg.foo + color.bg.xxx = [color]Panel.background ++ + +Each property line is expected to begin with either "color.", "font.", or "icon." Since + java defined properties don't start with these prefixes, they will have "[color]", "[font]", + or "[icon]" prepended to their property name. These brackets are only used to aid in + parsing this file. When the properties are used in Ghidra, the bracketed prefixes are + removed.
+ +Also, note that the values of these properties can reference other property names. If the + right side of the assignment is a property name and not a value, then it must also use the + bracketed prefix if the property name doesn't start with "color.", "font.", or "icon."
+ +Specifying Theme Property Values
+ +Specifying property values varies depending on whether it is a color, font, or icon. Fonts + and icons also support specifying modifiers. For a complete description of how to specify + these values, see the Developer Documentation. + +
Provided by: Theme Manager
+ + +
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ColorEditor.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ColorEditor.png new file mode 100644 index 0000000000..937e5a7b70 Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ColorEditor.png differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/FontEditor.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/FontEditor.png new file mode 100644 index 0000000000..10e4350d97 Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/FontEditor.png differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/IconEditor.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/IconEditor.png new file mode 100644 index 0000000000..b806590033 Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/IconEditor.png differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ThemeDialog.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ThemeDialog.png new file mode 100644 index 0000000000..5254f290aa Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ThemeDialog.png differ diff --git a/Ghidra/Framework/Docking/src/main/java/docking/CloseIcon.java b/Ghidra/Framework/Docking/src/main/java/docking/CloseIcon.java new file mode 100644 index 0000000000..48d28967e3 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/CloseIcon.java @@ -0,0 +1,120 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking; + +import java.awt.*; +import java.awt.geom.GeneralPath; + +import javax.swing.Icon; + +/** + * Icon for a close button + */ +public class CloseIcon implements Icon { + private int size; + private Color color; + private Shape shape; + + /** + * Creates a close icon. + * @param isSmall false signals to use a 16x16 size; true signals to use an 8x8 size + * @param color the color of the "x" + */ + public CloseIcon(boolean isSmall, Color color) { + this.size = isSmall ? 8 : 16; + this.color = color; + this.shape = buildShape(); + } + + private Shape buildShape() { + GeneralPath path = new GeneralPath(); + + /* + We use trial and error sizing. This class allows clients to specify the icon size. At + the time of writing, there were only 2 sizes in use: 16 and 8 pixels. If more size + needs arise, we can revisit how the values below are chosen. + */ + + double margin = 2; + double shapeSize = 11; + double thickness = 1.7; + if (size == 8) { + margin = 0; + shapeSize = 7; + thickness = 1; + } + + double p1x = margin; + double p1y = margin + thickness; + double p2x = margin + thickness; + double p2y = margin; + double p3x = margin + shapeSize; + double p3y = margin + shapeSize - thickness; + double p4x = margin + shapeSize - thickness; + double p4y = margin + shapeSize; + + path.moveTo(p1x, p1y); + path.lineTo(p2x, p2y); + path.lineTo(p3x, p3y); + path.lineTo(p4x, p4y); + path.lineTo(p1x, p1y); + + p1x = margin + shapeSize - thickness; + p1y = margin; + p2x = margin + shapeSize; + p2y = margin + thickness; + p3x = margin + thickness; + p3y = margin + shapeSize; + p4x = margin; + p4y = margin + shapeSize - thickness; + + path.moveTo(p1x, p1y); + path.lineTo(p2x, p2y); + path.lineTo(p3x, p3y); + path.lineTo(p4x, p4y); + path.lineTo(p1x, p1y); + + path.closePath(); + return path; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + try { + g2d.translate(x, y); + g2d.setColor(color); + g2d.fill(shape); + } + finally { + g2d.translate(-x, -y); + } + } + + @Override + public int getIconWidth() { + return size; + } + + @Override + public int getIconHeight() { + return size; + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java index cb71394ff5..20bfef2bc5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java @@ -15,14 +15,15 @@ */ package docking; -import java.awt.Component; -import java.awt.KeyboardFocusManager; +import java.awt.*; import java.awt.event.MouseEvent; import java.util.*; import javax.swing.*; import docking.action.*; +import generic.theme.Gui; +import generic.theme.ThemeManager; import ghidra.util.*; import ghidra.util.exception.AssertException; import help.HelpDescriptor; @@ -114,6 +115,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext private String inceptionInformation; + private String registeredFontId; + /** * Creates a new component provider with a default location of {@link WindowPosition#WINDOW}. * @param tool The tool will manage and show this provider @@ -776,6 +779,41 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext return dockingTool; } + /** + * Tells the provider to adjust the font size for this provider. By default, this method + * will adjust the font for the registered font id if it has been registered using + * {@link #registeredFontId}. Subclasses can override this method to a more comprehensive + * adjustment to multiple fonts if necessary. + * @param bigger if true, the font should be made bigger, otherwise the font should be made + * smaller + */ + public void adjustFontSize(boolean bigger) { + if (registeredFontId == null) { + return; + } + Font font = Gui.getFont(registeredFontId); + if (font == null) { + return; + } + int size = font.getSize(); + if (bigger) { + size += 1; + } + else { + size = Math.max(size - 1, 3); + } + ThemeManager.getInstance().setFont(registeredFontId, font.deriveFont((float) size)); + } + + /** + * Registers a fontId for the font that will be automatically adjusted when + * {@link #adjustFontSize(boolean)} is called. + * @param fontId the id of the theme font to be adjusted + */ + protected void registerAdjustableFontId(String fontId) { + this.registeredFontId = fontId; + } + @Override public String toString() { return name + " - " + getTitle() + " - " + getSubTitle(); @@ -885,4 +923,5 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext return inceptionInformation; } } + } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java index 605fb3d1f7..8d47d68f05 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java @@ -32,6 +32,8 @@ import docking.event.mouse.GMouseListenerAdapter; import docking.menu.DialogToolbarButton; import docking.util.AnimationUtils; import docking.widgets.label.GDHtmlLabel; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.util.*; import ghidra.util.exception.AssertException; import ghidra.util.task.*; @@ -45,7 +47,10 @@ import utility.function.Callback; public class DialogComponentProvider implements ActionContextProvider, StatusListener, TaskListener { - private static final Color WARNING_COLOR = new Color(0xff9900); + private static final Color FG_COLOR_ALERT = new GColor("color.fg.dialog.status.alert"); + private static final Color FG_COLOR_ERROR = new GColor("color.fg.dialog.status.error"); + private static final Color FG_COLOR_WARNING = new GColor("color.fg.dialog.status.warning"); + private static final Color FG_COLOR_NORMAL = new GColor("color.fg.dialog.status.normal"); private final static int DEFAULT_DELAY = 750; @@ -699,13 +704,13 @@ public class DialogComponentProvider protected Color getStatusColor(MessageType type) { switch (type) { case ALERT: - return Color.orange; + return FG_COLOR_ALERT; case WARNING: - return WARNING_COLOR; + return FG_COLOR_WARNING; case ERROR: - return Color.red; + return FG_COLOR_ERROR; default: - return Color.blue; + return FG_COLOR_NORMAL; } } @@ -914,7 +919,7 @@ public class DialogComponentProvider statusLabel = new GDHtmlLabel(" "); statusLabel.setName("statusLabel"); statusLabel.setHorizontalAlignment(SwingConstants.CENTER); - statusLabel.setForeground(Color.blue); + statusLabel.setForeground(Messages.NORMAL); statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5)); statusLabel.addComponentListener(new ComponentAdapter() { @Override diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java index 3ad420264f..aed16982ec 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableHeader.java @@ -23,7 +23,8 @@ import java.util.*; import java.util.List; import java.util.stream.Collectors; -import javax.swing.*; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; import org.jdesktop.animation.timing.Animator; import org.jdesktop.animation.timing.Animator.RepeatBehavior; @@ -31,6 +32,8 @@ import org.jdesktop.animation.timing.TimingTargetAdapter; import org.jdesktop.animation.timing.interpolation.PropertySetter; import docking.util.AnimationUtils; +import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors.Palette; import generic.util.WindowUtilities; import generic.util.image.ImageUtils; import ghidra.framework.OperatingSystem; @@ -41,7 +44,6 @@ import ghidra.util.bean.GGlassPane; import ghidra.util.bean.GGlassPanePainter; import help.Help; import help.HelpService; -import resources.ResourceManager; /** * Component for providing component titles and toolbar. Also provides Drag @@ -490,6 +492,7 @@ public class DockableHeader extends GenericHeader private static class EmphasizeDockableComponentPainter implements GGlassPanePainter { + private static final GIcon DRAGON_ICON = new GIcon("icon.dragon.256"); private SetotherComponentInfos = new HashSet<>(); private Image image; @@ -538,7 +541,7 @@ public class DockableHeader extends GenericHeader g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - Color background = new Color(218, 232, 250); + Color background = Palette.getColor("aliceblue"); g.setColor(background); Rectangle othersBounds = null; @@ -567,8 +570,7 @@ public class DockableHeader extends GenericHeader g2d.fillRect(othersBounds.x, othersBounds.y, othersBounds.width, othersBounds.height); - ImageIcon ghidra = ResourceManager.loadImage("images/GhidraIcon256.png"); - Image ghidraImage = ghidra.getImage(); + Image ghidraImage = DRAGON_ICON.getImageIcon().getImage(); double scale = percentComplete * 7; int gw = ghidraImage.getWidth(null); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockableToolBarManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockableToolBarManager.java index 82e8c35169..0116deda95 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockableToolBarManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockableToolBarManager.java @@ -15,8 +15,7 @@ */ package docking; -import java.awt.Dimension; -import java.awt.FlowLayout; +import java.awt.*; import java.util.Collections; import java.util.Iterator; @@ -24,17 +23,17 @@ import javax.swing.*; import docking.action.*; import docking.menu.*; +import generic.theme.GColor; import ghidra.util.exception.AssertException; import ghidra.util.task.SwingUpdateManager; -import resources.ResourceManager; /** * Manages to toolbar for the dockable components. */ class DockableToolBarManager { - private static final ImageIcon CLOSE_ICON = ResourceManager.loadImage("images/close16.gif"); - private static final ImageIcon MENU_ICON = ResourceManager.loadImage("images/menu16.gif"); - + private static final Color BUTTON_COLOR = new GColor("color.fg.button"); + private static final Icon CLOSE_ICON = new CloseIcon(false, BUTTON_COLOR); + private Icon MENU_ICON = new DropDownMenuIcon(BUTTON_COLOR); private GenericHeader dockableHeader; private ToolBarManager toolBarManager; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingUtils.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingUtils.java index e44ac282c9..6da2c86f27 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingUtils.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingUtils.java @@ -37,7 +37,8 @@ import docking.widgets.list.GList; import docking.widgets.list.GListCellRenderer; import docking.widgets.table.GTableCellRenderer; import docking.widgets.tree.support.GTreeRenderer; -import ghidra.docking.util.DockingWindowsLookAndFeelUtils; +import generic.theme.GThemeDefaults.Colors.Palette; +import ghidra.docking.util.LookAndFeelUtils; import ghidra.util.HTMLUtilities; import resources.ResourceManager; @@ -125,7 +126,7 @@ public class DockingUtils { public static JSeparator createToolbarSeparator() { Dimension sepDim = new Dimension(2, ICON_SIZE + 2); JSeparator separator = new JSeparator(SwingConstants.VERTICAL); - if (DockingWindowsLookAndFeelUtils.isUsingAquaUI(separator.getUI())) { + if (LookAndFeelUtils.isUsingAquaUI(separator.getUI())) { separator.setUI(new BasicSeparatorUI()); } separator.setPreferredSize(sepDim); // ugly work around to force height of separator @@ -349,7 +350,7 @@ public class DockingUtils { c.setBorder(BorderFactory.createEmptyBorder()); } - c.setBackground(new Color(0, 0, 0, 0)); + c.setBackground(Palette.NO_COLOR); } /** Hides any open tooltip window */ diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DropDownMenuIcon.java b/Ghidra/Framework/Docking/src/main/java/docking/DropDownMenuIcon.java new file mode 100644 index 0000000000..7f07f50405 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/DropDownMenuIcon.java @@ -0,0 +1,94 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking; + +import java.awt.*; +import java.awt.geom.GeneralPath; + +import javax.swing.Icon; + +/** + * Icon for a drop down menu button (triangle pointing down) + */ +public class DropDownMenuIcon implements Icon { + private static final int ICON_SIZE = 16; + + private Color color; + private Shape shape; + + /** + * Creates a drop down menu icon. + * @param color the color of the triangle + */ + public DropDownMenuIcon(Color color) { + this.color = color; + this.shape = buildShape(); + } + + private Shape buildShape() { + + GeneralPath path = new GeneralPath(); + + double iconSize = 16; + double height = 6; + double width = 10; + double leftMargin = (iconSize - width) / 2; + double topMargin = (iconSize - height) / 2; + + // draw a triangle pointing down; p1 is the bottom; p2 is the left + double p1x = leftMargin + (width / 2); + double p1y = topMargin + height; + double p2x = leftMargin; + double p2y = topMargin; + double p3x = leftMargin + width; + double p3y = topMargin; + + path.moveTo(p1x, p1y); + path.lineTo(p2x, p2y); + path.lineTo(p3x, p3y); + path.lineTo(p1x, p1y); + path.closePath(); + + return path; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + try { + g2d.translate(x, y); + g2d.setColor(color); + g2d.fill(shape); + } + finally { + g2d.translate(-x, -y); + } + } + + @Override + public int getIconWidth() { + return ICON_SIZE; + } + + @Override + public int getIconHeight() { + return ICON_SIZE; + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/EditWindow.java b/Ghidra/Framework/Docking/src/main/java/docking/EditWindow.java index bc1e21c2e1..9512e3eb65 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/EditWindow.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/EditWindow.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +22,8 @@ import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import generic.theme.GThemeDefaults.Colors; + /** * A re-usable floating text edit window. */ @@ -34,7 +35,7 @@ public class EditWindow extends JWindow { private Component comp; private Rectangle rect; private EditListener listener; - + private AssociatedComponentListener compListener = new AssociatedComponentListener(); /** @@ -46,7 +47,7 @@ public class EditWindow extends JWindow { this.mgr = mgr; create(); } - + Component getAssociatedComponent() { return comp; } @@ -55,7 +56,7 @@ public class EditWindow extends JWindow { * @see java.awt.Window#isActive() */ @Override - public boolean isActive() { + public boolean isActive() { return active; } @@ -63,16 +64,16 @@ public class EditWindow extends JWindow { * @see java.awt.Component#setVisible(boolean) */ @Override - public void setVisible(boolean state) { - + public void setVisible(boolean state) { + active = state; super.setVisible(state); - + if (!state) { if (comp != null) { comp.removeComponentListener(compListener); if (comp instanceof JTabbedPane) { - ((JTabbedPane)comp).removeChangeListener(compListener); + ((JTabbedPane) comp).removeChangeListener(compListener); } Frame frame = mgr.getRootFrame(); frame.removeComponentListener(compListener); @@ -81,7 +82,7 @@ public class EditWindow extends JWindow { } } } - + void close() { setVisible(false); dispose(); @@ -90,55 +91,55 @@ public class EditWindow extends JWindow { void show(String defaultText, Component c, Rectangle r, EditListener editListener) { if (comp != null) { - setVisible(false); + setVisible(false); } - + if (c == null || !c.isVisible()) { return; } - + this.comp = c; this.rect = r; this.listener = editListener; - + comp.addComponentListener(compListener); - + if (comp instanceof JTabbedPane) { - ((JTabbedPane)comp).addChangeListener(compListener); + ((JTabbedPane) comp).addChangeListener(compListener); } - + Frame frame = mgr.getRootFrame(); frame.addComponentListener(compListener); setLocation(); - + textField.setText(defaultText != null ? defaultText : ""); Dimension d = textField.getPreferredSize(); textField.setPreferredSize(new Dimension(rect.width, d.height)); pack(); - + setVisible(true); - + toFront(); - textField.requestFocus(); - textField.selectAll(); + textField.requestFocus(); + textField.selectAll(); } - + private void setLocation() { Point p = comp.getLocationOnScreen(); - setLocation(p.x+rect.x+3, p.y+rect.y); + setLocation(p.x + rect.x + 3, p.y + rect.y); } - + private void create() { textField = new JTextField(" "); JPanel panel = new JPanel(new BorderLayout()); - Color bgColor = new Color(255, 255, 195); + Color bgColor = Colors.BACKGROUND_TOOLTIP; panel.setBackground(bgColor); - panel.add(textField, BorderLayout.CENTER); + panel.add(textField, BorderLayout.CENTER); textField.addKeyListener(new KeyAdapter() { @Override - public void keyPressed(KeyEvent e) { + public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { close(); } @@ -146,51 +147,53 @@ public class EditWindow extends JWindow { }); textField.addFocusListener(new FocusAdapter() { @Override - public void focusLost(FocusEvent e) { - if ( !e.isTemporary() ) { - close(); - } + public void focusLost(FocusEvent e) { + if (!e.isTemporary()) { + close(); + } } }); - textField.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (listener != null) { - String text = textField.getText(); - EditListener l = listener; - close(); - l.editCompleted(text); - } + textField.addActionListener(e -> { + if (listener != null) { + String text = textField.getText(); + EditListener l = listener; + close(); + l.editCompleted(text); } }); getContentPane().add(panel, BorderLayout.CENTER); } - + private class AssociatedComponentListener implements ComponentListener, ChangeListener { - + /* * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.ComponentEvent) */ + @Override public void componentHidden(ComponentEvent e) { close(); } - + /* * @see java.awt.event.ComponentListener#componentResized(java.awt.event.ComponentEvent) */ + @Override public void componentResized(ComponentEvent e) { close(); } - + /* * @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent) */ + @Override public void componentShown(ComponentEvent e) { } - + /* * @see java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent) */ + @Override public void componentMoved(ComponentEvent e) { if (comp != null && comp.isVisible()) { setLocation(); @@ -200,6 +203,7 @@ public class EditWindow extends JWindow { /* * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) */ + @Override public void stateChanged(ChangeEvent e) { close(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ErrLogExpandableDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/ErrLogExpandableDialog.java index aa8674bb60..fed06a9180 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ErrLogExpandableDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ErrLogExpandableDialog.java @@ -31,19 +31,18 @@ import javax.swing.tree.TreePath; import docking.widgets.label.GHtmlLabel; import docking.widgets.tree.*; import docking.widgets.tree.support.GTreeDragNDropHandler; +import generic.theme.GIcon; import ghidra.util.*; import ghidra.util.exception.MultipleCauses; import ghidra.util.html.HTMLElement; -import resources.ResourceManager; import util.CollectionUtils; public class ErrLogExpandableDialog extends AbstractErrDialog { - public static ImageIcon IMG_REPORT = ResourceManager.loadImage("images/report.png"); - public static ImageIcon IMG_EXCEPTION = ResourceManager.loadImage("images/exception.png"); - public static ImageIcon IMG_FRAME_ELEMENT = - ResourceManager.loadImage("images/StackFrameElement.png"); - public static ImageIcon IMG_STACK = ResourceManager.loadImage("images/StackFrame_Red.png"); - public static ImageIcon IMG_CAUSE = ResourceManager.loadImage("images/cause.png"); + public static Icon IMG_REPORT = new GIcon("icon.dialog.error.expandable.report"); + public static Icon IMG_EXCEPTION = new GIcon("icon.dialog.error.expandable.exception"); + public static Icon IMG_FRAME_ELEMENT = new GIcon("icon.dialog.error.expandable.frame"); + public static Icon IMG_STACK = new GIcon("icon.dialog.error.expandable.stack"); + public static Icon IMG_CAUSE = new GIcon("icon.dialog.error.expandable.cause"); private static final String SEND = "Send Report..."; private static final String DETAIL = "Details >>>"; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java b/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java index ab224f95fb..8252b8598a 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/GenericHeader.java @@ -29,16 +29,22 @@ import docking.action.DockingActionIf; import docking.util.AnimationUtils; import docking.widgets.VariableHeightPanel; import docking.widgets.label.GDLabel; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Java; +import generic.theme.GThemeDefaults.Colors.Palette; // TODO: should this be put into generic? public class GenericHeader extends JPanel { - private static final Color NON_FOCUS_START_COLOR = new Color(150, 150, 150); - private static final Color FOCUS_START_COLOR = new Color(30, 30, 150); + private static final Color NON_FOCUS_START_COLOR = new GColor("color.bg.header.inactive"); + private static final Color FOCUS_START_COLOR = new GColor("color.bg.header.active"); private static final int MINIMUM_TITLE_SIZE = 80; private Color nonFocusColor = NON_FOCUS_START_COLOR; private Color focusColor = FOCUS_START_COLOR; + private Color activeForeground = new GColor("color.fg.header.active"); + private Color inactiveForeground = new GColor("color.fg.header.inactive"); protected Component component; protected DockableToolBarManager toolBarMgr; @@ -68,7 +74,7 @@ public class GenericHeader extends JPanel { BorderLayout layout = new BorderLayout(); layout.setVgap(1); setLayout(layout); - setBorder(BorderFactory.createLineBorder(Color.GRAY)); + setBorder(BorderFactory.createLineBorder(Palette.GRAY)); setFocusable(false); titlePanel = new TitlePanel(); @@ -206,7 +212,7 @@ public class GenericHeader extends JPanel { private void constructMultiLinePanel() { removeAll(); - toolbar.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK)); + toolbar.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Java.BORDER)); add(toolbar, BorderLayout.SOUTH); add(titlePanel, BorderLayout.CENTER); add(menuCloseToolbar, BorderLayout.EAST); @@ -294,11 +300,7 @@ public class GenericHeader extends JPanel { TitleFlasher() { animator = PropertySetter.createAnimator(1000, this, "color", NON_FOCUS_START_COLOR, - NON_FOCUS_START_COLOR, Color.YELLOW, FOCUS_START_COLOR); - -// animator = -// PropertySetter.createAnimator(1000, this, "color", NON_FOCUS_START_COLOR, -// NON_FOCUS_START_COLOR, Color.YELLOW, FOCUS_START_COLOR); + NON_FOCUS_START_COLOR, Palette.YELLOW, FOCUS_START_COLOR); animator.setAcceleration(0.2f); animator.setDeceleration(0.8f); @@ -347,7 +349,7 @@ public class GenericHeader extends JPanel { setFocusable(false); titleLabel = new GDLabel(); titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 6, 0, 0)); - titleLabel.setForeground(Color.BLACK); + titleLabel.setForeground(Colors.FOREGROUND); titleLabel.setFocusable(false); add(titleLabel, BorderLayout.CENTER); } @@ -419,7 +421,7 @@ public class GenericHeader extends JPanel { */ void setSelected(boolean state) { isSelected = state; - titleLabel.setForeground(state ? Color.WHITE : Color.BLACK); + titleLabel.setForeground(state ? activeForeground : inactiveForeground); repaint(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/HeaderCursor.java b/Ghidra/Framework/Docking/src/main/java/docking/HeaderCursor.java index a5b03c1574..cf88ecc39c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/HeaderCursor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/HeaderCursor.java @@ -19,11 +19,20 @@ import java.awt.*; import java.awt.dnd.DragSource; import java.awt.image.BufferedImage; +import generic.theme.*; + /** * The cursor values used when drag-n-dropping dockable components */ public class HeaderCursor { + private static final GColor CURSOR_COLOR = new GColor("color.header.drag.cursor"); + private static final ThemeListener THEME_LISTENER = event -> { + if (event.isColorChanged(CURSOR_COLOR.getId())) { + initilizeCursors(); + } + }; + static Cursor LEFT; static Cursor RIGHT; static Cursor TOP; @@ -33,6 +42,12 @@ public class HeaderCursor { static Cursor NO_DROP = DragSource.DefaultMoveNoDrop; static { + initilizeCursors(); + + Gui.addThemeListener(THEME_LISTENER); + } + + private static void initilizeCursors() { Toolkit tk = Toolkit.getDefaultToolkit(); Image image = drawLeftArrow(); @@ -57,7 +72,7 @@ public class HeaderCursor { private static Image drawLeftArrow() { BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - int v = 0xff000000; + int v = CURSOR_COLOR.getRGB(); int y = 6; for (int i = 0; i < 6; i++) { for (int j = 0; j < 2 * i + 1; j++) { @@ -76,7 +91,7 @@ public class HeaderCursor { private static Image drawRightArrow() { BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - int v = 0xff000000; + int v = CURSOR_COLOR.getRGB(); int y = 6; for (int i = 0; i < 6; i++) { for (int j = 0; j < 2 * i + 1; j++) { @@ -95,7 +110,7 @@ public class HeaderCursor { private static Image drawTopArrow() { BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - int v = 0xff000000; + int v = CURSOR_COLOR.getRGB(); int x = 6; for (int i = 0; i < 6; i++) { for (int j = 0; j < 2 * i + 1; j++) { @@ -113,7 +128,7 @@ public class HeaderCursor { private static Image drawBottomArrow() { BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - int v = 0xff000000; + int v = CURSOR_COLOR.getRGB(); int x = 6; for (int i = 0; i < 6; i++) { for (int j = 0; j < 2 * i + 1; j++) { @@ -131,7 +146,7 @@ public class HeaderCursor { private static Image drawStack() { BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - int v = 0xff000000; + int v = CURSOR_COLOR.getRGB(); for (int i = 0; i < 3; i++) { int x = i * 3; int y = 6 - i * 3; @@ -149,10 +164,11 @@ public class HeaderCursor { private static Image drawNewWindow() { BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); - int v = 0xff000000; + int headerColor = new GColor("color.bg.header.active").getRGB(); + int v = CURSOR_COLOR.getRGB(); for (int i = 0; i < 5; i++) { for (int j = 0; j < 14; j++) { - image.setRGB(j, i, 0xff0000ff); + image.setRGB(j, i, headerColor); } } for (int i = 0; i < 14; i++) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java b/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java index 35d96ba10b..87dc4a7427 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java @@ -16,12 +16,11 @@ package docking; import javax.swing.Icon; -import javax.swing.ImageIcon; import docking.action.*; import docking.actions.AutoGeneratedDockingAction; import ghidra.util.HelpLocation; -import resources.ResourceManager; +import resources.Icons; /** * Action for showing components. If the component is hidden it will be made visible. @@ -31,8 +30,7 @@ class ShowComponentAction extends DockingAction implements AutoGeneratedDockingAction, Comparable { private static final int MAX_LENGTH = 40; - protected static final ImageIcon EMPTY_ICON = - ResourceManager.loadImage("images/EmptyIcon16.gif"); + protected static final Icon EMPTY_ICON = Icons.EMPTY_ICON; protected static final String MENU_WINDOW = "&" + DockingWindowManager.COMPONENT_MENU_NAME; protected DockingWindowManager winMgr; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ShowWindowAction.java b/Ghidra/Framework/Docking/src/main/java/docking/ShowWindowAction.java index ecc997bdf6..641f04ae5c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ShowWindowAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ShowWindowAction.java @@ -21,13 +21,13 @@ import docking.action.DockingAction; import docking.action.MenuData; import docking.actions.AutoGeneratedDockingAction; import docking.tool.ToolConstants; +import generic.theme.GIcon; import ghidra.util.HelpLocation; -import resources.ResourceManager; class ShowWindowAction extends DockingAction implements AutoGeneratedDockingAction, Comparable { - private static final Icon ICON = ResourceManager.loadImage("images/application_xp.png"); + private static final Icon ICON = new GIcon("icon.window"); private static final String MENU_WINDOW = "&" + DockingWindowManager.COMPONENT_MENU_NAME; private static final int MAX_LENGTH = 40; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/SplitPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/SplitPanel.java index 1e095352bd..9a3d9cea87 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/SplitPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/SplitPanel.java @@ -22,6 +22,8 @@ import java.awt.event.MouseMotionAdapter; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import generic.theme.GColor; + public class SplitPanel extends JPanel { private static int DIVIDER_SIZE = 4; private Component leftComp; @@ -38,7 +40,7 @@ public class SplitPanel extends JPanel { this.rightComp = rightComp; this.isHorizontal = isHorizontal; divider = new Divider(); - divider.setBackground(Color.LIGHT_GRAY); + divider.setBackground(new GColor("SplitPane.background")); add(leftComp); add(divider); add(rightComp); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/StatusBar.java b/Ghidra/Framework/Docking/src/main/java/docking/StatusBar.java index 0576a65e2e..9ed42d82cf 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/StatusBar.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/StatusBar.java @@ -30,6 +30,8 @@ import org.jdesktop.animation.timing.Animator; import docking.util.AnimationUtils; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDLabel; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.util.*; import ghidra.util.layout.HorizontalLayout; @@ -196,7 +198,7 @@ public class StatusBar extends JPanel { String updatedText = fixupMultilineText(text); statusLabel.setText(updatedText); statusLabel.setToolTipText(getToolTipText()); - statusLabel.setForeground(Color.BLACK); + statusLabel.setForeground(Colors.FOREGROUND); if (StringUtils.isBlank(updatedText)) { return; @@ -304,24 +306,40 @@ public class StatusBar extends JPanel { private FadeTimer() { super(5000, null); addActionListener(this); - initFadeColors(); } private void initFadeColors() { - fadeColorMap.put(Color.BLACK, new Color(16, 16, 16)); - fadeColorMap.put(new Color(16, 16, 16), new Color(32, 32, 32)); - fadeColorMap.put(new Color(32, 32, 32), new Color(64, 64, 64)); - fadeColorMap.put(new Color(64, 64, 64), new Color(80, 80, 80)); - fadeColorMap.put(new Color(80, 80, 80), new Color(96, 96, 96)); - fadeColorMap.put(new Color(96, 96, 96), new Color(112, 112, 112)); - fadeColorMap.put(new Color(112, 112, 112), new Color(128, 128, 128)); + + int value = 0; + int delta = 16; + if (Gui.isDarkTheme()) { + value = 128; + delta = -16; + } + + Color start = ColorUtils.getColor(value, value, value); + fadeColorMap.put(statusLabel.getForeground(), start); + + for (int i = 0; i < 8; i++) { + + Color from = ColorUtils.getColor(value, value, value); + value += delta; + Color to = ColorUtils.getColor(value, value, value); + fadeColorMap.put(from, to); + } + } + + @Override + public void restart() { + initFadeColors(); + super.restart(); } @Override public void actionPerformed(ActionEvent event) { Color nextFadeColor = fadeColorMap.get(statusLabel.getForeground()); - if (nextFadeColor != null) { + statusLabel.setForeground(nextFadeColor); } else { @@ -385,7 +403,7 @@ public class StatusBar extends JPanel { int red = color.getRed(); int green = color.getGreen(); int blue = color.getBlue(); - return new Color((255 - red), (255 - green), (255 - blue)); + return ColorUtils.getColor((255 - red), (255 - green), (255 - blue)); } private void contrastStatusLabelColors() { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/StatusBarSpacer.java b/Ghidra/Framework/Docking/src/main/java/docking/StatusBarSpacer.java index 10bb194fc8..1225e447e0 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/StatusBarSpacer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/StatusBarSpacer.java @@ -18,16 +18,16 @@ package docking; import javax.swing.Icon; import docking.widgets.label.GIconLabel; +import generic.theme.GIcon; import ghidra.framework.OperatingSystem; import ghidra.framework.Platform; -import resources.ResourceManager; /** * A class to handle the space requirements on the status bar that vary for different OSes. For * example, the Mac requires extra space on the status bar, due to the drag icon the Mac uses. */ public class StatusBarSpacer extends GIconLabel { - private static Icon EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon.gif"); + private static Icon EMPTY_ICON = new GIcon("icon.empty.20"); public StatusBarSpacer() { super( diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ComponentThemeInspectorAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ComponentThemeInspectorAction.java new file mode 100644 index 0000000000..a23b59e0b9 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ComponentThemeInspectorAction.java @@ -0,0 +1,273 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.action; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.swing.*; +import javax.swing.table.TableCellRenderer; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; + +import org.apache.commons.lang3.StringUtils; + +import docking.ActionContext; +import docking.DockingWindowManager; +import generic.util.action.ReservedKeyBindings; +import ghidra.util.Msg; + +public class ComponentThemeInspectorAction extends DockingAction { + + public ComponentThemeInspectorAction() { + super("Component Theme Inspector", DockingWindowManager.DOCKING_WINDOWS_OWNER, false); + createReservedKeyBinding(ReservedKeyBindings.COMPONENT_THEME_INFO_KEY); + + // System action; no help needed + DockingWindowManager.getHelpService().excludeFromHelp(this); + } + + private Object getMouseOverObject() { + + PointerInfo pointerInfo = MouseInfo.getPointerInfo(); + Point mouseLocation = pointerInfo.getLocation(); + Object lastObject = DockingWindowManager.getMouseOverObject(); + + if (!(lastObject instanceof Component)) { + return lastObject; + } + + Component c = (Component) lastObject; + Window w; + if (c instanceof Window) { + w = (Window) c; + } + else { + w = SwingUtilities.windowForComponent(c); + } + + if (w != null) { + + SwingUtilities.convertPointFromScreen(mouseLocation, w); + Component deepestComponent = + SwingUtilities.getDeepestComponentAt(w, mouseLocation.x, mouseLocation.y); + if (deepestComponent != null) { + return deepestComponent; + } + } + + return lastObject; + } + + @Override + public void actionPerformed(ActionContext context) { + + Object object = getMouseOverObject(); + if (!(object instanceof Component)) { + Msg.debug(this, "Mouse not over a component: " + object); + return; + } + + Entry entry = null; + Component component = (Component) object; + List tree = new ArrayList<>(); + while (component != null) { + + Entry next; + if (component instanceof JTable) { + next = new TableEntry((JTable) component); + } + else if (component instanceof JTree) { + next = new TreeEntry((JTree) component); + } + else { + next = new Entry(component); + } + + if (entry != null) { + entry.parent = next; + } + entry = next; + + tree.add(entry); + component = component.getParent(); + } + + Collections.reverse(tree); + + StringBuilder buffy = new StringBuilder("\n"); + for (int i = 0; i < tree.size() - 1; i++) { + Entry e = tree.get(i); + e.toString(buffy, i + 1); // +1 to start printing at 1, as an ordinal + } + + buffy.append('\n'); + Entry hoveredEntry = tree.get(tree.size() - 1); + hoveredEntry.toString(buffy, 0); // no indent for the hovered item so it is easy to see + buffy.append('\n'); + Msg.debug(this, buffy); + } + + private void print(StringBuilder buffy, Component component, int indent) { + + Color bg = component.getBackground(); + Color fg = component.getForeground(); + String id; + String clazz = component.getClass().getSimpleName(); + if (clazz.isEmpty()) { + clazz = component.getClass().getName(); + } + String name = component.getName(); + if (name == null) { + id = clazz; + } + else { + id = clazz + "; name = " + name; + } + + String indentMarker = ""; + String spacer = ""; + if (indent > 0) { + indentMarker = Integer.toString(indent) + ") "; + + String asString = Integer.toString(indent); + int length = asString.length(); + spacer = StringUtils.repeat(' ', length + 2); // +2 for the text ") " + } + else { + // no indent; custom spacing of attributes + spacer = "\t"; + } + + String tabs = '\n' + StringUtils.repeat(' ', (indent * 3)); + buffy.append(tabs) + .append(indentMarker) + .append(id) + .append(tabs) + .append(spacer) + .append("bg: ") + .append(bg) + .append(tabs) + .append(spacer) + .append("fg: ") + .append(fg) + .append('\n'); + } + + private void debugComponent(Component component) { + // stub for debugging + } + + private void debugTable(TableCellRenderer renderer, Component component, + Component rendererComponent) { + // stub for debugging + } + + @Override + public boolean isEnabledForContext(ActionContext context) { + return true; + } + + private class Entry { + + private Entry parent; + protected Component component; + protected Point mouseLocation; + + Entry(Component component) { + this.component = component; + + PointerInfo pointerInfo = MouseInfo.getPointerInfo(); + mouseLocation = pointerInfo.getLocation(); + SwingUtilities.convertPointFromScreen(mouseLocation, component); + } + + public void toString(StringBuilder buffy, int indent) { + debugComponent(component); + print(buffy, component, indent); + } + + protected boolean isLeaf(int indent) { + return indent == 0; + } + } + + private class TableEntry extends Entry { + private JTable table; + + TableEntry(JTable table) { + super(table); + this.table = table; + } + + @Override + public void toString(StringBuilder buffy, int indent) { + print(buffy, component, indent); + + if (!isLeaf(indent)) { + return; + } + + // print extra data for the leaf component, as that is the hovered component + int row = table.rowAtPoint(mouseLocation); + int col = table.columnAtPoint(mouseLocation); + + if (row != -1 && col != -1) { + TableCellRenderer renderer = table.getCellRenderer(row, col); + Component rendererComponent = table.prepareRenderer(renderer, row, col); + debugTable(renderer, component, rendererComponent); + + print(buffy, rendererComponent, indent); + } + } + } + + private class TreeEntry extends Entry { + private JTree tree; + + TreeEntry(JTree tree) { + super(tree); + this.tree = tree; + } + + @Override + public void toString(StringBuilder buffy, int indent) { + print(buffy, component, indent); + + if (!isLeaf(indent)) { + return; + } + + // print extra data for the leaf component, as that is the hovered component + TreeCellRenderer renderer = tree.getCellRenderer(); + int row = tree.getClosestRowForLocation(mouseLocation.x, mouseLocation.y); + + if (row != -1) { + TreePath path = tree.getPathForRow(row); + Object pathValue = path.getLastPathComponent(); + Component rendererComponent = + renderer.getTreeCellRendererComponent(tree, pathValue, tree.isRowSelected(row), + tree.isExpanded(row), tree.getModel().isLeaf(pathValue), row, + true); + + print(buffy, rendererComponent, indent); + } + } + + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java index f2e9140e5c..b3585703b7 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java @@ -24,7 +24,7 @@ import javax.swing.Action; import javax.swing.KeyStroke; import docking.*; -import ghidra.util.ReservedKeyBindings; +import generic.util.action.ReservedKeyBindings; import ghidra.util.exception.AssertException; /** diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusCycleAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusCycleAction.java index ea6b7b4695..4b24f27eef 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusCycleAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusCycleAction.java @@ -24,7 +24,7 @@ import org.apache.logging.log4j.Logger; import docking.ActionContext; import docking.DockingWindowManager; -import ghidra.util.ReservedKeyBindings; +import generic.util.action.ReservedKeyBindings; public class ShowFocusCycleAction extends DockingAction { static final Logger log = LogManager.getLogger(ShowFocusCycleAction.class); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusInfoAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusInfoAction.java index 806dcbd6fa..2c489bfc25 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusInfoAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ShowFocusInfoAction.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import docking.*; -import ghidra.util.ReservedKeyBindings; +import generic.util.action.ReservedKeyBindings; public class ShowFocusInfoAction extends DockingAction { static final Logger log = LogManager.getLogger(ShowFocusInfoAction.class); @@ -82,6 +82,7 @@ public class ShowFocusInfoAction extends DockingAction { Object mouseOverObject = DockingWindowManager.getMouseOverObject(); if (mouseOverObject instanceof Component) { log.info("Mouse-over Object: " + printComp((Component) mouseOverObject)); + log.info("Focusable?: " + ((Component) mouseOverObject).isFocusable()); } log.info(""); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java index 030ca16eb6..7e1a114377 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java @@ -27,9 +27,10 @@ import docking.KeyEntryTextField; import docking.action.*; import docking.tool.ToolConstants; import docking.widgets.label.GIconLabel; +import generic.theme.GThemeDefaults.Colors.Messages; +import generic.util.action.ReservedKeyBindings; import ghidra.util.HelpLocation; -import ghidra.util.ReservedKeyBindings; -import resources.ResourceManager; +import resources.Icons; /** * Dialog to set the key binding on an action; it is popped up when the F4 key @@ -69,7 +70,7 @@ public class KeyEntryDialog extends DialogComponentProvider { defaultPanel = new JPanel(new BorderLayout()); defaultPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 5)); - JLabel imageLabel = new GIconLabel(ResourceManager.loadImage("images/information.png")); + JLabel imageLabel = new GIconLabel(Icons.INFO_ICON); bgColor = imageLabel.getBackground(); JTextPane pane = new JTextPane(); pane.setBorder(BorderFactory.createEmptyBorder(0, 5, 2, 5)); @@ -172,7 +173,7 @@ public class KeyEntryDialog extends DialogComponentProvider { textAttrSet = new SimpleAttributeSet(); textAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); textAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - textAttrSet.addAttribute(StyleConstants.Foreground, Color.BLUE); + textAttrSet.addAttribute(StyleConstants.Foreground, Messages.NORMAL); tabAttrSet = new SimpleAttributeSet(); TabStop tabs = new TabStop(20, StyleConstants.ALIGN_LEFT, TabStop.LEAD_NONE); @@ -206,9 +207,7 @@ public class KeyEntryDialog extends DialogComponentProvider { String ksName = KeyBindingUtils.parseKeyStroke(ks); try { doc.insertString(0, "Actions mapped to " + ksName + "\n\n", textAttrSet); - for (int i = 0; i < list.size(); i++) { - DockingActionIf a = list.get(i); - + for (DockingActionIf a : list) { String collisionStr = "\t" + a.getName() + " (" + a.getOwnerDescription() + ")\n"; int offset = doc.getLength(); doc.insertString(offset, collisionStr, textAttrSet); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java index 7a7d2ebd00..171e2a20c3 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java @@ -32,6 +32,7 @@ import org.apache.commons.collections4.map.LazyMap; import docking.*; import docking.action.*; import docking.tool.util.DockingToolConstants; +import generic.util.action.ReservedKeyBindings; import ghidra.framework.options.*; import ghidra.util.*; import ghidra.util.exception.AssertException; @@ -99,6 +100,7 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener { if (SystemUtilities.isInDevelopmentMode()) { keyBindingsManager.addReservedAction(new ShowFocusInfoAction()); keyBindingsManager.addReservedAction(new ShowFocusCycleAction()); + keyBindingsManager.addReservedAction(new ComponentThemeInspectorAction()); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/AboutDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/AboutDialog.java index 14599e1452..58a7c14c2f 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/AboutDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/AboutDialog.java @@ -16,12 +16,14 @@ package docking.framework; import java.awt.BorderLayout; -import java.awt.Color; import javax.swing.*; import docking.DialogComponentProvider; import docking.DockingWindowManager; +import generic.theme.GThemeDefaults.Colors; +import ghidra.framework.Application; +import utility.application.ApplicationLayout; /** * Splash screen window to display version information about the current release of @@ -29,7 +31,6 @@ import docking.DockingWindowManager; * initialization is complete, the splash screen is dismissed. */ public class AboutDialog extends DialogComponentProvider { - private static final Color DEFAULT_BACKGROUND_COLOR = new Color(243, 250, 255); public AboutDialog() { super(ApplicationInformationDisplayFactory.createAboutTitle(), true, false, true, false); @@ -57,7 +58,7 @@ public class AboutDialog extends DialogComponentProvider { private JPanel createMainPanel() { JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.setBorder(BorderFactory.createRaisedBevelBorder()); - mainPanel.setBackground(DEFAULT_BACKGROUND_COLOR); + mainPanel.setBackground(Colors.BACKGROUND); mainPanel.add(createInfoComponent(), BorderLayout.CENTER); return mainPanel; } @@ -67,6 +68,10 @@ public class AboutDialog extends DialogComponentProvider { } public static void main(String[] args) throws Exception { + ApplicationLayout layout = new DockingApplicationLayout("About Dialog", "1.0"); + DockingApplicationConfiguration config = new DockingApplicationConfiguration(); + config.setShowSplashScreen(false); + Application.initializeApplication(layout, config); DockingWindowManager.showDialog(null, new AboutDialog()); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/ApplicationInformationDisplayFactory.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/ApplicationInformationDisplayFactory.java index 74e41a53f1..94d5a40d59 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/ApplicationInformationDisplayFactory.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/ApplicationInformationDisplayFactory.java @@ -23,14 +23,19 @@ import javax.swing.*; import docking.widgets.label.GIconLabel; import docking.widgets.label.GLabel; +import generic.theme.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.framework.Application; import ghidra.framework.PluggableServiceRegistry; import ghidra.util.HelpLocation; import ghidra.util.Msg; -import resources.ResourceManager; public class ApplicationInformationDisplayFactory { + private static final String ICON_HOME = "icon.docking.application.home"; + private static final String ICON_16 = "icon.docking.application.16"; + private static final String ICON_128 = "icon.docking.application.128"; + static { PluggableServiceRegistry.registerPluggableService( ApplicationInformationDisplayFactory.class, new ApplicationInformationDisplayFactory()); @@ -70,7 +75,7 @@ public class ApplicationInformationDisplayFactory { return bestImageSoFar; } - public static ImageIcon getHomeIcon() { + public static Icon getHomeIcon() { ApplicationInformationDisplayFactory factory = PluggableServiceRegistry.getPluggableService( ApplicationInformationDisplayFactory.class); return factory.doGetHomeIcon(); @@ -115,13 +120,12 @@ public class ApplicationInformationDisplayFactory { final JPanel panel = new JPanel(new BorderLayout()); panel.setPreferredSize(new Dimension(400, 400)); - Color background = Color.BLACK; - + Color background = new GColor("color.bg.splashscreen"); panel.setBackground(background); JLabel nameLabel = new GLabel(Application.getName()); - nameLabel.setForeground(new Color(155, 155, 155)); - Font newFont = new Font("Garamond", Font.BOLD, 35); + nameLabel.setForeground(Palette.GRAY); + Font newFont = Gui.getFont("font.splash.header.default"); nameLabel.setFont(newFont); nameLabel.setHorizontalAlignment(SwingConstants.CENTER); nameLabel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); @@ -139,14 +143,14 @@ public class ApplicationInformationDisplayFactory { return panel; } - protected ImageIcon getSplashScreenIcon128() { - return ResourceManager.loadImage("images/www_128.png"); + protected Icon getSplashScreenIcon128() { + return new GIcon(ICON_128); } protected List doGetWindowIcons() { List list = new ArrayList<>(); - list.add(ResourceManager.loadImage("images/www_128.png").getImage()); - list.add(ResourceManager.loadImage("images/www_16.png").getImage()); + list.add(new GIcon(ICON_128).getImageIcon().getImage()); + list.add(new GIcon(ICON_16).getImageIcon().getImage()); return list; } @@ -158,8 +162,8 @@ public class ApplicationInformationDisplayFactory { return null; } - protected ImageIcon doGetHomeIcon() { - return ResourceManager.loadImage("images/www_16.png"); + protected Icon doGetHomeIcon() { + return new GIcon(ICON_HOME); } protected Runnable doGetHomeCallback() { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationConfiguration.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationConfiguration.java index aa57f15fe5..fef37b3cf4 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationConfiguration.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationConfiguration.java @@ -17,7 +17,8 @@ package docking.framework; import docking.DockingErrorDisplay; import docking.widgets.PopupKeyStorePasswordProvider; -import ghidra.docking.util.DockingWindowsLookAndFeelUtils; +import generic.theme.ApplicationThemeManager; +import ghidra.docking.util.LookAndFeelUtils; import ghidra.framework.ApplicationConfiguration; import ghidra.net.ApplicationKeyManagerFactory; import ghidra.util.ErrorDisplay; @@ -48,14 +49,15 @@ public class DockingApplicationConfiguration extends ApplicationConfiguration { protected void initializeApplication() { super.initializeApplication(); - DockingWindowsLookAndFeelUtils.loadFromPreferences(); + ApplicationThemeManager.initialize(); + LookAndFeelUtils.performPlatformSpecificFixups(); if (showSplashScreen) { SplashScreen.showSplashScreen(); } - ApplicationKeyManagerFactory.setKeyStorePasswordProvider( - new PopupKeyStorePasswordProvider()); + ApplicationKeyManagerFactory + .setKeyStorePasswordProvider(new PopupKeyStorePasswordProvider()); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java index d169142e32..ce42b87d9f 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java @@ -15,12 +15,16 @@ */ package docking.framework; +import java.io.File; import java.io.FileNotFoundException; -import java.util.Collection; -import java.util.Objects; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import generic.jar.ResourceFile; import ghidra.framework.ApplicationProperties; +import ghidra.framework.GModule; import ghidra.util.SystemUtilities; import util.CollectionUtils; import utility.application.ApplicationLayout; @@ -36,6 +40,10 @@ public class DockingApplicationLayout extends ApplicationLayout { private static final String NO_RELEASE_NAME = "NO_RELEASE"; + /** Dev mode main source bin dir pattern */ + private static final Pattern CLASS_PATH_MODULE_NAME_PATTERN = + Pattern.compile(".*/(\\w+)/bin/main"); + /** * Constructs a new docking application layout object with the given name and version. * @@ -74,6 +82,7 @@ public class DockingApplicationLayout extends ApplicationLayout { this.applicationProperties = Objects.requireNonNull(applicationProperties); this.applicationRootDirs = applicationRootDirs; + applicationRootDirs.addAll(getAdditionalApplicationRootDirs(applicationRootDirs)); // Application installation directory applicationInstallationDir = applicationRootDirs.iterator().next().getParentFile(); @@ -102,6 +111,53 @@ public class DockingApplicationLayout extends ApplicationLayout { applicationInstallationDir); } + protected Collection getAdditionalApplicationRootDirs( + Collection roots) { + return Collections.emptyList(); + } + + protected Map findModules() { + if (!SystemUtilities.isInDevelopmentMode()) { + // in release mode we only have one application root, so no need to find all others + return ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs); + } + + // In development mode we may have multiple module root directories under which modules may + // be found. Search all roots for modules. + Collection roots = + ModuleUtilities.findModuleRootDirectories(applicationRootDirs, new ArrayList<>()); + Map allModules = ModuleUtilities.findModules(applicationRootDirs, roots); + + // Filter any modules found to ensure that we only include those that are listed on the + // classpath. (Due to the nature of how the development classpath is created, not all + // found modules may match the classpath entries.) + Set cpNames = getClassPathModuleNames(); + Map filteredModules = new HashMap<>(); + Set > entrySet = allModules.entrySet(); + for (Entry entry : entrySet) { + GModule module = entry.getValue(); + if (cpNames.contains(module.getName())) { + filteredModules.put(entry.getKey(), module); + } + } + + return filteredModules; + } + + private Set getClassPathModuleNames() { + String cp = System.getProperty("java.class.path"); + String[] pathParts = cp.split(File.pathSeparator); + Set paths = new HashSet<>(Arrays.asList(pathParts)); + Set cpNames = new HashSet<>(); + for (String cpEntry : paths) { + Matcher matcher = CLASS_PATH_MODULE_NAME_PATTERN.matcher(cpEntry); + if (matcher.matches()) { + cpNames.add(matcher.group(1)); + } + } + return cpNames; + } + /** * Get the default list of Application directories. In repo-based * development mode this includes the root Ghidra directory within each repo. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/SplashScreen.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/SplashScreen.java index 6deff243de..a3c3a99b74 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/SplashScreen.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/SplashScreen.java @@ -24,7 +24,8 @@ import javax.swing.border.BevelBorder; import docking.*; import docking.widgets.label.GDLabel; -import docking.widgets.label.GLabel; +import generic.theme.GColor; +import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.framework.Application; import ghidra.util.Msg; @@ -37,7 +38,9 @@ import utility.application.ApplicationLayout; */ public class SplashScreen extends JWindow { - private static final Color DEFAULT_BACKGROUND_COLOR = new Color(243, 250, 255); + private static final Color BG_COLOR = new GColor("color.bg.splashscreen"); + + private static final String FONT_ID = "font.splash.status"; private static SplashScreen splashWindow; // splash window displayed while ghidra is coming up private static DockingFrame hiddenFrame; @@ -250,7 +253,7 @@ public class SplashScreen extends JWindow { List list = ApplicationInformationDisplayFactory.getWindowIcons(); hiddenFrame.setIconImages(list); hiddenFrame.setUndecorated(true); - hiddenFrame.setTransient(); + hiddenFrame.setTransient(); } return hiddenFrame; } @@ -286,8 +289,7 @@ public class SplashScreen extends JWindow { private JPanel createMainPanel() { JPanel mainPanel = new JPanel(new BorderLayout()); - mainPanel.setBackground(DEFAULT_BACKGROUND_COLOR); - mainPanel.add(createTitlePanel(), BorderLayout.NORTH); + mainPanel.setBackground(BG_COLOR); mainPanel.add(createContentPanel(), BorderLayout.CENTER); return mainPanel; } @@ -300,38 +302,12 @@ public class SplashScreen extends JWindow { return contentPanel; } - private Component createTitlePanel() { - Color backgroundColor = UIManager.getColor("InternalFrame.activeTitleBackground"); - Color foregroundColor = UIManager.getColor("InternalFrame.activeTitleForeground"); - - JPanel titlePanel = new JPanel(); - if (backgroundColor == null) { - backgroundColor = new Color(0, 0, 255); - } - titlePanel.setBackground(backgroundColor); - titlePanel.setLayout(new BorderLayout()); - - JLabel titleLabel = - new GLabel(ApplicationInformationDisplayFactory.createSplashScreenTitle()); - Font font = titleLabel.getFont(); - font = new Font(font.getName(), Font.BOLD, 11); - titleLabel.setFont(font); - if (foregroundColor == null) { - foregroundColor = Color.white; - } - titleLabel.setForeground(foregroundColor); - titlePanel.add(titleLabel, BorderLayout.CENTER); - titlePanel.setBorder(BorderFactory.createEmptyBorder(2, 10, 2, 10)); - return titlePanel; - } - private Component createStatusComponent() { - Font f = new Font("serif", Font.BOLD, 12); statusLabel = new GDLabel(" Loading..."); - statusLabel.setFont(f); + Gui.registerFont(statusLabel, FONT_ID); + statusLabel.setFont(Gui.getFont(FONT_ID)); statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 2, 10)); - statusLabel.setBackground(DEFAULT_BACKGROUND_COLOR); statusLabel.setOpaque(true); return statusLabel; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java b/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java index 04d8054c5d..7049358cdf 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java @@ -37,6 +37,7 @@ import org.jdesktop.animation.timing.TimingTargetAdapter; import docking.framework.ApplicationInformationDisplayFactory; import docking.util.AnimationPainter; import docking.util.AnimationUtils; +import generic.theme.GColor; import ghidra.framework.preferences.Preferences; import ghidra.util.Msg; import ghidra.util.Swing; @@ -398,7 +399,7 @@ public class DockingHelpBroker extends GHelpBroker { private class LocationHintPainter implements AnimationPainter { - private Color color = new Color(100, 100, 255, 100); + private Color color = new GColor("color.bg.help.hint"); private Shape paintShape; LocationHintPainter(Shape paintShape) { @@ -450,11 +451,11 @@ public class DockingHelpBroker extends GHelpBroker { /* // Debug Shape box = scaler.createTransformedShape(b); - g2d.setColor(Color.GREEN); + g2d.setColor(Palette.GREEN); g2d.fill(box); - + box = transform.createTransformedShape(box); - g2d.setColor(Color.YELLOW); + g2d.setColor(Palette.YELLOW); g2d.fill(box); */ diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java b/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java index dc3678c550..350cefd820 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java @@ -28,7 +28,6 @@ import java.util.Map.Entry; import javax.help.*; import javax.help.Map.ID; import javax.swing.JButton; -import javax.swing.UIManager; import docking.ComponentProvider; import docking.action.DockingActionIf; @@ -52,6 +51,12 @@ import utilities.util.reflection.ReflectionUtilities; */ public class HelpManager implements HelpService { + /** + * The hardcoded value to use for all HelpSet 'home id' values. Subclasses may change this + * value by overriding {@link #getHomeId()}. + */ + private static final String HOME_ID = "Misc_Help_Contents"; + public static final String SHOW_AID_KEY = "SHOW.HELP.NAVIGATION.AID"; private static final String TABLE_OF_CONTENTS_FILENAME_KEY = "data"; @@ -85,11 +90,10 @@ public class HelpManager implements HelpService { */ protected HelpManager(URL url) throws HelpSetException { mainHS = new DockingHelpSet(new GHelpClassLoader(null), url); + mainHS.setHomeID(getHomeId()); mainHB = mainHS.createHelpBroker(); mainHS.setTitle(GHIDRA_HELP_TITLE); - setColorResources(); - isValidHelp = isValidHelp(); } @@ -124,6 +128,15 @@ public class HelpManager implements HelpService { } } + /** + * Returns the 'home id' to be used by all help sets in the system (as opposed to allowing each + * help set to define its own home id. + * @return the home id + */ + protected String getHomeId() { + return HOME_ID; + } + @Override public void excludeFromHelp(Object helpObject) { excludedFromHelp.add(helpObject); @@ -195,6 +208,18 @@ public class HelpManager implements HelpService { return mainHS; } + @Override + public void reload() { + + if (!(mainHB instanceof GHelpBroker)) { + // not our broker installed; can't force a reload + return; + } + + GHelpBroker gHelpBroker = (GHelpBroker) mainHB; + gHelpBroker.reload(); + } + @Override public void showHelp(URL url) { if (!isValidHelp) { @@ -686,21 +711,13 @@ public class HelpManager implements HelpService { private HelpSet createHelpSet(URL url, GHelpClassLoader classLoader) throws HelpSetException { if (!urlToHelpSets.containsKey(url)) { GHelpSet hs = new GHelpSet(classLoader, url); + hs.setHomeID(getHomeId()); urlToHelpSets.put(url, hs); return hs; } return null; } - /** - * Set the color resources on the JEditorPane for selection so that - * you can see the highlights when you do a search in the JavaHelp. - */ - private void setColorResources() { - UIManager.put("EditorPane.selectionBackground", new Color(204, 204, 255)); - UIManager.put("EditorPane.selectionForeground", UIManager.get("EditorPane.foreground")); - } - private void displayHelpInfo(Object helpObj, HelpLocation loc, Window parent) { String msg = getHelpInfo(helpObj, loc); Msg.showInfo(this, parent, "Help Info", msg); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/ToggleNavigationAid.java b/Ghidra/Framework/Docking/src/main/java/docking/help/ToggleNavigationAid.java index 5af1ff1b19..8bd568c358 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/ToggleNavigationAid.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/help/ToggleNavigationAid.java @@ -21,6 +21,7 @@ import java.awt.event.ActionEvent; import javax.swing.*; +import generic.theme.GIcon; import ghidra.framework.preferences.Preferences; import resources.MultiIcon; import resources.ResourceManager; @@ -29,9 +30,9 @@ import resources.icons.TranslateIcon; public class ToggleNavigationAid extends AbstractAction { - private static final Icon ENABLED_ICON = - ResourceManager.loadImage("images/software-update-available.png"); - private static final Icon CANCEL_ICON = ResourceManager.loadImage("images/dialog-cancel.png"); + private static final Icon ENABLED_ICON = new GIcon("icon.help.navigation.aid.enabled"); + private static final Icon DISABLED_OVERLAY_ICON = + new GIcon("icon.help.navigation.aid.disabled.overlay"); private static Icon DISABLED_ICON; private boolean showingNavigationAid = true; @@ -44,7 +45,7 @@ public class ToggleNavigationAid extends AbstractAction { "when navigating within the help system"); TranslateIcon translatedIcon = - new CenterTranslateIcon(CANCEL_ICON, ENABLED_ICON.getIconWidth()); + new CenterTranslateIcon(DISABLED_OVERLAY_ICON, ENABLED_ICON.getIconWidth()); ImageIcon disabledBaseIcon = ResourceManager.getDisabledIcon(ENABLED_ICON, 50); DISABLED_ICON = new MultiIcon(disabledBaseIcon, translatedIcon); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingToolBarUtils.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingToolBarUtils.java index 9db8af21b1..f5601a1ae2 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingToolBarUtils.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/DockingToolBarUtils.java @@ -24,7 +24,7 @@ import javax.swing.KeyStroke; import org.apache.commons.lang3.StringUtils; import docking.action.DockingActionIf; -import ghidra.docking.util.DockingWindowsLookAndFeelUtils; +import ghidra.docking.util.LookAndFeelUtils; import ghidra.util.StringUtilities; class DockingToolBarUtils { @@ -96,7 +96,7 @@ class DockingToolBarUtils { builder.append(InputEvent.getModifiersExText(modifiers)); // The Aqua LaF does not use the '+' symbol between modifiers - if (!DockingWindowsLookAndFeelUtils.isUsingAquaUI(button.getUI())) { + if (!LookAndFeelUtils.isUsingAquaUI(button.getUI())) { builder.append('+'); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java index 8a68fcbd11..6492259535 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/MultipleActionDockingToolbarButton.java @@ -30,6 +30,7 @@ import docking.*; import docking.action.*; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDHtmlLabel; +import generic.theme.GThemeDefaults.Colors; import ghidra.util.Swing; import resources.ResourceManager; @@ -52,7 +53,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton { public MultipleActionDockingToolbarButton(MultiActionDockingActionIf action) { multipleAction = action; installMouseListeners(); - setIcon(ResourceManager.loadImage("images/core.png")); + setIcon(ResourceManager.getDefaultIcon()); } @Override @@ -96,6 +97,16 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton { popupContext = createPopupContext(); } + @Override + public void updateUI() { + + removeMouseListener(popupListener); + + super.updateUI(); + + installMouseListeners(); + } + private void installMouseListeners() { MouseListener[] mouseListeners = getMouseListeners(); for (MouseListener mouseListener : mouseListeners) { @@ -251,7 +262,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton { return; // shouldn't happen } - g.setColor(Color.BLACK); + g.setColor(Colors.FOREGROUND); int iconWidth = baseIcon.getIconWidth(); int iconHeight = baseIcon.getIconHeight(); int insetsPadding = insets.left + insets.right; // the insets of the left icon and the arrow (between the two) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ButtonPanelFactory.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ButtonPanelFactory.java index 09c79c7a62..68147cd3fe 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ButtonPanelFactory.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ButtonPanelFactory.java @@ -20,6 +20,7 @@ import java.awt.*; import javax.swing.*; import javax.swing.border.Border; +import generic.theme.GThemeDefaults.Colors; import resources.ResourceManager; /** @@ -99,7 +100,7 @@ public class ButtonPanelFactory { public final static Icon BROWSE_ICON = new Icon() { @Override public void paintIcon(Component c, Graphics g, int x, int y) { - g.setColor(Color.BLACK); + g.setColor(Colors.FOREGROUND); g.fillRect(x, y + 5, 2, 2); g.fillRect(x + 4, y + 5, 2, 2); g.fillRect(x + 8, y + 5, 2, 2); @@ -115,10 +116,6 @@ public class ButtonPanelFactory { return 10; } }; - /** - * Font for the browse button label. - */ - public final static Font BROWSE_FONT = new Font("Dialog", Font.BOLD, 12); /** * internal values used when creating the panels and buttons diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorEditor.java index c3b5e8cfaf..7f8ae726cd 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorEditor.java @@ -21,31 +21,27 @@ import java.awt.event.MouseEvent; import java.beans.PropertyEditorSupport; import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import docking.DialogComponentProvider; import docking.DockingWindowManager; import docking.widgets.label.GDHtmlLabel; +import generic.theme.GThemeDefaults.Colors.Palette; +import ghidra.util.ColorUtils; +import ghidra.util.WebColors; /** - * Color editor that uses the JColorChooser. + * Color editor that is a bit unusual in that its custom component is a button that when pushed, + * pops up a dialog for editing the color. Use {@link ColorPropertyEditor} for a more traditional + * property editor that returns a direct color editing component. */ public class ColorEditor extends PropertyEditorSupport { - private static final String LIGHT_COLOR = "SILVER"; - private static final String DARK_COLOR = "BLACK"; - private static GhidraColorChooser colorChooser; private JLabel previewLabel = new GDHtmlLabel(); private Color color; private Color lastUserSelectedColor; - /** - * The default constructor. - * - */ public ColorEditor() { previewLabel.setOpaque(true); previewLabel.setPreferredSize(new Dimension(100, 20)); @@ -72,42 +68,16 @@ public class ColorEditor extends PropertyEditorSupport { DockingWindowManager.showDialog(previewLabel, provider); } - /** - * A PropertyEditor may chose to make available a full custom Component - * that edits its property value. It is the responsibility of the - * PropertyEditor to hook itself up to its editor Component itself and - * to report property value changes by firing a PropertyChange event. - * - * The higher-level code that calls getCustomEditor may either embed - * the Component in some larger property sheet, or it may put it in - * its own individual dialog, or ... - * - * @return A java.awt.Component that will allow a human to directly - * edit the current property value. May be null if this is - * not supported. - */ @Override public Component getCustomEditor() { return previewLabel; } - /** - * Determines whether the propertyEditor can provide a custom editor. - * - * @return True if the propertyEditor can provide a custom editor. - */ @Override public boolean supportsCustomEditor() { return true; } - /** - * Set (or change) the object that is to be edited. - * @param value The new target object to be edited. Note that this - * object should not be modified by the PropertyEditor, rather - * the PropertyEditor should create a new object to hold any - * modified value. - */ @Override public void setValue(Object value) { color = (Color) value; @@ -116,61 +86,37 @@ public class ColorEditor extends PropertyEditorSupport { } private void updateColor(Color newColor) { - String colorString = LIGHT_COLOR; // change the color to a darker value if the color being set is light - int colorValue = newColor.getRed() + newColor.getGreen() + newColor.getBlue(); - if (colorValue > 400) { // arbitrary threshold determined by trial-and-error - colorString = DARK_COLOR; - } - + String colorString = WebColors.toString(ColorUtils.contrastForegroundColor(newColor)); previewLabel.setText( "
click "); previewLabel.setBackground(color); } - /** - * Get the value. - */ @Override public Object getValue() { return color; } - /** - * Return true which this editor can paint its property value. - */ @Override public boolean isPaintable() { return false; } - /** - * Paint a representation of the value into a given area of screen - * real estate. Note that the propertyEditor is responsible for doing - * its own clipping so that it fits into the given rectangle. - *- * If the PropertyEditor doesn't honor paint requests (see isPaintable) - * this method should be a silent noop. - * - * @param gfx Graphics object to paint into. - * @param box Rectangle within graphics object into which we should paint. - */ @Override public void paintValue(Graphics gfx, Rectangle box) { if (color != null) { gfx.setColor(color); } else { - gfx.setColor(Color.black); + gfx.setColor(Palette.BLACK); } gfx.fillRect(box.x, box.y, box.width, box.height); } - ///////////////////////////////////////////////////////////////////////// - - class EditorProvider extends DialogComponentProvider { + private class EditorProvider extends DialogComponentProvider { EditorProvider(JPanel contentPanel) { super("Color Editor", true); @@ -186,7 +132,7 @@ public class ColorEditor extends PropertyEditorSupport { } } - class ColorEditorPanel extends JPanel { + private class ColorEditorPanel extends JPanel { ColorEditorPanel() { @@ -197,15 +143,12 @@ public class ColorEditor extends PropertyEditorSupport { } add(colorChooser, BorderLayout.CENTER); - colorChooser.getSelectionModel().addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - lastUserSelectedColor = colorChooser.getColor(); - // This could be a ColorUIResource, but Options only support storing Color. - lastUserSelectedColor = - new Color(lastUserSelectedColor.getRed(), lastUserSelectedColor.getGreen(), - lastUserSelectedColor.getBlue(), lastUserSelectedColor.getAlpha()); - } + colorChooser.getSelectionModel().addChangeListener(e -> { + + // This could be a ColorUIResource, but Options only support storing Color. So, + // manually create a new Color object to avoid saving a ColorUIResource. + Color c = colorChooser.getColor(); + lastUserSelectedColor = ColorUtils.getColor(c.getRGB()); }); colorChooser.setColor(color); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java new file mode 100644 index 0000000000..7fb6a09f39 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java @@ -0,0 +1,68 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.options.editor; + +import java.awt.Color; +import java.awt.Component; +import java.beans.PropertyEditorSupport; +import java.util.Objects; + +import ghidra.util.Swing; + +/** + * Property Editor for Colors. Uses a {@link GhidraColorChooser} as its custom component + */ +public class ColorPropertyEditor extends PropertyEditorSupport { + + private GhidraColorChooser colorChooser; + + private void colorChanged() { + // run later - allows debugging without hanging the UI in some environments + Swing.runLater(() -> setValue(colorChooser.getColor())); + } + + @Override + public Component getCustomEditor() { + if (colorChooser != null) { + return colorChooser; + } + + colorChooser = new GhidraColorChooser(); + colorChooser.getSelectionModel().addChangeListener(e -> colorChanged()); + return colorChooser; + } + + public void saveState() { + if (colorChooser != null) { + colorChooser.addColorToHistory(colorChooser.getColor()); + } + } + + @Override + public boolean supportsCustomEditor() { + return true; + } + + @Override + public void setValue(Object value) { + if (colorChooser != null) { + colorChooser.setColor((Color) value); + } + if (!Objects.equals(value, getValue())) { + super.setValue(value); + } + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/EditorInitializer.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/EditorInitializer.java index c0940375c5..2eb5a320eb 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/EditorInitializer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/EditorInitializer.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +30,7 @@ public class EditorInitializer implements ModuleInitializer { public void run() { PropertyEditorManager.registerEditor(String.class, StringEditor.class); PropertyEditorManager.registerEditor(Color.class, ColorEditor.class); - PropertyEditorManager.registerEditor(Font.class, FontPropertyEditor.class); + PropertyEditorManager.registerEditor(Font.class, FontEditor.class); PropertyEditorManager.registerEditor(Enum.class, EnumEditor.class); PropertyEditorManager.registerEditor(Boolean.class, BooleanEditor.class); PropertyEditorManager.registerEditor(Date.class, DateEditor.class); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FileChooserEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FileChooserEditor.java index 7362459aaf..82d3a743f6 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FileChooserEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FileChooserEditor.java @@ -16,7 +16,6 @@ package docking.options.editor; import java.awt.Component; -import java.awt.Font; import java.awt.event.MouseListener; import java.beans.PropertyEditorSupport; import java.io.File; @@ -107,9 +106,6 @@ public class FileChooserEditor extends PropertyEditorSupport { textField.setText(currentFileValue != null ? currentFileValue.getAbsolutePath() : ""); browseButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE); - Font f = browseButton.getFont(); - f = new Font(f.getName(), Font.BOLD, f.getSize()); - browseButton.setFont(f); add(textField); add(Box.createHorizontalStrut(5)); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontEditor.java new file mode 100644 index 0000000000..b44509de46 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontEditor.java @@ -0,0 +1,111 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.options.editor; + +import java.awt.*; +import java.beans.PropertyEditorSupport; +import java.util.Objects; + +import javax.swing.*; + +import docking.DialogComponentProvider; +import docking.DockingWindowManager; + +/** + * Font property editor that is a bit unusual in that its custom component is a button that when + * pushed, pops up a dialog for editing the color. Use {@link FontPropertyEditor} for a more + * traditional property editor that returns a direct color editing component. + */ + +public class FontEditor extends PropertyEditorSupport { + private JButton previewButton; + private FontPropertyEditor fontPropertyEditor; + + public FontEditor() { + previewButton = new JButton(FontPropertyEditor.SAMPLE_STRING); + previewButton.addActionListener(e -> buttonPushed()); + fontPropertyEditor = new FontPropertyEditor(); + fontPropertyEditor.addPropertyChangeListener(ev -> fontChanged()); + } + + private void buttonPushed() { + showDialog(); + previewButton.setFont((Font) getValue()); + } + + /** + * Convenience method for directly showing a dialog for editing fonts + */ + public void showDialog() { + EditorDialogProvider provider = new EditorDialogProvider(); + DockingWindowManager.showDialog(previewButton, provider); + previewButton.repaint(); + } + + @Override + public void setValue(Object o) { + if (Objects.equals(o, getValue())) { + return; + } + Font font = (Font) o; + previewButton.setFont(font); + fontPropertyEditor.setValue(font); + super.setValue(font); + } + + @Override + public boolean supportsCustomEditor() { + return true; + } + + @Override + public Component getCustomEditor() { + return previewButton; + } + + private void fontChanged() { + Font font = (Font) fontPropertyEditor.getValue(); + setValue(font); + } + + class EditorDialogProvider extends DialogComponentProvider { + private Font originalFont = (Font) getValue(); + + EditorDialogProvider() { + super("Font Editor", true); + addWorkPanel(buildWorkPanel()); + addOKButton(); + addCancelButton(); + } + + private JComponent buildWorkPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(fontPropertyEditor.getCustomEditor()); + return panel; + } + + @Override + protected void okCallback() { + close(); + } + + @Override + protected void cancelCallback() { + setValue(originalFont); + close(); + } + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java index 017ad8fca5..3af96b8769 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java @@ -16,74 +16,31 @@ package docking.options.editor; import java.awt.*; -import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyEditorSupport; -import java.util.ArrayList; -import java.util.Collections; +import java.util.*; import java.util.List; -import java.util.stream.IntStream; +import java.util.stream.*; import javax.swing.*; -import docking.DialogComponentProvider; -import docking.DockingWindowManager; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GDLabel; +import ghidra.util.Swing; /** - * This Bean FontEditor displays a String with the current selected font name, - * style and size attributes. + * Property Editor for editing {@link Font}s */ public class FontPropertyEditor extends PropertyEditorSupport { - private Font font; -// private JLabel previewLabel = new GDLabel(); - private final static String SAMPLE_STRING = "ABCabc \u00a9\u00ab\u00a7\u0429\u05d1\u062c\u4eb9"; - private JButton previewButton = new JButton(SAMPLE_STRING); + public final static String SAMPLE_STRING = "ABCabc \u00a9\u00ab\u00a7\u0429\u05d1\u062c\u4eb9"; - /** - * The default constructor. - * - */ - public FontPropertyEditor() { - - previewButton.addActionListener(e -> { - // show the editor to get the user value - showDialog(); - - // now set the new value - previewButton.setFont(font); - }); - -// previewLabel.addMouseListener( new MouseAdapter() { -// @Override -// public void mouseClicked( MouseEvent evt ) { -// // show the editor to get the user value -// showDialog(); -// -// // now set the new value -// previewLabel.setFont( font ); -// } -// } ); - } - - public void showDialog() { - EditorProvider provider = new EditorProvider(new FontPanel()); - DockingWindowManager.showDialog(previewButton, provider); - previewButton.repaint(); - } + private FontChooserPanel fontChooserPanel; @Override - public void setValue(Object o) { - font = (Font) o; - previewButton.setFont(font); - - // set the font values on the widget - } - - @Override - public Object getValue() { - return font; + public Component getCustomEditor() { + fontChooserPanel = new FontChooserPanel(); + fontChooserPanel.updateControls((Font) getValue()); + return fontChooserPanel; } @Override @@ -92,205 +49,221 @@ public class FontPropertyEditor extends PropertyEditorSupport { } @Override - public Component getCustomEditor() { - return previewButton; + public void setValue(Object value) { + if (fontChooserPanel != null) { + fontChooserPanel.updateControls((Font) value); + } + if (!Objects.equals(value, getValue())) { + super.setValue(value); + } } -//================================================================================================== -// Inner Classes -//================================================================================================== + class FontChooserPanel extends JPanel { - private class FontPanel extends JPanel implements ActionListener { - JLabel fontLabel, sizeLabel, styleLabel; - JLabel fontStringLabel; - JComboBox
fonts; - JComboBox sizes; - JComboBox styles; - int styleChoice; - int sizeChoice; + private GDLabel previewLabel; + private GComboBox fontCombo; + private GComboBox sizeCombo; + private GComboBox styleCombo; + private ActionListener actionListener = e -> fontChanged(); + private List systemFontNames; - FontPanel() { - init(); + public FontChooserPanel() { + build(); } - public void init() { - this.setLayout(new BorderLayout()); - - JPanel topPanel = new JPanel(); - JPanel fontPanel = new JPanel(); - JPanel sizePanel = new JPanel(); - JPanel stylePanel = new JPanel(); - JPanel sizeAndStylePanel = new JPanel(); - - topPanel.setLayout(new BorderLayout()); - fontPanel.setLayout(new GridLayout(2, 1)); - sizePanel.setLayout(new GridLayout(2, 1)); - stylePanel.setLayout(new GridLayout(2, 1)); - sizeAndStylePanel.setLayout(new BorderLayout()); - - topPanel.add(BorderLayout.WEST, fontPanel); - sizeAndStylePanel.add(BorderLayout.WEST, sizePanel); - sizeAndStylePanel.add(BorderLayout.CENTER, stylePanel); - topPanel.add(BorderLayout.CENTER, sizeAndStylePanel); - - fontStringLabel = new GDLabel(FontPropertyEditor.SAMPLE_STRING); - fontStringLabel.setPreferredSize(new Dimension(350, 50)); - fontStringLabel.setHorizontalAlignment(SwingConstants.CENTER); - fontStringLabel.setFont(font); - topPanel.add(BorderLayout.SOUTH, fontStringLabel); - - add(BorderLayout.NORTH, topPanel); - - fontLabel = new GDLabel("Fonts"); - Font newFont = getFont().deriveFont(1); - fontLabel.setFont(newFont); - fontLabel.setHorizontalAlignment(SwingConstants.CENTER); - fontPanel.add(fontLabel); - - sizeLabel = new GDLabel("Sizes"); - sizeLabel.setFont(newFont); - sizeLabel.setHorizontalAlignment(SwingConstants.CENTER); - sizePanel.add(sizeLabel); - - styleLabel = new GDLabel("Styles"); - styleLabel.setFont(newFont); - styleLabel.setHorizontalAlignment(SwingConstants.CENTER); - stylePanel.add(styleLabel); - - GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); - - String envfonts[] = gEnv.getAvailableFontFamilyNames(); - List list = new ArrayList<>(envfonts.length); - for (String envfont : envfonts) { - list.add(new FontWrapper(envfont)); + public void updateControls(Font font) { + if (font == null) { + return; } - Collections.sort(list); - fonts = new GComboBox<>(list.toArray(new FontWrapper[envfonts.length])); - fonts.setMaximumRowCount(9); + updatePreviewLabel(font); + + fontCombo.removeActionListener(actionListener); + sizeCombo.removeActionListener(actionListener); + styleCombo.removeActionListener(actionListener); + FontWrapper fontWrapper = new FontWrapper(font.getName()); - fontPanel.add(fonts); - fonts.setSelectedItem(fontWrapper); + updateComboBoxModeIfNeeded(fontWrapper); - sizes = new GComboBox<>(IntStream.rangeClosed(1, 72).boxed().toArray(Integer[]::new)); - sizes.setMaximumRowCount(9); - sizePanel.add(sizes); - sizeChoice = font.getSize(); - sizes.setSelectedItem(sizeChoice); - sizes.setMaximumRowCount(9); + int styleChoice = font.getStyle(); + int size = font.getSize(); + fontCombo.setSelectedItem(fontWrapper); + sizeCombo.setSelectedItem(size); + styleCombo.setSelectedIndex(styleChoice); + + fontCombo.addActionListener(actionListener); + sizeCombo.addActionListener(actionListener); + styleCombo.addActionListener(actionListener); - styles = new GComboBox<>(new String[] { "PLAIN", "BOLD", "ITALIC", "BOLD & ITALIC" }); - styles.setMaximumRowCount(9); - stylePanel.add(styles); - styleChoice = font.getStyle(); - styles.setSelectedIndex(styleChoice); - fonts.addActionListener(this); - styles.addActionListener(this); - sizes.addActionListener(this); } - @Override - public void actionPerformed(ActionEvent event) { - // get values of panels - // set the editors new font - Object list = event.getSource(); + private void updateComboBoxModeIfNeeded(FontWrapper fontWrapper) { + if (systemFontNames.contains(fontWrapper)) { + return; + } + systemFontNames.add(fontWrapper); + DefaultComboBoxModel model = + new DefaultComboBoxModel<>(systemFontNames.toArray(new FontWrapper[0])); + fontCombo.setModel(model); + } - String fontNameChoice = font.getName(); - if (list == fonts) { - FontWrapper fontWrapper = (FontWrapper) fonts.getSelectedItem(); - fontNameChoice = fontWrapper.getFontName(); - } - else if (list == styles) { - styleChoice = styles.getSelectedIndex(); - } - else { - sizeChoice = (Integer) sizes.getSelectedItem(); - } + private void build() { + setLayout(new BorderLayout()); + add(buildTopPanel(), BorderLayout.NORTH); + add(buildPreviewLabel(), BorderLayout.CENTER); + } - font = new Font(fontNameChoice, styleChoice, sizeChoice); - fontStringLabel.setFont(font); - FontMetrics fm = fontStringLabel.getFontMetrics(font); + private Component buildTopPanel() { + JPanel panel = new JPanel(new FlowLayout(SwingConstants.CENTER, 10, 0)); + panel.add(buildFontNamePanel()); + panel.add(buildSizePanel()); + panel.add(buildStylePanel()); + return panel; + } + + private Component buildPreviewLabel() { + previewLabel = new GDLabel(SAMPLE_STRING); + previewLabel.setPreferredSize(new Dimension(350, 50)); + previewLabel.setHorizontalAlignment(SwingConstants.CENTER); + previewLabel.setVerticalAlignment(SwingConstants.CENTER); + previewLabel.setMinimumSize(new Dimension(300, 50)); + return previewLabel; + } + + private Component buildStylePanel() { + JPanel panel = new JPanel(new GridLayout(2, 1)); + + GDLabel styleLabel = new GDLabel("Styles"); + styleLabel.setFont(getFont().deriveFont(1)); + styleLabel.setHorizontalAlignment(SwingConstants.CENTER); + panel.add(styleLabel); + + styleCombo = + new GComboBox<>(new String[] { "PLAIN", "BOLD", "ITALIC", "BOLD & ITALIC" }); + styleCombo.setMaximumRowCount(9); + styleCombo.addActionListener(actionListener); + panel.add(styleCombo); + + return panel; + } + + private Component buildSizePanel() { + JPanel panel = new JPanel(new GridLayout(2, 1)); + + GDLabel sizeLabel = new GDLabel("Sizes"); + sizeLabel.setFont(getFont().deriveFont(1)); + sizeLabel.setHorizontalAlignment(SwingConstants.CENTER); + panel.add(sizeLabel); + + sizeCombo = + new GComboBox<>(IntStream.rangeClosed(1, 72).boxed().toArray(Integer[]::new)); + sizeCombo.setMaximumRowCount(9); + sizeCombo.setMaximumRowCount(9); + sizeCombo.addActionListener(actionListener); + panel.add(sizeCombo); + + return panel; + } + + private Component buildFontNamePanel() { + JPanel panel = new JPanel(new GridLayout(2, 1)); + + GDLabel fontLabel = new GDLabel("Fonts"); + fontLabel.setFont(getFont().deriveFont(1)); + fontLabel.setHorizontalAlignment(SwingConstants.CENTER); + panel.add(fontLabel); + + systemFontNames = getSystemFontNames(); + fontCombo = new GComboBox<>(systemFontNames.toArray(new FontWrapper[0])); + fontCombo.setMaximumRowCount(9); + fontCombo.addActionListener(actionListener); + panel.add(fontCombo); + + return panel; + } + + private List getSystemFontNames() { + GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Stream stream = Arrays.stream(gEnv.getAvailableFontFamilyNames()); + List collect = + stream.map(s -> new FontWrapper(s)).collect(Collectors.toList()); + Collections.sort(collect); + return new ArrayList<>(collect); + } + + private void fontChanged() { + FontWrapper fontWrapper = (FontWrapper) fontCombo.getSelectedItem(); + String fontNameChoice = fontWrapper.getFontName(); + int styleChoice = styleCombo.getSelectedIndex(); + int sizeChoice = (Integer) sizeCombo.getSelectedItem(); + Font font = new Font(fontNameChoice, styleChoice, sizeChoice); + updatePreviewLabel(font); + // allows debugging without hanging amazon aws + Swing.runLater(() -> setValue(font)); + } + + private void updatePreviewLabel(Font font) { + previewLabel.setFont(font); + FontMetrics fm = previewLabel.getFontMetrics(font); int height = fm.getHeight(); - Dimension d = fontStringLabel.getSize(); + Dimension d = previewLabel.getSize(); if (d.height < height) { d = new Dimension(d.width, height); - fontStringLabel.setPreferredSize(d); + previewLabel.setPreferredSize(d); } - fontStringLabel.invalidate(); + previewLabel.invalidate(); - setValue(font); - FontPropertyEditor.this.firePropertyChange(); } + + // A wrapper class created so that the names of fonts are comparable ignoring case + private class FontWrapper implements Comparable { + private final String fontName; + + private FontWrapper(String fontName) { + this.fontName = fontName; + } + + private String getFontName() { + return fontName; + } + + @Override + public String toString() { + return fontName; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (!getClass().equals(obj.getClass())) { + return false; + } + + FontWrapper otherWrapper = (FontWrapper) obj; + return fontName.toLowerCase().equals(otherWrapper.fontName.toLowerCase()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = + prime * result + ((fontName == null) ? 0 : fontName.toLowerCase().hashCode()); + return result; + } + + @Override + public int compareTo(FontWrapper otherWrapper) { + return fontName.compareToIgnoreCase(otherWrapper.fontName); + } + } + } - class EditorProvider extends DialogComponentProvider { - private Font originalFont = font; - - EditorProvider(JPanel contentPanel) { - super("Font Editor", true); - - addWorkPanel(contentPanel); - addOKButton(); - addCancelButton(); - } - - @Override - protected void okCallback() { - close(); - } - - @Override - protected void cancelCallback() { - font = originalFont; - super.cancelCallback(); - } - } - - // A wrapper class created so that the names of fonts are comparable ignoring case - private class FontWrapper implements Comparable { - private final String fontName; - - private FontWrapper(String fontName) { - this.fontName = fontName; - } - - private String getFontName() { - return fontName; - } - - @Override - public String toString() { - return fontName; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null) { - return false; - } - - if (!getClass().equals(obj.getClass())) { - return false; - } - - FontWrapper otherWrapper = (FontWrapper) obj; - return fontName.toLowerCase().equals(otherWrapper.fontName.toLowerCase()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((fontName == null) ? 0 : fontName.toLowerCase().hashCode()); - return result; - } - - @Override - public int compareTo(FontWrapper otherWrapper) { - return fontName.compareToIgnoreCase(otherWrapper.fontName); - } - } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java index b892ff2919..b4a9030eee 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java @@ -44,10 +44,16 @@ public class GhidraColorChooser extends JColorChooser { this.title = title; } + public void addColorToHistory(Color c) { + recentColorCache.addColor(c); + maybeInstallSettableColorSwatchChooserPanel(); + } + public void setColorHistory(List colors) { for (Color color : colors) { recentColorCache.addColor(color); } + maybeInstallSettableColorSwatchChooserPanel(); } public List getColorHistory() { @@ -66,8 +72,6 @@ public class GhidraColorChooser extends JColorChooser { @SuppressWarnings("deprecation") public Color showDialog(Component centerOverComponent) { - maybeInstallSettableColorSwatchChooserPanel(); - OKListener okListener = new OKListener(); JDialog dialog = createDialog(centerOverComponent, title, true, this, okListener, null); doSetActiveTab(dialog); @@ -123,7 +127,7 @@ public class GhidraColorChooser extends JColorChooser { } private void maybeInstallSettableColorSwatchChooserPanel() { - if (recentColorCache.size() == 0) { + if (recentColorCache.isEmpty()) { return; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/IconPropertyEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/IconPropertyEditor.java new file mode 100644 index 0000000000..68d863f44f --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/IconPropertyEditor.java @@ -0,0 +1,295 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.options.editor; + +import java.awt.*; +import java.beans.PropertyEditorSupport; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.List; + +import javax.swing.*; + +import org.apache.commons.io.FileUtils; + +import docking.theme.gui.ProtectedIcon; +import docking.widgets.*; +import docking.widgets.filechooser.GhidraFileChooser; +import docking.widgets.filechooser.GhidraFileChooserMode; +import docking.widgets.label.GDLabel; +import docking.widgets.list.GListCellRenderer; +import ghidra.framework.Application; +import ghidra.framework.preferences.Preferences; +import ghidra.util.Msg; +import ghidra.util.filechooser.ExtensionFileFilter; +import resources.ResourceManager; +import resources.icons.ScaledImageIcon; +import resources.icons.UrlImageIcon; + +public class IconPropertyEditor extends PropertyEditorSupport { + private IconChooserPanel iconChooserPanel; + + @Override + public Component getCustomEditor() { + iconChooserPanel = new IconChooserPanel(); + return iconChooserPanel; + } + + @Override + public boolean supportsCustomEditor() { + return true; + } + + @Override + public void setValue(Object value) { + if (iconChooserPanel != null) { + iconChooserPanel.setSelectedIcon((Icon) value); + } + doSetValue(value); + } + + private void doSetValue(Object value) { + if (!Objects.equals(value, getValue())) { + super.setValue(value); + } + } + + private String iconToString(Icon icon) { + if (icon instanceof UrlImageIcon urlIcon) { + return urlIcon.getOriginalPath(); + } + return " "; + } + + class IconChooserPanel extends JPanel { + + private static final String IMAGE_DIR = "images/"; + private static final String LAST_ICON_DIR_PREFERENCE_KEY = "IconEditor.lastDir"; + private GDLabel previewLabel; + private DropDownSelectionTextField dropDown; + private IconDropDownDataModel dataModel; + DropDownSelectionChoiceListener choiceListener = t -> iconChanged(t); + + public IconChooserPanel() { + build(); + } + + public void setSelectedIcon(Icon icon) { + if (icon == null) { + return; + } + if (!(icon instanceof UrlImageIcon)) { + icon = new ProtectedIcon(icon); + } + updateDropDownDataModel(icon); + updatePreviewLabel(icon); + + } + + private void updateDropDownDataModel(Icon icon) { + Set icons = ResourceManager.getLoadedUrlIcons(); + icons.add(icon); + dataModel.setData(new ArrayList<>(icons)); + dropDown.setSelectedValue(icon); + } + + private void build() { + setLayout(new BorderLayout()); + add(buildTopPanel(), BorderLayout.NORTH); + add(buildPreviewLabel(), BorderLayout.CENTER); + } + + private Component buildTopPanel() { + JPanel panel = new JPanel(new BorderLayout()); + dataModel = new IconDropDownDataModel(); + dropDown = new DropDownSelectionTextField<>(dataModel) { + protected List getMatchingData(String searchText) { + if (searchText.isBlank()) { + return ((IconDropDownDataModel) dataModel).getData(); + } + return super.getMatchingData(searchText); + } + }; + dropDown.addDropDownSelectionChoiceListener(choiceListener); + panel.add(dropDown, BorderLayout.CENTER); + JButton browseButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE); + panel.add(browseButton, BorderLayout.EAST); + browseButton.addActionListener(e -> browse()); + + return panel; + } + + private void iconChanged(Icon icon) { + boolean isDropDownWindowShowing = dropDown.isMatchingListShowing(); + if (!isDropDownWindowShowing) { + updatePreviewLabel(icon); + doSetValue(icon); + } + } + + private void browse() { + GhidraFileChooser chooser = new GhidraFileChooser(iconChooserPanel); + chooser.setTitle("Import Icon"); + chooser.setApproveButtonToolTipText("Import Icon"); + chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY); + chooser.setSelectedFileFilter( + ExtensionFileFilter.forExtensions("Icon Files", ".png", "gif")); + String lastDir = Preferences.getProperty(LAST_ICON_DIR_PREFERENCE_KEY); + if (lastDir != null) { + chooser.setCurrentDirectory(new File(lastDir)); + } + File file = chooser.getSelectedFile(); + if (file != null) { + File dir = chooser.getCurrentDirectory(); + Preferences.setProperty(LAST_ICON_DIR_PREFERENCE_KEY, dir.getAbsolutePath()); + importIconFile(file); + } + } + + private void importIconFile(File file) { + + if (!isValidIcon(file)) { + Msg.error(this, "File is not a valid icon: " + file.getAbsolutePath()); + return; + } + File dir = Application.getUserSettingsDirectory(); + String relativePath = IMAGE_DIR + file.getName(); + + File destinationFile = new File(dir, relativePath); + if (destinationFile.exists()) { + int result = OptionDialog.showYesNoDialog(dropDown, "Overwrite?", + "An icon with that name already exists.\n Do you want to overwrite it?"); + if (result == OptionDialog.NO_OPTION) { + return; + } + } + try { + FileUtils.copyFile(file, destinationFile); + String path = ResourceManager.EXTERNAL_ICON_PREFIX + relativePath; + ImageIcon icon = ResourceManager.loadImage(path); + setValue(icon); + } + catch (IOException e) { + Msg.showError(this, dropDown, "Error importing file", e); + } + } + + private boolean isValidIcon(File file) { + if (!file.exists()) { + return false; + } + try { + UrlImageIcon icon = new UrlImageIcon(file.getAbsolutePath(), file.toURI().toURL()); + icon.getIconWidth(); + return true; + } + catch (Exception e) { + Msg.showError(this, dropDown, "Invalid Icon File", + "The file is not a valid icon: " + file.getAbsolutePath()); + return false; + } + + } + + private Component buildPreviewLabel() { + JPanel panel = new JPanel(new BorderLayout()); + + previewLabel = new GDLabel(""); + previewLabel.setIcon(ResourceManager.getDefaultIcon()); + previewLabel.setHorizontalAlignment(SwingConstants.CENTER); + previewLabel.setVerticalAlignment(SwingConstants.CENTER); + panel.add(previewLabel, BorderLayout.CENTER); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return panel; + } + + private void updatePreviewLabel(Icon icon) { + previewLabel.setIcon(icon); + int height = icon.getIconHeight(); + int width = icon.getIconWidth(); + Dimension d = previewLabel.getSize(); + height = Math.max(d.height, height); + width = Math.max(d.width, width); + previewLabel.setPreferredSize(new Dimension(width, height)); + previewLabel.invalidate(); + iconChooserPanel.validate(); + } + + } + + class IconDropDownDataModel extends DefaultDropDownSelectionDataModel { + IconListCellRender renderer = new IconListCellRender(); + + public IconDropDownDataModel() { + super(Collections.emptyList(), IconPropertyEditor.this::iconToString); + } + + List getData() { + return data; + } + + void setData(List icons) { + Collections.sort(icons, comparator); + data = icons; + } + + @Override + public List getMatchingData(String searchText) { + if (searchText.isBlank()) { + return data; + } + searchText = searchText.toLowerCase(); + List results = new ArrayList<>(); + for (Icon icon : data) { + String name = iconToString(icon); + if (name.toLowerCase().contains(searchText)) { + results.add(icon); + } + } + + return results; + + } + + @Override + public ListCellRenderer getListRenderer() { + return renderer; + } + + } + + class IconListCellRender extends GListCellRenderer { + @Override + protected String getItemText(Icon icon) { + return iconToString(icon); + } + + @Override + public Component getListCellRendererComponent(JList extends Icon> list, Icon icon, + int index, boolean isSelected, boolean hasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, icon, index, + isSelected, hasFocus); + + if (icon.getIconWidth() != 16 || icon.getIconHeight() != 16) { + icon = new ScaledImageIcon(icon, 16, 16); + } + label.setIcon(icon); + return label; + } + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsDialog.java index 0a89d0330a..824ba792ec 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsDialog.java @@ -15,7 +15,6 @@ */ package docking.options.editor; -import java.awt.Color; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -55,7 +54,6 @@ public class OptionsDialog extends DialogComponentProvider { new OptionsPropertyChangeListener()); setTitle(title); - setBackground(Color.lightGray); addWorkPanel(panel); addOKButton(); @@ -67,6 +65,7 @@ public class OptionsDialog extends DialogComponentProvider { setFocusComponent(panel.getFocusComponent()); } + @Override public void dispose() { panel.dispose(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java index d8640fab9b..a7a14d5206 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java @@ -40,7 +40,7 @@ import ghidra.util.layout.MiddleLayout; import ghidra.util.task.SwingUpdateManager; import help.Help; import help.HelpService; -import resources.ResourceManager; +import resources.Icons; public class OptionsPanel extends JPanel { private PropertyChangeListener changeListener; @@ -251,7 +251,7 @@ public class OptionsPanel extends JPanel { BoxLayout bl = new BoxLayout(labelPanel, BoxLayout.X_AXIS); labelPanel.setLayout(bl); labelPanel.add(Box.createHorizontalStrut(5)); - labelPanel.add(new GIconLabel(ResourceManager.loadImage("images/information.png"))); + labelPanel.add(new GIconLabel(Icons.INFO_ICON)); labelPanel.add(Box.createHorizontalStrut(5)); labelPanel.add(label); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsTreeNode.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsTreeNode.java index 6a3b5c86ff..50355b8cc6 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsTreeNode.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsTreeNode.java @@ -21,16 +21,14 @@ import javax.swing.Icon; import docking.widgets.tree.GTreeLazyNode; import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.framework.options.Options; -import resources.ResourceManager; +import resources.Icons; class OptionsTreeNode extends GTreeLazyNode { - private final static Icon OPEN_FOLDER_ICON = - ResourceManager.loadImage("images/openSmallFolder.png"); - private final static Icon CLOSED_FOLDER_ICON = - ResourceManager.loadImage("images/closedSmallFolder.png"); - private final static Icon PROPERTIES_ICON = - ResourceManager.loadImage("images/document-properties.png"); + private final static Icon OPEN_FOLDER_ICON = Icons.OPEN_FOLDER_ICON; + private final static Icon CLOSED_FOLDER_ICON = Icons.CLOSED_FOLDER_ICON; + private final static Icon PROPERTIES_ICON = new GIcon("icon.properties"); private final Options options; private final String name; @@ -46,7 +44,7 @@ class OptionsTreeNode extends GTreeLazyNode { @Override protected List generateChildren() { - List childList = new ArrayList (); + List childList = new ArrayList<>(); if (options.getOptionsEditor() == null) { // if hasOptionsEditor, don't show child options List childOptionsList = options.getChildOptions(); for (Options childOptions : childOptionsList) { @@ -108,7 +106,7 @@ class OptionsTreeNode extends GTreeLazyNode { public List getOptionNames() { if (options == null) { - return new ArrayList (); + return new ArrayList<>(); } return options.getLeafOptionNames(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/SettableColorSwatchChooserPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/SettableColorSwatchChooserPanel.java index 6585e6352e..7703baf713 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/SettableColorSwatchChooserPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/SettableColorSwatchChooserPanel.java @@ -21,11 +21,14 @@ import java.io.Serializable; import java.util.List; import javax.swing.*; -import javax.swing.border.*; +import javax.swing.border.LineBorder; import javax.swing.colorchooser.AbstractColorChooserPanel; import docking.widgets.label.GHtmlLabel; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Java; +import ghidra.util.ColorUtils; import ghidra.util.layout.VerticalLayout; public class SettableColorSwatchChooserPanel extends AbstractColorChooserPanel { @@ -66,6 +69,7 @@ public class SettableColorSwatchChooserPanel extends AbstractColorChooserPanel { return Integer.parseInt((String) value); } catch (NumberFormatException nfe) { + // return default value } } return defaultValue; @@ -118,8 +122,7 @@ public class SettableColorSwatchChooserPanel extends AbstractColorChooserPanel { recentSwatchListener = new RecentSwatchListener(); recentSwatchPanel.addMouseListener(recentSwatchListener); - Border border = - new CompoundBorder(new LineBorder(Color.black), new LineBorder(Color.white)); + LineBorder border = new LineBorder(Java.BORDER); swatchPanel.setBorder(border); gbc.weightx = 1.0; gbc.gridwidth = 2; @@ -182,6 +185,7 @@ public class SettableColorSwatchChooserPanel extends AbstractColorChooserPanel { @Override public void updateChooser() { + // stub } class HistorySwatchListener extends MouseAdapter { @@ -222,7 +226,7 @@ class SwatchPanel extends JPanel { initColors(); setToolTipText(""); // register for events setOpaque(true); - setBackground(Color.white); + setBackground(Colors.BACKGROUND); setRequestFocusEnabled(false); } @@ -232,6 +236,7 @@ class SwatchPanel extends JPanel { } protected void initValues() { + // stub } @Override @@ -251,7 +256,7 @@ class SwatchPanel extends JPanel { } int y = row * (swatchSize.height + gap.height); g.fillRect(x, y, swatchSize.width, swatchSize.height); - g.setColor(Color.black); + g.setColor(Java.BORDER); g.drawLine(x + swatchSize.width - 1, y, x + swatchSize.width - 1, y + swatchSize.height - 1); g.drawLine(x, y + swatchSize.height - 1, x + swatchSize.width - 1, @@ -268,7 +273,7 @@ class SwatchPanel extends JPanel { } protected void initColors() { - + // stub } @Override @@ -383,8 +388,8 @@ class MainSwatchPanel extends SwatchPanel { colors = new Color[numColors]; for (int i = 0; i < numColors; i++) { - colors[i] = - new Color(rawValues[(i * 3)], rawValues[(i * 3) + 1], rawValues[(i * 3) + 2]); + colors[i] = ColorUtils.getColor(rawValues[(i * 3)], rawValues[(i * 3) + 1], + rawValues[(i * 3) + 2]); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/resources/icons/NumberIcon.java b/Ghidra/Framework/Docking/src/main/java/docking/resources/icons/NumberIcon.java index d219d6e16a..403882d31e 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/resources/icons/NumberIcon.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/resources/icons/NumberIcon.java @@ -22,12 +22,15 @@ import javax.swing.Icon; import javax.swing.JComponent; import docking.util.GraphicsUtils; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; /** * An icon that paints the given number */ public class NumberIcon implements Icon { + private static final Color BORDER_COLOR = Palette.getColor("lightskyblue"); private String number; private float bestFontSize = -1; @@ -42,9 +45,9 @@ public class NumberIcon implements Icon { @Override public void paintIcon(Component c, Graphics g, int x, int y) { - g.setColor(Color.WHITE); + g.setColor(Colors.BACKGROUND); g.fillRect(x, y, getIconWidth(), getIconHeight()); - g.setColor(new Color(0xb5d5ff)); + g.setColor(BORDER_COLOR); g.drawRect(x, y, getIconWidth(), getIconHeight()); float fontSize = getMaxFontSize(g, getIconWidth() - 1, getIconHeight()); @@ -66,7 +69,7 @@ public class NumberIcon implements Icon { int halfTextWidth = textWidth >> 1; int baselineX = x + (halfWidth - halfTextWidth); - g.setColor(Color.BLACK); + g.setColor(Colors.FOREGROUND); JComponent jc = null; if (c instanceof JComponent) { jc = (JComponent) c; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java new file mode 100644 index 0000000000..69ef32f4c5 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java @@ -0,0 +1,51 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.Color; +import java.beans.PropertyChangeListener; + +import docking.options.editor.ColorPropertyEditor; +import generic.theme.*; + +/** + * Editor for Theme colors + */ +public class ColorValueEditor extends ThemeValueEditor { + + /** + * Constructor + * @param listener the {@link PropertyChangeListener} to be notified when changes are made + */ + public ColorValueEditor(PropertyChangeListener listener) { + super("Color", listener, new ColorPropertyEditor()); + } + + @Override + protected Color getRawValue(String id) { + return Gui.getColor(id); + } + + @Override + protected ThemeValue createNewThemeValue(String id, Color color) { + return new ColorValue(id, color); + } + + @Override + protected void storeState() { + ((ColorPropertyEditor) editor).saveState(); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ExportThemeDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ExportThemeDialog.java new file mode 100644 index 0000000000..482be31be4 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ExportThemeDialog.java @@ -0,0 +1,168 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.io.File; +import java.io.IOException; + +import javax.swing.*; + +import docking.DialogComponentProvider; +import docking.options.editor.ButtonPanelFactory; +import docking.widgets.checkbox.GCheckBox; +import docking.widgets.filechooser.GhidraFileChooser; +import docking.widgets.filechooser.GhidraFileChooserMode; +import docking.widgets.label.GLabel; +import generic.theme.*; +import ghidra.util.MessageType; +import ghidra.util.Msg; +import ghidra.util.filechooser.GhidraFileFilter; +import ghidra.util.layout.PairLayout; + +/** + * Dialog for exporting themes to external files or zip files. + */ +public class ExportThemeDialog extends DialogComponentProvider { + + private JTextField nameField; + private JTextField fileTextField; + private GCheckBox includeDefaultsCheckbox; + private boolean exportAsZip; + private ThemeManager themeManager; + + public ExportThemeDialog(ThemeManager themeManager, boolean exportAsZip) { + super("Export Theme"); + this.themeManager = themeManager; + this.exportAsZip = exportAsZip; + addWorkPanel(buildMainPanel()); + addOKButton(); + addCancelButton(); + setRememberSize(false); + } + + @Override + protected void okCallback() { + if (exportTheme()) { + close(); + } + } + + private boolean exportTheme() { + String themeName = nameField.getText(); + GTheme activeTheme = themeManager.getActiveTheme(); + LafType laf = activeTheme.getLookAndFeelType(); + boolean useDarkDefaults = activeTheme.useDarkDefaults(); + File file = new File(fileTextField.getText()); + + if (themeName.isBlank()) { + setStatusText("Missing Theme Name", MessageType.ERROR, true); + return false; + } + + try { + GTheme exportTheme = new GTheme(file, themeName, laf, useDarkDefaults); + loadValues(exportTheme); + ThemeWriter themeWriter = new ThemeWriter(exportTheme); + themeWriter.writeTheme(file, exportAsZip); + return true; + } + catch (IOException e) { + Msg.error("Error Exporting Theme", "I/O Error encountered trying to export theme!", e); + } + return false; + } + + private void loadValues(GTheme exportTheme) { + if (includeDefaultsCheckbox.isSelected()) { + exportTheme.load(themeManager.getCurrentValues()); + } + else { + exportTheme.load(themeManager.getNonDefaultValues()); + } + } + + @Override + protected void cancelCallback() { + close(); + } + + private JComponent buildMainPanel() { + JPanel panel = new JPanel(new PairLayout(10, 10)); + panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + + panel.add(new GLabel("Theme Name:", SwingConstants.RIGHT)); + panel.add(buildNameField()); + panel.add(new GLabel("Output File:", SwingConstants.RIGHT)); + panel.add(buildFilePanel()); + panel.add(new GLabel("Include Defaults:", SwingConstants.RIGHT)); + panel.add(buildIncludeDefaultsCheckbox()); + return panel; + } + + private Component buildNameField() { + nameField = new JTextField(25); + nameField.setText(themeManager.getActiveTheme().getName()); + return nameField; + } + + private Component buildIncludeDefaultsCheckbox() { + includeDefaultsCheckbox = new GCheckBox(); + includeDefaultsCheckbox.setSelected(true); + return includeDefaultsCheckbox; + } + + private Component buildFilePanel() { + File homeDir = new File(System.getProperty("user.home")); // prefer the home directory + + String name = themeManager.getActiveTheme().getName(); + String filename = name.replaceAll(" ", "_") + "."; + filename += exportAsZip ? GTheme.ZIP_FILE_EXTENSION : GTheme.FILE_EXTENSION; + File file = new File(homeDir, filename); + + fileTextField = new JTextField(); + fileTextField.setText(file.getAbsolutePath()); + fileTextField.setEditable(false); + fileTextField.setFocusable(false); + JButton folderButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE); + folderButton.addActionListener(e -> chooseFile()); + + JPanel panel = new JPanel(new BorderLayout()); + panel.add(fileTextField, BorderLayout.CENTER); + panel.add(folderButton, BorderLayout.EAST); + return panel; + } + + private void chooseFile() { + GhidraFileChooser chooser = new GhidraFileChooser(getComponent()); + chooser.setTitle("Choose Theme File"); + chooser.setApproveButtonToolTipText("Select File"); + chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY); + chooser.setSelectedFileFilter(GhidraFileFilter.ALL); + chooser.setSelectedFile(new File(fileTextField.getText())); + File file = chooser.getSelectedFile(); + if (file != null) { + fileTextField.setText(file.getAbsolutePath()); + } + } + + // used for testing + public void setOutputFile(File outputFile) { + fileTextField.setText(outputFile.getAbsolutePath()); + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/FontValueEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/FontValueEditor.java new file mode 100644 index 0000000000..4d0291e38e --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/FontValueEditor.java @@ -0,0 +1,47 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.Font; +import java.beans.PropertyChangeListener; + +import docking.options.editor.FontPropertyEditor; +import generic.theme.*; + +/** + * Editor for Theme fonts + */ +public class FontValueEditor extends ThemeValueEditor { + + /** + * Constructor + * @param listener the {@link PropertyChangeListener} to be notified when changes are made + */ + public FontValueEditor(PropertyChangeListener listener) { + super("Font", listener, new FontPropertyEditor()); + } + + @Override + protected Font getRawValue(String id) { + return Gui.getFont(id); + } + + @Override + protected ThemeValue createNewThemeValue(String id, Font font) { + return new FontValue(id, font); + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/IconValueEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/IconValueEditor.java new file mode 100644 index 0000000000..541641eb88 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/IconValueEditor.java @@ -0,0 +1,48 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.beans.PropertyChangeListener; + +import javax.swing.Icon; + +import docking.options.editor.IconPropertyEditor; +import generic.theme.*; + +/** + * Editor for Theme fonts + */ +public class IconValueEditor extends ThemeValueEditor { + + /** + * Constructor + * @param listener the {@link PropertyChangeListener} to be notified when changes are made + */ + public IconValueEditor(PropertyChangeListener listener) { + super("Icon", listener, new IconPropertyEditor()); + } + + @Override + protected Icon getRawValue(String id) { + return Gui.getIcon(id); + } + + @Override + protected ThemeValue createNewThemeValue(String id, Icon icon) { + return new IconValue(id, icon); + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ProtectedIcon.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ProtectedIcon.java new file mode 100644 index 0000000000..6c9ab3d276 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ProtectedIcon.java @@ -0,0 +1,60 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.Component; +import java.awt.Graphics; + +import javax.swing.Icon; +import javax.swing.LookAndFeel; + +import resources.ResourceManager; + +/** + * A wrapper for an icon that suppresses errors. Some Icons that are mined from a + * {@link LookAndFeel} have specialized uses and will throw exceptions if used outside + * their intended component. This class is used when trying to show them in the the theme + * editor table. + */ +public class ProtectedIcon implements Icon { + Icon bomb = ResourceManager.getDefaultIcon(); + Icon delegate; + boolean isError = false; + + public ProtectedIcon(Icon delegate) { + this.delegate = delegate; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + try { + delegate.paintIcon(c, g, x, y); + } + catch (Exception e) { + bomb.paintIcon(c, g, x, y); + } + } + + @Override + public int getIconWidth() { + return Math.max(1, delegate.getIconWidth()); + } + + @Override + public int getIconHeight() { + return Math.max(1, delegate.getIconHeight()); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTable.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTable.java new file mode 100644 index 0000000000..12a328bdbc --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTable.java @@ -0,0 +1,123 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; + +import javax.swing.JPanel; +import javax.swing.ListSelectionModel; +import javax.swing.table.TableColumn; + +import docking.ActionContext; +import docking.action.ActionContextProvider; +import docking.widgets.table.GFilterTable; +import docking.widgets.table.GTable; +import generic.theme.ColorValue; +import generic.theme.ThemeManager; +import ghidra.util.Swing; + +/** + * Color Table for Theme Dialog + */ +public class ThemeColorTable extends JPanel implements ActionContextProvider { + + private ThemeColorTableModel colorTableModel; + private ColorValueEditor colorEditor = new ColorValueEditor(this::colorValueChanged); + private GTable table; + private GFilterTable filterTable; + private ThemeManager themeManager; + + public ThemeColorTable(ThemeManager themeManager) { + super(new BorderLayout()); + this.themeManager = themeManager; + colorTableModel = new ThemeColorTableModel(themeManager); + + filterTable = new GFilterTable<>(colorTableModel); + table = filterTable.getTable(); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + ColorValue colorValue = filterTable.getSelectedRowObject(); + if (colorValue != null) { + colorEditor.editValue(colorValue); + } + e.consume(); + } + } + }); + + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + ColorValue value = filterTable.getItemAt(e.getPoint()); + + int col = filterTable.getColumn(e.getPoint()); + TableColumn column = table.getColumnModel().getColumn(col); + Object identifier = column.getIdentifier(); + if ("Current Color".equals(identifier) || "Id".equals(identifier)) { + colorEditor.editValue(value); + } + } + } + }); + + add(filterTable, BorderLayout.CENTER); + + } + + void colorValueChanged(PropertyChangeEvent event) { + // run later - don't rock the boat in the middle of a listener callback + Swing.runLater(() -> { + ColorValue newValue = (ColorValue) event.getNewValue(); + themeManager.setColor(newValue); + }); + } + + /** + * Returns the current values displayed in the table + */ + public void reloadCurrent() { + colorTableModel.reloadCurrent(); + } + + /** + * Reloads all the values displayed in the table + */ + public void reloadAll() { + colorTableModel.reloadAll(); + } + + @Override + public ActionContext getActionContext(MouseEvent e) { + if (e != null && e.getSource() == table) { + ColorValue currentValue = filterTable.getSelectedRowObject(); + if (currentValue == null) { + return null; + } + String id = currentValue.getId(); + ColorValue themeValue = colorTableModel.getThemeValue(id); + return new ThemeTableContext (currentValue, themeValue); + } + return null; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java new file mode 100644 index 0000000000..cba8f3dc41 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java @@ -0,0 +1,263 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.*; +import java.util.Comparator; +import java.util.List; +import java.util.function.Supplier; + +import javax.swing.Icon; +import javax.swing.JLabel; + +import docking.widgets.table.*; +import generic.theme.*; +import ghidra.docking.settings.Settings; +import ghidra.framework.plugintool.ServiceProvider; +import ghidra.framework.plugintool.ServiceProviderStub; +import ghidra.util.ColorUtils; +import ghidra.util.WebColors; +import ghidra.util.table.column.AbstractGColumnRenderer; +import ghidra.util.table.column.GColumnRenderer; + +/** + * Table model for theme colors + */ +public class ThemeColorTableModel extends GDynamicColumnTableModel { + private List colors; + private GThemeValueMap currentValues; + private GThemeValueMap themeValues; + private GThemeValueMap defaultValues; + private GThemeValueMap lightDefaultValues; + private GThemeValueMap darkDefaultValues; + private ThemeManager themeManager; + + public ThemeColorTableModel(ThemeManager themeManager) { + super(new ServiceProviderStub()); + this.themeManager = themeManager; + load(); + } + + /** + * Reloads the just the current values shown in the table. Called whenever a color changes. + */ + public void reloadCurrent() { + currentValues = themeManager.getCurrentValues(); + colors = currentValues.getColors(); + fireTableDataChanged(); + } + + /** + * Reloads all the current values and all the default values in the table. Called when the + * theme changes or the application defaults have been forced to reload. + */ + public void reloadAll() { + load(); + fireTableDataChanged(); + } + + ColorValue getThemeValue(String id) { + return themeValues.getColor(id); + } + + private void load() { + currentValues = themeManager.getCurrentValues(); + colors = currentValues.getColors(); + themeValues = themeManager.getThemeValues(); + defaultValues = themeManager.getDefaults(); + lightDefaultValues = themeManager.getApplicationLightDefaults(); + darkDefaultValues = themeManager.getApplicationDarkDefaults(); + + } + + @Override + public String getName() { + return "Colors"; + } + + @Override + public List getModelData() { + return colors; + } + + @Override + protected TableColumnDescriptor createTableColumnDescriptor() { + TableColumnDescriptor descriptor = new TableColumnDescriptor<>(); + descriptor.addVisibleColumn(new IdColumn()); + descriptor.addVisibleColumn(new ValueColumn("Current Color", () -> currentValues)); + descriptor.addVisibleColumn(new ValueColumn("Theme Color", () -> themeValues)); + descriptor.addVisibleColumn(new ValueColumn("Default Color", () -> defaultValues)); + descriptor.addHiddenColumn(new ValueColumn("Light Defaults", () -> lightDefaultValues)); + descriptor.addHiddenColumn(new ValueColumn("Dark Defaults", () -> darkDefaultValues)); + return descriptor; + } + + @Override + public Object getDataSource() { + return null; + } + + class IdColumn extends AbstractDynamicTableColumn { + + @Override + public String getColumnName() { + return "Id"; + } + + @Override + public String getValue(ColorValue themeColor, Settings settings, Object data, + ServiceProvider provider) throws IllegalArgumentException { + return themeColor.getId(); + } + + @Override + public int getColumnPreferredWidth() { + return 300; + } + } + + class ValueColumn extends AbstractDynamicTableColumn { + private ThemeColorRenderer renderer; + private String name; + private Supplier valueSupplier; + + ValueColumn(String name, Supplier supplier) { + this.name = name; + this.valueSupplier = supplier; + renderer = new ThemeColorRenderer(); + } + + @Override + public String getColumnName() { + return name; + } + + @Override + public ResolvedColor getValue(ColorValue themeColor, Settings settings, Object data, + ServiceProvider provider) throws IllegalArgumentException { + GThemeValueMap valueMap = valueSupplier.get(); + String id = themeColor.getId(); + ColorValue colorValue = valueMap.getColor(id); + if (colorValue == null) { + return null; + } + Color color = colorValue.hasResolvableValue(valueMap) ? colorValue.get(valueMap) : null; + if (color == null) { + return null; + } + return new ResolvedColor(id, colorValue.getReferenceId(), color); + } + + @Override + public GColumnRenderer getColumnRenderer() { + return renderer; + } + + public Comparator getComparator() { + return (v1, v2) -> { + if (v1 == null && v2 == null) { + return 0; + } + if (v1 == null) { + return 1; + } + if (v2 == null) { + return -1; + } + return ColorUtils.COMPARATOR.compare(v1.color, v2.color); + }; + } + + @Override + public int getColumnPreferredWidth() { + return 300; + } + + } + + private class ThemeColorRenderer extends AbstractGColumnRenderer { + + public ThemeColorRenderer() { + setFont(Gui.getFont("font.monospaced")); + } + + @Override + public Component getTableCellRendererComponent(GTableCellRenderingData data) { + JLabel label = (JLabel) super.getTableCellRendererComponent(data); + ResolvedColor resolved = (ResolvedColor) data.getValue(); + + String text = getValueText(resolved); + Color color = resolved == null ? GThemeDefaults.Colors.BACKGROUND : resolved.color(); + label.setText(text); + label.setIcon(new SwatchIcon(color, label.getForeground())); + label.setOpaque(true); + return label; + } + + private String getValueText(ResolvedColor resolvedColor) { + if (resolvedColor == null) { + return " "; + } + Color color = resolvedColor.color(); + String name = WebColors.toWebColorName(color); + if (resolvedColor.refId() != null) { + return "[" + resolvedColor.refId() + "] "; + } + String text = WebColors.toString(color, false); + if (name != null) { + text += " (" + name + ")"; + } + return text; + } + + @Override + public String getFilterString(ResolvedColor colorValue, Settings settings) { + return getValueText(colorValue); + } + + } + + static class SwatchIcon implements Icon { + private Color color; + private Color border; + + SwatchIcon(Color c, Color border) { + this.color = c; + this.border = border; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + g.setColor(color); + g.fillRect(x, y, 25, 16); + g.setColor(border); + g.drawRect(x, y, 25, 16); + } + + @Override + public int getIconWidth() { + return 25; + } + + @Override + public int getIconHeight() { + return 16; + } + } + + record ResolvedColor(String id, String refId, Color color) {/**/} + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeDialog.java new file mode 100644 index 0000000000..8ff6662636 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeDialog.java @@ -0,0 +1,302 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.*; +import java.util.*; +import java.util.stream.Collectors; + +import javax.swing.*; + +import docking.*; +import docking.action.ActionContextProvider; +import docking.action.DockingAction; +import docking.action.builder.ActionBuilder; +import docking.widgets.OptionDialog; +import docking.widgets.combobox.GhidraComboBox; +import generic.theme.*; +import ghidra.util.*; + +/** + * Primary dialog for editing Themes. + */ +public class ThemeDialog extends DialogComponentProvider { + private static ThemeDialog INSTANCE; + + private JButton saveButton; + private JButton restoreButton; + private GhidraComboBox combo; + private ItemListener comboListener = this::themeComboChanged; + private ThemeListener listener = new DialogThemeListener(); + private JTabbedPane tabbedPane; + + private ThemeColorTable colorTable; + private ThemeFontTable fontTable; + private ThemeIconTable iconTable; + + private ThemeManager themeManager; + + public ThemeDialog(ThemeManager themeManager) { + super("Theme Dialog", false); + this.themeManager = themeManager; + addWorkPanel(createMainPanel()); + + addDismissButton(); + addButton(createSaveButton()); + addButton(createRestoreButton()); + + setPreferredSize(1100, 500); + setRememberSize(false); + updateButtons(); + createActions(); + Gui.addThemeListener(listener); + setHelpLocation(new HelpLocation("Theming", "Edit_Theme")); + } + + private void createActions() { + DockingAction reloadDefaultsAction = new ActionBuilder("Reload Ghidra Defaults", getTitle()) + .toolBarIcon(new GIcon("icon.refresh")) + .helpLocation(new HelpLocation("Theming", "Reload_Ghidra_Defaults")) + .onAction(e -> reloadDefaultsCallback()) + .build(); + addAction(reloadDefaultsAction); + + DockingAction resetValueAction = new ActionBuilder("Restore Value", getTitle()) + .popupMenuPath("Restore Value") + .withContext(ThemeTableContext.class) + .enabledWhen(c -> c.isChanged()) + .popupWhen(c -> true) + .helpLocation(new HelpLocation("Theming", "Restore_Value")) + .onAction(c -> c.getThemeValue().installValue(themeManager)) + .build(); + addAction(resetValueAction); + } + + @Override + protected void dismissCallback() { + if (handleChanges()) { + INSTANCE = null; + close(); + } + } + + private boolean handleChanges() { + if (themeManager.hasThemeChanges()) { + int result = OptionDialog.showYesNoCancelDialog(null, "Close Theme Dialog", + "You have changed the theme.\n Do you want save your changes?"); + if (result == OptionDialog.CANCEL_OPTION) { + return false; + } + if (result == OptionDialog.YES_OPTION) { + return ThemeUtils.saveThemeChanges(themeManager); + } + themeManager.restoreThemeValues(); + } + return true; + } + + protected void saveCallback() { + ThemeUtils.saveThemeChanges(themeManager); + } + + private void restoreCallback() { + if (themeManager.hasThemeChanges()) { + int result = OptionDialog.showYesNoDialog(null, "Restore Theme Values", + "Are you sure you want to discard all your changes?"); + if (result == OptionDialog.NO_OPTION) { + return; + } + } + themeManager.restoreThemeValues(); + } + + private void reloadDefaultsCallback() { + if (themeManager.hasThemeChanges()) { + int result = OptionDialog.showYesNoDialog(null, "Reload Ghidra Default Values", + "This will discard all your theme changes. Continue?"); + if (result == OptionDialog.NO_OPTION) { + return; + } + } + themeManager.reloadApplicationDefaults(); + } + + private void reset() { + colorTable.reloadAll(); + fontTable.reloadAll(); + iconTable.reloadAll(); + updateButtons(); + updateCombo(); + } + + private void themeComboChanged(ItemEvent e) { + + if (e.getStateChange() != ItemEvent.SELECTED) { + return; + } + + if (!ThemeUtils.askToSaveThemeChanges(themeManager)) { + Swing.runLater(() -> updateCombo()); + return; + } + String themeName = (String) e.getItem(); + + Swing.runLater(() -> { + GTheme theme = themeManager.getTheme(themeName); + themeManager.setTheme(theme); + if (theme.getLookAndFeelType() == LafType.GTK) { + setStatusText( + "Warning - Themes using the GTK LookAndFeel do not support changing java component colors, fonts or icons.", + MessageType.ERROR); + } + else { + setStatusText(""); + } + colorTable.reloadAll(); + fontTable.reloadAll(); + iconTable.reloadAll(); + }); + } + + private void updateButtons() { + boolean hasChanges = themeManager.hasThemeChanges(); + saveButton.setEnabled(hasChanges); + restoreButton.setEnabled(hasChanges); + } + + private JComponent createMainPanel() { + JPanel panel = new JPanel(); + + panel.setLayout(new BorderLayout()); + panel.add(buildControlPanel(), BorderLayout.NORTH); + panel.add(buildTabedTables()); + return panel; + } + + private Component buildControlPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + panel.add(buildThemeCombo(), BorderLayout.WEST); + panel.setName("gthemePanel"); + return panel; + } + + private void updateCombo() { + Set supportedThemes = themeManager.getSupportedThemes(); + List themeNames = + supportedThemes.stream().map(t -> t.getName()).collect(Collectors.toList()); + Collections.sort(themeNames); + combo.removeItemListener(comboListener); + combo.setModel(new DefaultComboBoxModel (new Vector (themeNames))); + combo.setSelectedItem(themeManager.getActiveTheme().getName()); + combo.addItemListener(comboListener); + } + + private Component buildThemeCombo() { + JPanel panel = new JPanel(); + Set supportedThemes = themeManager.getSupportedThemes(); + List themeNames = + supportedThemes.stream().map(t -> t.getName()).collect(Collectors.toList()); + Collections.sort(themeNames); + + combo = new GhidraComboBox<>(themeNames); + combo.setSelectedItem(themeManager.getActiveTheme().getName()); + combo.addItemListener(comboListener); + + panel.add(new JLabel("Theme: "), BorderLayout.WEST); + panel.add(combo); + panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + return panel; + } + + private Component buildTabedTables() { + tabbedPane = new JTabbedPane(); + colorTable = new ThemeColorTable(themeManager); + fontTable = new ThemeFontTable(themeManager); + iconTable = new ThemeIconTable(themeManager); + tabbedPane.add("Colors", colorTable); + tabbedPane.add("Fonts", fontTable); + tabbedPane.add("Icons", iconTable); + return tabbedPane; + } + + private JButton createRestoreButton() { + restoreButton = new JButton("Restore"); + restoreButton.setMnemonic('R'); + restoreButton.setName("Restore"); + restoreButton.addActionListener(e -> restoreCallback()); + restoreButton.setToolTipText("Restores all values to current theme"); + return restoreButton; + } + + private JButton createSaveButton() { + saveButton = new JButton("Save"); + saveButton.setMnemonic('S'); + saveButton.setName("Save"); + saveButton.addActionListener(e -> saveCallback()); + saveButton.setToolTipText("Saves changed values to a new Theme"); + return saveButton; + } + + /** + * Edits the current theme + * @param themeManager the application ThemeManager + */ + public static void editTheme(ThemeManager themeManager) { + if (INSTANCE != null) { + INSTANCE.toFront(); + return; + } + INSTANCE = new ThemeDialog(themeManager); + DockingWindowManager.showDialog(INSTANCE); + + } + + @Override + public void close() { + Gui.removeThemeListener(listener); + super.close(); + } + + @Override + public ActionContext getActionContext(MouseEvent event) { + ActionContextProvider contextProvider = + (ActionContextProvider) tabbedPane.getSelectedComponent(); + return contextProvider.getActionContext(event); + } + + class DialogThemeListener implements ThemeListener { + @Override + public void themeChanged(ThemeEvent event) { + if (event.haveAllValuesChanged()) { + reset(); + return; + } + if (event.hasAnyColorChanged()) { + colorTable.reloadCurrent(); + } + if (event.hasAnyFontChanged()) { + fontTable.reloadCurrent(); + } + if (event.hasAnyIconChanged()) { + iconTable.reloadCurrent(); + } + updateButtons(); + } + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTable.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTable.java new file mode 100644 index 0000000000..0b36688696 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTable.java @@ -0,0 +1,125 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; + +import javax.swing.JPanel; +import javax.swing.ListSelectionModel; +import javax.swing.table.TableColumn; + +import docking.ActionContext; +import docking.action.ActionContextProvider; +import docking.widgets.table.GFilterTable; +import docking.widgets.table.GTable; +import generic.theme.FontValue; +import generic.theme.ThemeManager; +import ghidra.util.Swing; + +/** + * Font Table for Theme Dialog + */ +public class ThemeFontTable extends JPanel implements ActionContextProvider { + + private ThemeFontTableModel fontTableModel; + private FontValueEditor fontEditor = new FontValueEditor(this::fontValueChanged); + private GTable table; + private GFilterTable filterTable; + private ThemeManager themeManager; + + public ThemeFontTable(ThemeManager themeManager) { + super(new BorderLayout()); + this.themeManager = themeManager; + + fontTableModel = new ThemeFontTableModel(themeManager); + filterTable = new GFilterTable<>(fontTableModel); + table = filterTable.getTable(); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + FontValue fontValue = filterTable.getSelectedRowObject(); + if (fontValue != null) { + fontEditor.editValue(fontValue); + } + e.consume(); + } + } + }); + + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + FontValue value = filterTable.getItemAt(e.getPoint()); + + int col = filterTable.getColumn(e.getPoint()); + TableColumn column = table.getColumnModel().getColumn(col); + Object identifier = column.getIdentifier(); + if ("Current Font".equals(identifier) || "Id".equals(identifier)) { + fontEditor.editValue(value); + } + } + } + }); + add(filterTable, BorderLayout.CENTER); + + } + + void fontValueChanged(PropertyChangeEvent event) { + // run later - don't rock the boat in the middle of a listener callback + Swing.runLater(() -> { + FontValue newValue = (FontValue) event.getNewValue(); + themeManager.setFont(newValue); + }); + } + + /** + * Reloads all the values displayed in the table + */ + public void reloadAll() { + fontTableModel.reloadAll(); + } + + /** + * Returns the current values displayed in the table + */ + public void reloadCurrent() { + fontTableModel.reloadCurrent(); + } + + @Override + public ActionContext getActionContext(MouseEvent e) { + if (e == null) { + return null; + } + if (e.getSource() == table) { + FontValue currentValue = filterTable.getSelectedRowObject(); + if (currentValue == null) { + return null; + } + String id = currentValue.getId(); + FontValue themeValue = fontTableModel.getThemeValue(id); + return new ThemeTableContext(currentValue, themeValue); + } + return null; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java new file mode 100644 index 0000000000..35740f365b --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java @@ -0,0 +1,211 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.Component; +import java.awt.Font; +import java.util.Comparator; +import java.util.List; +import java.util.function.Supplier; + +import javax.swing.JLabel; + +import docking.widgets.table.*; +import generic.theme.*; +import ghidra.docking.settings.Settings; +import ghidra.framework.plugintool.ServiceProvider; +import ghidra.framework.plugintool.ServiceProviderStub; +import ghidra.util.table.column.AbstractGColumnRenderer; +import ghidra.util.table.column.GColumnRenderer; + +/** + * Table model for theme fonts + */ +public class ThemeFontTableModel extends GDynamicColumnTableModel { + private List fonts; + private GThemeValueMap currentValues; + private GThemeValueMap themeValues; + private GThemeValueMap defaultValues; + private ThemeManager themeManager; + + public ThemeFontTableModel(ThemeManager themeManager) { + super(new ServiceProviderStub()); + this.themeManager = themeManager; + load(); + } + + /** + * Reloads the just the current values shown in the table. Called whenever a font changes. + */ + public void reloadCurrent() { + currentValues = themeManager.getCurrentValues(); + fonts = currentValues.getFonts(); + fireTableDataChanged(); + } + + /** + * Reloads all the current values and all the default values in the table. Called when the + * theme changes or the application defaults have been forced to reload. + */ + public void reloadAll() { + load(); + fireTableDataChanged(); + } + + private void load() { + currentValues = themeManager.getCurrentValues(); + fonts = currentValues.getFonts(); + themeValues = themeManager.getThemeValues(); + defaultValues = themeManager.getDefaults(); + } + + @Override + public String getName() { + return "Fonts"; + } + + @Override + public List getModelData() { + return fonts; + } + + @Override + protected TableColumnDescriptor createTableColumnDescriptor() { + TableColumnDescriptor descriptor = new TableColumnDescriptor<>(); + descriptor.addVisibleColumn(new IdColumn()); + descriptor.addVisibleColumn(new FontValueColumn("Current Font", () -> currentValues)); + descriptor.addVisibleColumn(new FontValueColumn("Theme Font", () -> themeValues)); + descriptor.addVisibleColumn(new FontValueColumn("Default Font", () -> defaultValues)); + return descriptor; + } + + @Override + public Object getDataSource() { + return null; + } + + private String getValueText(FontValue fontValue) { + if (fontValue == null) { + return " "; + } + if (fontValue.getReferenceId() != null) { + return "[" + fontValue.getReferenceId() + "]"; + } + + Font font = fontValue.getRawValue(); + return FontValue.fontToString(font); + } + + class IdColumn extends AbstractDynamicTableColumn { + + @Override + public String getColumnName() { + return "Id"; + } + + @Override + public String getValue(FontValue fontValue, Settings settings, Object data, + ServiceProvider provider) throws IllegalArgumentException { + return fontValue.getId(); + } + + @Override + public int getColumnPreferredWidth() { + return 300; + } + } + + class FontValueColumn extends AbstractDynamicTableColumn { + private ThemeFontRenderer renderer; + private String name; + private Supplier valueSupplier; + + FontValueColumn(String name, Supplier supplier) { + this.name = name; + this.valueSupplier = supplier; + renderer = new ThemeFontRenderer(); + } + + @Override + public String getColumnName() { + return name; + } + + @Override + public FontValue getValue(FontValue fontValue, Settings settings, Object data, + ServiceProvider provider) throws IllegalArgumentException { + GThemeValueMap valueMap = valueSupplier.get(); + String id = fontValue.getId(); + return valueMap.getFont(id); + } + + @Override + public GColumnRenderer getColumnRenderer() { + return renderer; + } + + public Comparator getComparator() { + return (v1, v2) -> { + if (v1 == null && v2 == null) { + return 0; + } + if (v1 == null) { + return 1; + } + if (v2 == null) { + return -1; + } + return getValueText(v1).compareTo(getValueText(v2)); + }; + } + + @Override + public int getColumnPreferredWidth() { + return 300; + } + + } + + private class ThemeFontRenderer extends AbstractGColumnRenderer { + + @Override + public Component getTableCellRendererComponent(GTableCellRenderingData data) { + JLabel label = (JLabel) super.getTableCellRendererComponent(data); + FontValue fontValue = (FontValue) data.getValue(); + + String text = getValueText(fontValue); + label.setText(text); + label.setOpaque(true); + return label; + } + + @Override + public String getFilterString(FontValue fontValue, Settings settings) { + return getValueText(fontValue); + } + + } + + /** + * Returns the original value for the id as defined by the current theme + * @param id the resource id to get a font value for + * @return the original value for the id as defined by the current theme + */ + public FontValue getThemeValue(String id) { + return themeValues.getFont(id); + } + +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTable.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTable.java new file mode 100644 index 0000000000..0514c902b7 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTable.java @@ -0,0 +1,118 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; + +import javax.swing.*; +import javax.swing.table.TableColumn; + +import docking.ActionContext; +import docking.action.ActionContextProvider; +import docking.widgets.table.GFilterTable; +import docking.widgets.table.GTable; +import generic.theme.IconValue; +import generic.theme.ThemeManager; +import ghidra.util.Swing; + +/** + * Icon Table for Theme Dialog + */ +public class ThemeIconTable extends JPanel implements ActionContextProvider { + + private ThemeIconTableModel iconTableModel; + private IconValueEditor iconEditor = new IconValueEditor(this::iconValueChanged); + private GTable table; + private GFilterTable filterTable; + private ThemeManager themeManager; + + public ThemeIconTable(ThemeManager themeManager) { + super(new BorderLayout()); + this.themeManager = themeManager; + iconTableModel = new ThemeIconTableModel(themeManager); + filterTable = new GFilterTable<>(iconTableModel); + table = filterTable.getTable(); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + IconValue iconValue = filterTable.getSelectedRowObject(); + if (iconValue != null) { + iconEditor.editValue(iconValue); + } + e.consume(); + } + } + }); + + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + IconValue value = filterTable.getItemAt(e.getPoint()); + + int col = filterTable.getColumn(e.getPoint()); + TableColumn column = table.getColumnModel().getColumn(col); + Object identifier = column.getIdentifier(); + if ("Current Icon".equals(identifier) || "Id".equals(identifier)) { + iconEditor.editValue(value); + } + } + } + }); + add(filterTable, BorderLayout.CENTER); + } + + void iconValueChanged(PropertyChangeEvent event) { + // run later - don't rock the boat in the middle of a listener callback + Swing.runLater(() -> { + IconValue newValue = (IconValue) event.getNewValue(); + themeManager.setIcon(newValue); + }); + } + + /** + * Reloads all the values displayed in the table + */ + public void reloadAll() { + iconTableModel.reloadAll(); + } + + /** + * Returns the current values displayed in the table + */ + public void reloadCurrent() { + iconTableModel.reloadCurrent(); + } + + @Override + public ActionContext getActionContext(MouseEvent e) { + if (e.getSource() == table) { + IconValue currentValue = filterTable.getSelectedRowObject(); + if (currentValue == null) { + return null; + } + String id = currentValue.getId(); + IconValue themeValue = iconTableModel.getThemeValue(id); + return new ThemeTableContext (currentValue, themeValue); + } + return null; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java new file mode 100644 index 0000000000..13b60bc181 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java @@ -0,0 +1,245 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.Component; +import java.util.Comparator; +import java.util.List; +import java.util.function.Supplier; + +import javax.swing.*; + +import docking.widgets.table.*; +import generic.theme.*; +import ghidra.docking.settings.Settings; +import ghidra.framework.plugintool.ServiceProvider; +import ghidra.framework.plugintool.ServiceProviderStub; +import ghidra.util.table.column.AbstractGColumnRenderer; +import ghidra.util.table.column.GColumnRenderer; +import resources.icons.*; + +/** + * Table model for theme icons + */ +public class ThemeIconTableModel extends GDynamicColumnTableModel { + private List icons; + private GThemeValueMap currentValues; + private GThemeValueMap themeValues; + private GThemeValueMap defaultValues; + private ThemeManager themeManager; + + public ThemeIconTableModel(ThemeManager themeManager) { + super(new ServiceProviderStub()); + this.themeManager = themeManager; + load(); + } + + /** + * Reloads the just the current values shown in the table. Called whenever an icon changes. + */ + public void reloadCurrent() { + currentValues = themeManager.getCurrentValues(); + icons = currentValues.getIcons(); + fireTableDataChanged(); + } + + /** + * Reloads all the current values and all the default values in the table. Called when the + * theme changes or the application defaults have been forced to reload. + */ + public void reloadAll() { + load(); + fireTableDataChanged(); + } + + private void load() { + currentValues = themeManager.getCurrentValues(); + icons = currentValues.getIcons(); + themeValues = themeManager.getThemeValues(); + defaultValues = themeManager.getDefaults(); + } + + @Override + public String getName() { + return "Fonts"; + } + + @Override + public List getModelData() { + return icons; + } + + @Override + protected TableColumnDescriptor createTableColumnDescriptor() { + TableColumnDescriptor descriptor = new TableColumnDescriptor<>(); + descriptor.addVisibleColumn(new IdColumn()); + descriptor.addVisibleColumn(new IconValueColumn("Current Icon", () -> currentValues)); + descriptor.addVisibleColumn(new IconValueColumn("Theme Icon", () -> themeValues)); + descriptor.addVisibleColumn(new IconValueColumn("Default Icon", () -> defaultValues)); + return descriptor; + } + + @Override + public Object getDataSource() { + return null; + } + + class IdColumn extends AbstractDynamicTableColumn { + + @Override + public String getColumnName() { + return "Id"; + } + + @Override + public String getValue(IconValue iconValue, Settings settings, Object data, + ServiceProvider provider) throws IllegalArgumentException { + return iconValue.getId(); + } + + @Override + public int getColumnPreferredWidth() { + return 300; + } + } + + class IconValueColumn extends AbstractDynamicTableColumn { + private ThemeIconRenderer renderer; + private String name; + private Supplier valueSupplier; + + IconValueColumn(String name, Supplier supplier) { + this.name = name; + this.valueSupplier = supplier; + renderer = new ThemeIconRenderer(); + } + + @Override + public String getColumnName() { + return name; + } + + @Override + public ResolvedIcon getValue(IconValue iconValue, Settings settings, Object data, + ServiceProvider provider) throws IllegalArgumentException { + GThemeValueMap valueMap = valueSupplier.get(); + String id = iconValue.getId(); + IconValue value = valueMap.getIcon(id); + if (value == null) { + return null; + } + Icon icon = value.get(valueMap); + return new ResolvedIcon(id, value.getReferenceId(), icon); + } + + @Override + public GColumnRenderer getColumnRenderer() { + return renderer; + } + + @Override + public Comparator getComparator() { + return (v1, v2) -> { + if (v1 == null && v2 == null) { + return 0; + } + if (v1 == null) { + return 1; + } + if (v2 == null) { + return -1; + } + return v1.icon().toString().compareTo(v2.icon().toString()); + }; + } + + @Override + public int getColumnPreferredWidth() { + return 300; + } + + } + + private class ThemeIconRenderer extends AbstractGColumnRenderer { + + public ThemeIconRenderer() { + setFont(Gui.getFont("font.monospaced")); + } + + @Override + public Component getTableCellRendererComponent(GTableCellRenderingData data) { + Component comp = super.getTableCellRendererComponent(data); + JLabel label = (JLabel) comp; + ResolvedIcon resolved = (ResolvedIcon) data.getValue(); + + String text = getValueText(resolved); + Icon icon = prepareIcon(resolved.icon()); + label.setIcon(icon); + label.setText(text); + label.setOpaque(true); + return label; + } + + private Icon prepareIcon(Icon icon) { + if (!(icon instanceof LazyImageIcon)) { + icon = new ProtectedIcon(icon); + } + if (icon.getIconWidth() != 16 && icon.getIconHeight() != 16) { + icon = new ScaledImageIcon(icon, 16, 16); + } + return icon; + } + + private String getValueText(ResolvedIcon resolvedIcon) { + if (resolvedIcon == null) { + return " "; + } + Icon icon = resolvedIcon.icon(); + String sizeString = "[" + icon.getIconWidth() + "x" + icon.getIconHeight() + "] "; + + String iconString = GTheme.JAVA_ICON; + if (icon instanceof UrlImageIcon urlIcon) { + iconString = urlIcon.getOriginalPath(); + } + else if (icon instanceof ImageIcon imageIcon) { + String description = imageIcon.getDescription(); + if (description != null) { + iconString = "[" + description + "]"; + } + } + if (resolvedIcon.refId() != null) { + iconString = resolvedIcon.refId() + " [" + iconString + "]"; + } + return String.format("%-8s%s", sizeString, iconString); + } + + @Override + public String getFilterString(ResolvedIcon iconValue, Settings settings) { + return getValueText(iconValue); + } + } + + record ResolvedIcon(String id, String refId, Icon icon) {/**/} + + /** + * Returns the original value for the id as defined by the current theme + * @param id the resource id to get a font value for + * @return the original value for the id as defined by the current theme + */ + public IconValue getThemeValue(String id) { + return themeValues.getIcon(id); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeTableContext.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeTableContext.java new file mode 100644 index 0000000000..dbd0ae22a8 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeTableContext.java @@ -0,0 +1,61 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import docking.ActionContext; +import generic.theme.ThemeValue; + +/** + * ActionContext for ThemeDialog tables + * + * @param the resource type (Color, Font, or Icon) + */ +public class ThemeTableContext extends ActionContext { + + private ThemeValue currentValue; + private ThemeValue themeValue; + + public ThemeTableContext(ThemeValue currentValue, ThemeValue themeValue) { + this.currentValue = currentValue; + this.themeValue = themeValue; + } + + /** + * Returns the currentValue of the selected table row + * @return the currentValue of the selected table row + */ + public ThemeValue getCurrentValue() { + return currentValue; + } + + /** + * Returns the original theme value of the selected table row + * @return the original theme value of the selected table row + */ + public ThemeValue getThemeValue() { + return themeValue; + } + + /** + * Returns true if the current value is not the same as the original theme value for the + * selected table row + * @return true if the current value is not the same as the original theme value for the + * selected table row + */ + public boolean isChanged() { + return !currentValue.equals(themeValue); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeUtils.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeUtils.java new file mode 100644 index 0000000000..0b3dcef9d9 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeUtils.java @@ -0,0 +1,246 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import docking.DockingWindowManager; +import docking.widgets.OptionDialog; +import docking.widgets.SelectFromListDialog; +import docking.widgets.dialogs.InputDialog; +import docking.widgets.filechooser.GhidraFileChooser; +import docking.widgets.filechooser.GhidraFileChooserMode; +import generic.theme.*; +import ghidra.framework.Application; +import ghidra.util.Msg; +import ghidra.util.filechooser.ExtensionFileFilter; + +/** + * Some common methods related to saving themes. These are invoked from various places to handle + * what to do if a change is made that would result in loosing theme changes. + */ +public class ThemeUtils { + + /** + * Asks the user if they want to save the current theme changes. If they answer yes, it + * will handle several use cases such as whether it gets saved to a new file or + * overwrites an existing file. + * @return true if the operation was not cancelled + */ + public static boolean askToSaveThemeChanges(ThemeManager themeManager) { + if (themeManager.hasThemeChanges()) { + int result = OptionDialog.showYesNoCancelDialog(null, "Save Theme Changes?", + "You have made changes to the theme.\n Do you want save your changes?"); + if (result == OptionDialog.CANCEL_OPTION) { + return false; + } + if (result == OptionDialog.YES_OPTION) { + return ThemeUtils.saveThemeChanges(themeManager); + } + themeManager.reloadApplicationDefaults(); + } + return true; + } + + /** + * Saves all current theme changes. Handles several use cases such as requesting a new theme + * name and asking to overwrite an existing file. + * @return true if the operation was not cancelled + */ + public static boolean saveThemeChanges(ThemeManager themeManager) { + GTheme activeTheme = themeManager.getActiveTheme(); + String name = activeTheme.getName(); + + while (!canSaveToName(themeManager, name)) { + name = getNameFromUser(name); + if (name == null) { + return false; + } + } + return saveCurrentValues(themeManager, name); + } + + /** + * Resets the theme to the default, handling the case where the current theme has changes. + */ + public static void resetThemeToDefault(ThemeManager themeManager) { + if (askToSaveThemeChanges(themeManager)) { + themeManager.setTheme(themeManager.getDefaultTheme()); + } + } + + /** + * Imports a theme. Handles the case where there are existing changes to the current theme. + * @param themeManager the application ThemeManager + */ + public static void importTheme(ThemeManager themeManager) { + GhidraFileChooser chooser = new GhidraFileChooser(null); + chooser.setTitle("Choose Theme File"); + chooser.setApproveButtonToolTipText("Select File"); + chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY); + chooser.setFileFilter(ExtensionFileFilter.forExtensions("Ghidra Theme Files", + GTheme.FILE_EXTENSION, GTheme.ZIP_FILE_EXTENSION)); + + File file = chooser.getSelectedFile(); + if (file == null) { + return; + } + importTheme(themeManager, file); + } + + static void importTheme(ThemeManager themeManager, File themeFile) { + if (!ThemeUtils.askToSaveThemeChanges(themeManager)) { + return; + } + GTheme startingTheme = themeManager.getActiveTheme(); + try { + GTheme imported = GTheme.loadTheme(themeFile); + // by setting the theme, we can let the normal save handle all the edge cases + // such as if a theme with that names exists and if so, should it be overwritten? + // Also, the imported theme may contain default values which we don't want to save. So + // by going through the usual save mechanism, only values that differ from defaults + // be saved. + themeManager.setTheme(imported); + if (!ThemeUtils.saveThemeChanges(themeManager)) { + themeManager.setTheme(startingTheme); + } + } + catch (IOException e) { + Msg.showError(ThemeUtils.class, null, "Error Importing Theme File", + "Error encountered importing file: " + themeFile.getAbsolutePath(), e); + } + + } + + /** + * Exports a theme, prompting the user to pick an file. Also handles dealing with any + * existing changes to the current theme. + * @param themeManager the ThemeManager that actually does the export + */ + public static void exportTheme(ThemeManager themeManager) { + if (!ThemeUtils.askToSaveThemeChanges(themeManager)) { + return; + } + boolean hasExternalIcons = !themeManager.getActiveTheme().getExternalIconFiles().isEmpty(); + String message = + "Export as zip file? (You are not using any external icons so the zip\n" + + "file would only contain a single theme file.)"; + if (hasExternalIcons) { + message = + "Export as zip file? (You have external icons so a zip file is required if you\n" + + "want to include the icons in the export.)"; + } + int result = OptionDialog.showOptionDialog(null, "Export as Zip?", message, "Export Zip", + "Export File", OptionDialog.QUESTION_MESSAGE); + if (result == OptionDialog.CANCEL_OPTION) { + return; + } + boolean exportAsZip = result == OptionDialog.OPTION_ONE; + + ExportThemeDialog dialog = new ExportThemeDialog(themeManager, exportAsZip); + DockingWindowManager.showDialog(dialog); + } + + /** + * Prompts for and deletes a selected theme. + */ + public static void deleteTheme(ThemeManager themeManager) { + List savedThemes = new ArrayList<>( + themeManager.getAllThemes().stream().filter(t -> t.getFile() != null).toList()); + if (savedThemes.isEmpty()) { + Msg.showInfo(ThemeUtils.class, null, "Delete Theme", "There are no deletable themes"); + return; + } + + GTheme selectedTheme = SelectFromListDialog.selectFromList(savedThemes, "Delete Theme", + "Select theme to delete", t -> t.getName()); + if (selectedTheme == null) { + return; + } + if (themeManager.getActiveTheme().equals(selectedTheme)) { + Msg.showWarn(ThemeUtils.class, null, "Delete Failed", + "Can't delete the current theme."); + return; + } + GTheme fileTheme = selectedTheme; + int result = OptionDialog.showYesNoDialog(null, "Delete Theme: " + fileTheme.getName(), + "Are you sure you want to delete theme " + fileTheme.getName()); + if (result == OptionDialog.YES_OPTION) { + themeManager.deleteTheme(fileTheme); + } + } + + private static String getNameFromUser(String name) { + InputDialog inputDialog = new InputDialog("Create Theme", "New Theme Name", name); + DockingWindowManager.showDialog(inputDialog); + return inputDialog.getValue(); + } + + private static boolean canSaveToName(ThemeManager themeManager, String name) { + GTheme existing = themeManager.getTheme(name); + // if no theme exists with that name, then we are save to save it + if (existing == null) { + return true; + } + // if the existing theme is a built-in theme, then we definitely can't save to that name + if (existing instanceof DiscoverableGTheme) { + return false; + } + // if the existing theme with that name has no associated file, we can save it without + // worrying about overwriting an existing file. + if (existing.getFile() == null) { + return true; + } + int result = OptionDialog.showYesNoDialog(null, "Overwrite Existing Theme?", + "Do you want to overwrite the existing theme file for \"" + name + "\"?"); + return result == OptionDialog.YES_OPTION; + } + + private static boolean saveCurrentValues(ThemeManager themeManager, String themeName) { + GTheme activeTheme = themeManager.getActiveTheme(); + File file = getSaveFile(themeName); + + GTheme newTheme = new GTheme(file, themeName, activeTheme.getLookAndFeelType(), + activeTheme.useDarkDefaults()); + newTheme.load(themeManager.getNonDefaultValues()); + try { + newTheme.save(); + themeManager.addTheme(newTheme); + themeManager.setTheme(newTheme); + } + catch (IOException e) { + Msg.showError(ThemeUtils.class, null, "I/O Error", + "Error writing theme file: " + newTheme.getFile().getAbsolutePath(), e); + return false; + } + + return true; + + } + + private static File getSaveFile(String themeName) { + File dir = Application.getUserSettingsDirectory(); + File themeDir = new File(dir, ThemeFileLoader.THEME_DIR); + if (!themeDir.exists()) { + themeDir.mkdir(); + } + String cleanedName = themeName.replaceAll(" ", "_") + "." + GTheme.FILE_EXTENSION; + return new File(themeDir, cleanedName); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java new file mode 100644 index 0000000000..068bd640ae --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java @@ -0,0 +1,159 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.beans.*; + +import javax.swing.*; + +import docking.DialogComponentProvider; +import docking.DockingWindowManager; +import generic.theme.ThemeValue; + +/** + * Base class for Theme property Editors (Colors, Fonts, and Icons) + * + * @param the base property (Color, Font, or Icon) + */ +public abstract class ThemeValueEditor { + private PropertyChangeListener clientListener; + protected ThemeValue currentThemeValue; + private EditorDialog dialog; + private String typeName; + protected PropertyEditor editor; + + /** + * Constructor + * + * @param typeName the name of the type (Used in the dialog title) + * @param listener the {@link PropertyChangeListener} to be notified for changes + * @param editor the standard property editor for the type + */ + protected ThemeValueEditor(String typeName, PropertyChangeListener listener, + PropertyEditor editor) { + this.typeName = typeName; + this.clientListener = listener; + this.editor = editor; + } + + /** + * Edits the ThemeValue by invoking the appropriate dialog for editing the type + * @param themeValue the value to be edited + */ + public void editValue(ThemeValue themeValue) { + this.currentThemeValue = themeValue; + if (dialog == null) { + dialog = new EditorDialog(themeValue); + DockingWindowManager.showDialog(dialog); + } + else { + dialog.setValue(themeValue); + dialog.toFront(); + } + + } + + /** + * Called when the user has pressed ok. This allows sub-classes to store any state for + * future dialog invocations. + */ + protected void storeState() { + // for sub-classes + } + + /** + * Returns the actual value (Color, Font, or Icon) + * @param id the theme property id for the value + * @return the current stored value for the id + */ + protected abstract T getRawValue(String id); + + /** + * Factory method for creating the ThemeValue of the correct type. + * @param id the id for theme property + * @param newValue the new value for the underlying type (Color, Font, or Icon) + * @return the new ThemeValue for the type + */ + protected abstract ThemeValue createNewThemeValue(String id, T newValue); + + private void valueChanged(T value) { + ThemeValue oldValue = currentThemeValue; + String id = oldValue.getId(); + ThemeValue newValue = createNewThemeValue(id, value); + firePropertyChangeEvent(oldValue, newValue); + PropertyChangeEvent event = + new PropertyChangeEvent(this, id, oldValue, newValue); + clientListener.propertyChange(event); + } + + private void firePropertyChangeEvent(ThemeValue oldValue, ThemeValue newValue) { + PropertyChangeEvent event = + new PropertyChangeEvent(this, oldValue.getId(), oldValue, newValue); + clientListener.propertyChange(event); + } + + class EditorDialog extends DialogComponentProvider { + private PropertyChangeListener internalListener = ev -> editorChanged(); + private ThemeValue originalValue; + + protected EditorDialog(ThemeValue initialValue) { + super("Edit " + typeName + ": " + currentThemeValue.getId(), false, false, true, false); + this.originalValue = initialValue; + addWorkPanel(buildWorkPanel(getRawValue(initialValue.getId()))); + addOKButton(); + addCancelButton(); + setRememberSize(false); + } + + @SuppressWarnings("unchecked") + private void editorChanged() { + valueChanged((T) editor.getValue()); + } + + JComponent buildWorkPanel(T initialValue) { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); + panel.add(editor.getCustomEditor(), BorderLayout.CENTER); + + editor.setValue(initialValue); + editor.addPropertyChangeListener(internalListener); + return panel; + } + + void setValue(ThemeValue