mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-1981 externalized icons for XTRA modules. Added loadIcon method in
ResourceManager. Created api for integrating Options with Theming. Fixed issue with system property mappings. Created dynamic icons for the close and drop-down menu item icons.
This commit is contained in:
parent
0971c0088c
commit
d466dbf06b
32 changed files with 637 additions and 260 deletions
|
@ -3,6 +3,7 @@
|
||||||
##MODULE IP: Oxygen Icons - LGPL 3.0
|
##MODULE IP: Oxygen Icons - LGPL 3.0
|
||||||
Module.manifest||GHIDRA||reviewed||END|
|
Module.manifest||GHIDRA||reviewed||END|
|
||||||
data/ExtensionPoint.manifest||GHIDRA||||END|
|
data/ExtensionPoint.manifest||GHIDRA||||END|
|
||||||
|
data/sample.plugin.theme.properties||GHIDRA||||END|
|
||||||
extension.properties||GHIDRA||||END|
|
extension.properties||GHIDRA||||END|
|
||||||
src/main/help/help/TOC_Source.xml||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/arrow.gif||GHIDRA||reviewed||END|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[Defaults]
|
||||||
|
icon.sample.plugin.action.show.options = table.png
|
||||||
|
icon.sample.plugin.action.save = disk.png
|
|
@ -27,6 +27,7 @@ import docking.action.*;
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
import docking.widgets.checkbox.GCheckBox;
|
||||||
import docking.widgets.filechooser.GhidraFileChooserPanel;
|
import docking.widgets.filechooser.GhidraFileChooserPanel;
|
||||||
import docking.widgets.table.GFilterTable;
|
import docking.widgets.table.GFilterTable;
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.framework.options.OptionsChangeListener;
|
import ghidra.framework.options.OptionsChangeListener;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||||
|
@ -34,7 +35,6 @@ import ghidra.framework.plugintool.util.OptionsService;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
import ghidra.util.layout.MiddleLayout;
|
import ghidra.util.layout.MiddleLayout;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
public class SampleTableProvider extends ComponentProviderAdapter implements OptionsChangeListener {
|
public class SampleTableProvider extends ComponentProviderAdapter implements OptionsChangeListener {
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ public class SampleTableProvider extends ComponentProviderAdapter implements Opt
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
ImageIcon icon = ResourceManager.loadImage("images/table.png");
|
Icon icon = new GIcon("icon.sample.plugin.action.show.options");
|
||||||
optionsAction.setToolBarData(new ToolBarData(icon));
|
optionsAction.setToolBarData(new ToolBarData(icon));
|
||||||
|
|
||||||
DockingAction saveTableDataAction = new DockingAction("Save Table Data", plugin.getName()) {
|
DockingAction saveTableDataAction = new DockingAction("Save Table Data", plugin.getName()) {
|
||||||
|
@ -189,7 +189,7 @@ public class SampleTableProvider extends ComponentProviderAdapter implements Opt
|
||||||
return SwingUtilities.isDescendingFrom((Component) sourceObject, filterTable);
|
return SwingUtilities.isDescendingFrom((Component) sourceObject, filterTable);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
icon = ResourceManager.loadImage("images/disk.png");
|
icon = new GIcon("icons.sample.plugin.action.save");
|
||||||
saveTableDataAction.setToolBarData(new ToolBarData(icon));
|
saveTableDataAction.setToolBarData(new ToolBarData(icon));
|
||||||
saveTableDataAction.setPopupMenuData(new MenuData(new String[] { "Save Data" }));
|
saveTableDataAction.setPopupMenuData(new MenuData(new String[] { "Save Data" }));
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
##MODULE IP: Oxygen Icons - LGPL 3.0
|
##MODULE IP: Oxygen Icons - LGPL 3.0
|
||||||
Module.manifest||GHIDRA||reviewed||END|
|
Module.manifest||GHIDRA||reviewed||END|
|
||||||
data/README.txt||GHIDRA||||END|
|
data/README.txt||GHIDRA||||END|
|
||||||
|
data/sample.theme.properties||GHIDRA||||END|
|
||||||
extension.properties||GHIDRA||||END|
|
extension.properties||GHIDRA||||END|
|
||||||
src/main/help/help/TOC_Source.xml||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/arrow.gif||GHIDRA||reviewed||END|
|
||||||
|
|
13
Ghidra/Extensions/sample/data/sample.theme.properties
Normal file
13
Ghidra/Extensions/sample/data/sample.theme.properties
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[Defaults]
|
||||||
|
icon.sample.provider = erase16.png
|
||||||
|
icon.sample.provider.graph = color_swatch.png
|
||||||
|
icon.sample.provider.hello.world = information.png
|
||||||
|
|
||||||
|
icon.sample.action.hello.world = information.png
|
||||||
|
icon.sample.kitchen.sink.action.hellow.world = left.png
|
||||||
|
icon.sample.kitchen.sink.action.hellow.program = right.png
|
||||||
|
|
||||||
|
icon.sample.action.show.graph = applications-development.png
|
||||||
|
|
||||||
|
icon.sample.graph.dependency.layout = color_swatch.png
|
||||||
|
icon.sample.hello.world.action.clear = erase16.png
|
|
@ -24,14 +24,13 @@ import docking.ActionContext;
|
||||||
import docking.WindowPosition;
|
import docking.WindowPosition;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.widgets.EmptyBorderButton;
|
import docking.widgets.EmptyBorderButton;
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
public class HelloWorldComponentProvider extends ComponentProviderAdapter {
|
public class HelloWorldComponentProvider extends ComponentProviderAdapter {
|
||||||
private final static String PREV_IMAGE = "images/information.png";
|
|
||||||
private final static HelpLocation HELP = new HelpLocation("SampleHelpTopic",
|
private final static HelpLocation HELP = new HelpLocation("SampleHelpTopic",
|
||||||
"SampleHelpTopic_Anchor_Name");
|
"SampleHelpTopic_Anchor_Name");
|
||||||
private MyButton activeButtonObj;
|
private MyButton activeButtonObj;
|
||||||
|
@ -41,7 +40,7 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter {
|
||||||
public HelloWorldComponentProvider(PluginTool tool, String name) {
|
public HelloWorldComponentProvider(PluginTool tool, String name) {
|
||||||
super(tool, name, name);
|
super(tool, name, name);
|
||||||
buildMainPanel();
|
buildMainPanel();
|
||||||
setIcon(ResourceManager.loadImage("images/erase16.png"));
|
setIcon(new GIcon("icon.sample.provider"));
|
||||||
setHelpLocation(HELP);
|
setHelpLocation(HELP);
|
||||||
setDefaultWindowPosition(WindowPosition.WINDOW);
|
setDefaultWindowPosition(WindowPosition.WINDOW);
|
||||||
setTitle("Hello World Component");
|
setTitle("Hello World Component");
|
||||||
|
@ -64,13 +63,13 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
// put in Menu called "Hello", with Menu item of "World". Since this will be a local action
|
// put in Menu called "Hello", with Menu item of "World". Since this will be a local action
|
||||||
// the menu item will appear on the local toolbar drop down.
|
// the menu item will appear on the local toolbar drop down.
|
||||||
ImageIcon prevImage = ResourceManager.loadImage(PREV_IMAGE);
|
Icon icon = new GIcon("icon.sample.action.hello.world");
|
||||||
action.setMenuBarData(new MenuData(new String[] { "Misc", "Hello World" }, prevImage));
|
action.setMenuBarData(new MenuData(new String[] { "Misc", "Hello World" }, icon));
|
||||||
action.setKeyBindingData(new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_W,
|
action.setKeyBindingData(new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_W,
|
||||||
InputEvent.CTRL_MASK)));
|
InputEvent.CTRL_MASK)));
|
||||||
|
|
||||||
// puts the action on the local toolbar.
|
// puts the action on the local toolbar.
|
||||||
action.setToolBarData(new ToolBarData(prevImage));
|
action.setToolBarData(new ToolBarData(icon));
|
||||||
action.setDescription("Hello World");
|
action.setDescription("Hello World");
|
||||||
|
|
||||||
// set the help URL for the action
|
// set the help URL for the action
|
||||||
|
|
|
@ -15,6 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.examples;
|
package ghidra.examples;
|
||||||
|
|
||||||
|
import java.awt.Event;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.action.*;
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.app.ExamplesPluginPackage;
|
import ghidra.app.ExamplesPluginPackage;
|
||||||
import ghidra.app.events.ProgramLocationPluginEvent;
|
import ghidra.app.events.ProgramLocationPluginEvent;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
|
@ -28,15 +36,6 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
import java.awt.Event;
|
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import resources.ResourceManager;
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class description goes here
|
* Class description goes here
|
||||||
*
|
*
|
||||||
|
@ -54,8 +53,6 @@ import docking.action.*;
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class KitchenSinkPlugin extends ProgramPlugin {
|
public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
private final static String NEXT_IMAGE = "images/right.png";
|
|
||||||
private final static String PREV_IMAGE = "images/left.png";
|
|
||||||
|
|
||||||
private DockingAction helloProgramAction;
|
private DockingAction helloProgramAction;
|
||||||
private Program program;
|
private Program program;
|
||||||
|
@ -84,37 +81,41 @@ public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupActions() {
|
private void setupActions() {
|
||||||
DockingAction action = new DockingAction("Hello World", getName() ) {
|
DockingAction action = new DockingAction("Hello World", getName()) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed( ActionContext context ) {
|
public void actionPerformed(ActionContext context) {
|
||||||
Msg.info(this, "Hello World:: action");
|
Msg.info(this, "Hello World:: action");
|
||||||
announce("Hello World");
|
announce("Hello World");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
action.setEnabled( true );
|
action.setEnabled(true);
|
||||||
String helloGroup = "Hello";
|
String helloGroup = "Hello";
|
||||||
ImageIcon prevImage = ResourceManager.loadImage(PREV_IMAGE);
|
Icon prevImage = new GIcon("icon.sample.kitchen.sink.action.hello.world");
|
||||||
action.setMenuBarData( new MenuData( new String[] {"Misc", "Hello World"}, prevImage, helloGroup ) );
|
action.setMenuBarData(
|
||||||
action.setPopupMenuData( new MenuData( new String[] {"Hello World"}, prevImage, helloGroup ) );
|
new MenuData(new String[] { "Misc", "Hello World" }, prevImage, helloGroup));
|
||||||
action.setKeyBindingData( new KeyBindingData( KeyStroke.getKeyStroke('H', Event.CTRL_MASK ) ) );
|
action.setPopupMenuData(
|
||||||
action.setToolBarData( new ToolBarData( prevImage, helloGroup ) );
|
new MenuData(new String[] { "Hello World" }, prevImage, helloGroup));
|
||||||
|
action.setKeyBindingData(new KeyBindingData(KeyStroke.getKeyStroke('H', Event.CTRL_MASK)));
|
||||||
|
action.setToolBarData(new ToolBarData(prevImage, helloGroup));
|
||||||
action.setDescription("Hello World");
|
action.setDescription("Hello World");
|
||||||
action.setHelpLocation(new HelpLocation("SampleHelpTopic", "KS_Hello_World"));
|
action.setHelpLocation(new HelpLocation("SampleHelpTopic", "KS_Hello_World"));
|
||||||
|
|
||||||
tool.addAction(action);
|
tool.addAction(action);
|
||||||
|
|
||||||
action = new DockingAction("Hello Program", getName() ) {
|
action = new DockingAction("Hello Program", getName()) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed( ActionContext context ) {
|
public void actionPerformed(ActionContext context) {
|
||||||
Msg.info(this, "Hello Program:: action");
|
Msg.info(this, "Hello Program:: action");
|
||||||
sayHelloProgram();
|
sayHelloProgram();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
action.setEnabled(false);
|
action.setEnabled(false);
|
||||||
ImageIcon nextImage = ResourceManager.loadImage(NEXT_IMAGE);
|
Icon nextImage = new GIcon("icon.sample.kitchen.sink.action.hello.program");
|
||||||
action.setMenuBarData( new MenuData( new String[]{"Misc", "Hello Program"}, nextImage, helloGroup ) );
|
action.setMenuBarData(
|
||||||
action.setKeyBindingData( new KeyBindingData( KeyStroke.getKeyStroke(KeyEvent.VK_P, Event.CTRL_MASK ) ) );
|
new MenuData(new String[] { "Misc", "Hello Program" }, nextImage, helloGroup));
|
||||||
action.setToolBarData( new ToolBarData( nextImage, helloGroup ) );
|
action.setKeyBindingData(
|
||||||
|
new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_P, Event.CTRL_MASK)));
|
||||||
|
action.setToolBarData(new ToolBarData(nextImage, helloGroup));
|
||||||
action.setDescription("Hello Program");
|
action.setDescription("Hello Program");
|
||||||
action.setHelpLocation(new HelpLocation("SampleHelpTopic", "KS_Hello_Program"));
|
action.setHelpLocation(new HelpLocation("SampleHelpTopic", "KS_Hello_Program"));
|
||||||
tool.addAction(action);
|
tool.addAction(action);
|
||||||
|
@ -128,6 +129,7 @@ public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
helloProgramAction.setEnabled(true);
|
helloProgramAction.setEnabled(true);
|
||||||
this.program = activatedProgram;
|
this.program = activatedProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void programDeactivated(Program deactivatedProgram) {
|
protected void programDeactivated(Program deactivatedProgram) {
|
||||||
if (this.program == deactivatedProgram) {
|
if (this.program == deactivatedProgram) {
|
||||||
|
@ -135,6 +137,7 @@ public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
this.program = null;
|
this.program = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sayHelloProgram() {
|
protected void sayHelloProgram() {
|
||||||
|
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
|
@ -145,7 +148,7 @@ public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void announce(String message) {
|
protected void announce(String message) {
|
||||||
JOptionPane.showMessageDialog(null,message,"Hello World",
|
JOptionPane.showMessageDialog(null, message, "Hello World",
|
||||||
JOptionPane.INFORMATION_MESSAGE);
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +161,7 @@ public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void writeConfigState(SaveState saveState) {
|
public void writeConfigState(SaveState saveState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If your plugin maintains configuration state, this is where you read it
|
* If your plugin maintains configuration state, this is where you read it
|
||||||
* back in.
|
* back in.
|
||||||
|
@ -166,8 +170,3 @@ public class KitchenSinkPlugin extends ProgramPlugin {
|
||||||
public void readConfigState(SaveState saveState) {
|
public void readConfigState(SaveState saveState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,15 @@ import docking.ActionContext;
|
||||||
import docking.WindowPosition;
|
import docking.WindowPosition;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
import docking.action.ToolBarData;
|
import docking.action.ToolBarData;
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
public class ShowInfoComponentProvider extends ComponentProviderAdapter {
|
public class ShowInfoComponentProvider extends ComponentProviderAdapter {
|
||||||
private final static ImageIcon CLEAR_ICON = ResourceManager.loadImage("images/erase16.png");
|
private final static Icon CLEAR_ICON = new GIcon("icon.sample.hello.world.action.clear");
|
||||||
private final static ImageIcon INFO_ICON = ResourceManager.loadImage("images/information.png");
|
private final static Icon PROVIDER_ICON = new GIcon("icon.sample.provider.hello.world");
|
||||||
|
|
||||||
private JPanel panel;
|
private JPanel panel;
|
||||||
private JTextArea textArea;
|
private JTextArea textArea;
|
||||||
|
@ -42,7 +42,7 @@ public class ShowInfoComponentProvider extends ComponentProviderAdapter {
|
||||||
public ShowInfoComponentProvider(PluginTool tool, String name) {
|
public ShowInfoComponentProvider(PluginTool tool, String name) {
|
||||||
super(tool, name, name);
|
super(tool, name, name);
|
||||||
create();
|
create();
|
||||||
setIcon(INFO_ICON);
|
setIcon(PROVIDER_ICON);
|
||||||
setDefaultWindowPosition(WindowPosition.BOTTOM);
|
setDefaultWindowPosition(WindowPosition.BOTTOM);
|
||||||
setTitle("Show Info");
|
setTitle("Show Info");
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
|
|
@ -15,17 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.examples.graph;
|
package ghidra.examples.graph;
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
import docking.action.ToolBarData;
|
import docking.action.ToolBarData;
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.app.ExamplesPluginPackage;
|
import ghidra.app.ExamplesPluginPackage;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
import ghidra.framework.plugintool.util.PluginStatus;
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sample plugin to demonstrate a plugin with a dockable GUI graph component
|
* Sample plugin to demonstrate a plugin with a dockable GUI graph component
|
||||||
|
@ -64,8 +64,7 @@ public class SampleGraphPlugin extends Plugin {
|
||||||
showProvider();
|
showProvider();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Icon icon = new GIcon("icon.sample.action.show.graph");
|
||||||
ImageIcon icon = ResourceManager.loadImage("images/applications-development.png");
|
|
||||||
showProviderAction.setToolBarData(new ToolBarData(icon, "View"));
|
showProviderAction.setToolBarData(new ToolBarData(icon, "View"));
|
||||||
showProviderAction.setHelpLocation(DEFAULT_HELP);
|
showProviderAction.setHelpLocation(DEFAULT_HELP);
|
||||||
tool.addAction(showProviderAction);
|
tool.addAction(showProviderAction);
|
||||||
|
@ -75,7 +74,6 @@ public class SampleGraphPlugin extends Plugin {
|
||||||
provider.setVisible(true);
|
provider.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dispose() {
|
protected void dispose() {
|
||||||
provider.dispose();
|
provider.dispose();
|
||||||
|
|
|
@ -21,12 +21,12 @@ import java.util.Collection;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import edu.uci.ics.jung.algorithms.layout.Layout;
|
import edu.uci.ics.jung.algorithms.layout.Layout;
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.examples.graph.*;
|
import ghidra.examples.graph.*;
|
||||||
import ghidra.graph.viewer.layout.AbstractLayoutProvider;
|
import ghidra.graph.viewer.layout.AbstractLayoutProvider;
|
||||||
import ghidra.graph.viewer.layout.VisualGraphLayout;
|
import ghidra.graph.viewer.layout.VisualGraphLayout;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layout provider for the {@link SampleGraphPlugin}.
|
* The layout provider for the {@link SampleGraphPlugin}.
|
||||||
|
@ -34,7 +34,7 @@ import resources.ResourceManager;
|
||||||
public abstract class SampleGraphLayoutProvider
|
public abstract class SampleGraphLayoutProvider
|
||||||
extends AbstractLayoutProvider<SampleVertex, SampleEdge, SampleGraph> {
|
extends AbstractLayoutProvider<SampleVertex, SampleEdge, SampleGraph> {
|
||||||
|
|
||||||
private static final Icon DEFAULT_ICON = ResourceManager.loadImage("images/color_swatch.png");
|
private static final Icon DEFAULT_ICON = new GIcon("icon.sample.provider.graph");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract VisualGraphLayout<SampleVertex, SampleEdge> getLayout(SampleGraph g,
|
public abstract VisualGraphLayout<SampleVertex, SampleEdge> getLayout(SampleGraph g,
|
||||||
|
|
|
@ -17,12 +17,12 @@ package ghidra.examples.graph.layout;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import generic.theme.GIcon;
|
||||||
import ghidra.examples.graph.*;
|
import ghidra.examples.graph.*;
|
||||||
import ghidra.graph.viewer.layout.AbstractLayoutProvider;
|
import ghidra.graph.viewer.layout.AbstractLayoutProvider;
|
||||||
import ghidra.graph.viewer.layout.VisualGraphLayout;
|
import ghidra.graph.viewer.layout.VisualGraphLayout;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A layout provider for the {@link SampleGraphPlugin}
|
* A layout provider for the {@link SampleGraphPlugin}
|
||||||
|
@ -31,7 +31,7 @@ public class SampleGraphPluginDependencyLayoutProvider
|
||||||
extends AbstractLayoutProvider<SampleVertex, SampleEdge, SampleGraph> {
|
extends AbstractLayoutProvider<SampleVertex, SampleEdge, SampleGraph> {
|
||||||
|
|
||||||
private static final String NAME = "Plugin Dependency Layout";
|
private static final String NAME = "Plugin Dependency Layout";
|
||||||
private static final Icon DEFAULT_ICON = ResourceManager.loadImage("images/color_swatch.png");
|
private static final Icon DEFAULT_ICON = new GIcon("icon.sample.graph.dependency.layout");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VisualGraphLayout<SampleVertex, SampleEdge> getLayout(SampleGraph g, TaskMonitor monitor)
|
public VisualGraphLayout<SampleVertex, SampleEdge> getLayout(SampleGraph g, TaskMonitor monitor)
|
||||||
|
|
|
@ -94,8 +94,6 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
||||||
private int searchLimit;
|
private int searchLimit;
|
||||||
private static final Icon SEARCH_MARKER_ICON = new GIcon("icon.base.search.marker");
|
private static final Icon SEARCH_MARKER_ICON = new GIcon("icon.base.search.marker");
|
||||||
|
|
||||||
private Color defaultHighlightColor;
|
|
||||||
private Color activeHighlightColor;
|
|
||||||
private boolean doHighlight;
|
private boolean doHighlight;
|
||||||
private int byteGroupSize;
|
private int byteGroupSize;
|
||||||
private String byteDelimiter;
|
private String byteDelimiter;
|
||||||
|
@ -389,10 +387,10 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
||||||
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_NAME, true, null,
|
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_NAME, true, null,
|
||||||
"Toggles highlight search results");
|
"Toggles highlight search results");
|
||||||
|
|
||||||
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME,
|
opt.registerThemeColorOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_OPTION_NAME,
|
||||||
PluginConstants.SEARCH_HIGHLIGHT_COLOR, null, "The search result highlight color");
|
PluginConstants.SEARCH_HIGHLIGHT_COLOR_ID, null, "The search result highlight color");
|
||||||
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME,
|
opt.registerThemeColorOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_OPTION_NAME,
|
||||||
PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR, null,
|
PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_ID, null,
|
||||||
"The search result highlight color for the currently selected match");
|
"The search result highlight color for the currently selected match");
|
||||||
|
|
||||||
opt.addOptionsChangeListener(this);
|
opt.addOptionsChangeListener(this);
|
||||||
|
@ -413,10 +411,6 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
||||||
prepopulateSearch = opt.getBoolean(PluginConstants.PRE_POPULATE_MEM_SEARCH, true);
|
prepopulateSearch = opt.getBoolean(PluginConstants.PRE_POPULATE_MEM_SEARCH, true);
|
||||||
autoRestrictSelection = opt.getBoolean(PluginConstants.AUTO_RESTRICT_SELECTION, true);
|
autoRestrictSelection = opt.getBoolean(PluginConstants.AUTO_RESTRICT_SELECTION, true);
|
||||||
doHighlight = opt.getBoolean(PluginConstants.SEARCH_HIGHLIGHT_NAME, 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);
|
opt = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS);
|
||||||
byteGroupSize = opt.getInt(BytesFieldFactory.BYTE_GROUP_SIZE_MSG, 1);
|
byteGroupSize = opt.getInt(BytesFieldFactory.BYTE_GROUP_SIZE_MSG, 1);
|
||||||
|
@ -747,7 +741,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
||||||
private Color getHighlightColor(Address highlightStart, int highlightLength) {
|
private Color getHighlightColor(Address highlightStart, int highlightLength) {
|
||||||
ProgramLocation location = navigatable != null ? navigatable.getLocation() : null;
|
ProgramLocation location = navigatable != null ? navigatable.getLocation() : null;
|
||||||
if (!(location instanceof BytesFieldLocation)) {
|
if (!(location instanceof BytesFieldLocation)) {
|
||||||
return defaultHighlightColor;
|
return PluginConstants.SEARCH_HIGHLIGHT_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
BytesFieldLocation byteLoc = (BytesFieldLocation) location;
|
BytesFieldLocation byteLoc = (BytesFieldLocation) location;
|
||||||
|
@ -755,11 +749,12 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
||||||
if (highlightStart.hasSameAddressSpace(byteAddress)) {
|
if (highlightStart.hasSameAddressSpace(byteAddress)) {
|
||||||
long diff = byteAddress.subtract(highlightStart);
|
long diff = byteAddress.subtract(highlightStart);
|
||||||
if (diff >= 0 && diff < highlightLength) {
|
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() {
|
private boolean checkRemoveHighlights() {
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.searchtext;
|
package ghidra.app.plugin.core.searchtext;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.Component;
|
||||||
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -99,8 +100,6 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
||||||
private int searchLimit;
|
private int searchLimit;
|
||||||
private SearchTask currentTask;
|
private SearchTask currentTask;
|
||||||
private String lastSearchedText;
|
private String lastSearchedText;
|
||||||
private Color highlightColor;
|
|
||||||
private Color currentAddrHighlightColor;
|
|
||||||
private boolean doHighlight;
|
private boolean doHighlight;
|
||||||
private Navigatable navigatable;
|
private Navigatable navigatable;
|
||||||
|
|
||||||
|
@ -424,12 +423,6 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
||||||
}
|
}
|
||||||
searchLimit = newSearchLimit;
|
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)) {
|
else if (optionName.equals(PluginConstants.SEARCH_HIGHLIGHT_NAME)) {
|
||||||
doHighlight = ((Boolean) newValue).booleanValue();
|
doHighlight = ((Boolean) newValue).booleanValue();
|
||||||
}
|
}
|
||||||
|
@ -442,22 +435,16 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
||||||
|
|
||||||
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_NAME, true, loc,
|
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_NAME, true, loc,
|
||||||
"Determines whether to highlight the matched string for a search in the listing.");
|
"Determines whether to highlight the matched string for a search in the listing.");
|
||||||
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME,
|
opt.registerThemeColorOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_OPTION_NAME,
|
||||||
PluginConstants.SEARCH_HIGHLIGHT_COLOR, loc,
|
PluginConstants.SEARCH_HIGHLIGHT_COLOR_ID, null, "The search result highlight color");
|
||||||
"Color to use when highlighting the matched string for a search in the listing.");
|
opt.registerThemeColorOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_OPTION_NAME,
|
||||||
opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME,
|
PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_ID, null,
|
||||||
PluginConstants.SEARCH_HIGHLIGHT_COLOR, loc,
|
"The search result highlight color for the currently selected match");
|
||||||
"Color to use for highlighting when the match string occurs at the current address.");
|
|
||||||
|
|
||||||
searchLimit =
|
searchLimit =
|
||||||
opt.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, PluginConstants.DEFAULT_SEARCH_LIMIT);
|
opt.getInt(GhidraOptions.OPTION_SEARCH_LIMIT, PluginConstants.DEFAULT_SEARCH_LIMIT);
|
||||||
|
|
||||||
doHighlight = opt.getBoolean(PluginConstants.SEARCH_HIGHLIGHT_NAME, true);
|
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"));
|
opt.setOptionsHelpLocation(new HelpLocation(HelpTopics.SEARCH, "Search_Text"));
|
||||||
|
|
||||||
|
@ -661,12 +648,14 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
||||||
int start = matcher.start();
|
int start = matcher.start();
|
||||||
int end = matcher.end() - 1;
|
int end = matcher.end() - 1;
|
||||||
if (start <= cursorTextOffset && end >= cursorTextOffset) {
|
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
|
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
|
// meaning that this is a one at a time search and not a table
|
||||||
// of results.
|
// of results.
|
||||||
list.add(new Highlight(start, end, highlightColor));
|
list.add(new Highlight(start, end,
|
||||||
|
PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,17 +77,10 @@ public interface PluginConstants {
|
||||||
* Name of the Options object for Search.
|
* Name of the Options object for Search.
|
||||||
*/
|
*/
|
||||||
public static final String SEARCH_OPTION_NAME = "Search";
|
public static final String SEARCH_OPTION_NAME = "Search";
|
||||||
/**
|
|
||||||
* Option name for highlight color
|
|
||||||
*/
|
|
||||||
public static final String SEARCH_HIGHLIGHT_COLOR_NAME = " Highlight Color";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option name for highlight color used when something to highlight is at the current
|
* Option name for highlight color used when something to highlight is at the current
|
||||||
* address.
|
* address.
|
||||||
*/
|
*/
|
||||||
public static final String SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME =
|
|
||||||
"Highlight Color for Current Match";
|
|
||||||
/**
|
/**
|
||||||
* Option name for whether to highlight search results.
|
* Option name for whether to highlight search results.
|
||||||
*/
|
*/
|
||||||
|
@ -96,13 +89,19 @@ public interface PluginConstants {
|
||||||
/**
|
/**
|
||||||
* Color for highlighting for searches.
|
* Color for highlighting for searches.
|
||||||
*/
|
*/
|
||||||
public static final Color SEARCH_HIGHLIGHT_COLOR = new GColor("color.bg.search.highlight");
|
public static final String SEARCH_HIGHLIGHT_COLOR_OPTION_NAME = " Highlight Color";
|
||||||
|
public static final String SEARCH_HIGHLIGHT_COLOR_ID = "color.bg.search.highlight";
|
||||||
|
public static final Color SEARCH_HIGHLIGHT_COLOR = new GColor(SEARCH_HIGHLIGHT_COLOR_ID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default highlight color used when something to highlight is at the current
|
* Default highlight color used when something to highlight is at the current
|
||||||
* address.
|
* address.
|
||||||
*/
|
*/
|
||||||
|
public static final String SEARCH_HIGHLIGHT_CURRENT_COLOR_OPTION_NAME =
|
||||||
|
"Highlight Color for Current Match";
|
||||||
|
public static final String SEARCH_HIGHLIGHT_CURRENT_COLOR_ID =
|
||||||
|
"color.bg.search.current.line.highlight";
|
||||||
public static final Color SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR =
|
public static final Color SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR =
|
||||||
new GColor("color.bg.search.current.line.highlight");
|
new GColor(SEARCH_HIGHLIGHT_CURRENT_COLOR_ID);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ color.fg.fieldpanel = color.fg
|
||||||
color.bg.fieldpanel.selection = color.bg.selection
|
color.bg.fieldpanel.selection = color.bg.selection
|
||||||
color.bg.fieldpanel.highlight = color.bg.highlight
|
color.bg.fieldpanel.highlight = color.bg.highlight
|
||||||
color.bg.fieldpanel.selection.and.highlight = green
|
color.bg.fieldpanel.selection.and.highlight = green
|
||||||
|
// docking buttons
|
||||||
|
color.fg.button = black
|
||||||
|
|
||||||
// Icons files
|
// Icons files
|
||||||
icon.empty = EmptyIcon16.gif
|
icon.empty = EmptyIcon16.gif
|
||||||
|
@ -207,4 +209,6 @@ color.bg.tableheader.gradient.end = darkGray
|
||||||
color.bg.tableheader.gradient.start.primary = color.bg
|
color.bg.tableheader.gradient.start.primary = color.bg
|
||||||
color.bg.tableheader.gradient.end.primary = darkBlue
|
color.bg.tableheader.gradient.end.primary = darkBlue
|
||||||
|
|
||||||
|
// docking buttons
|
||||||
|
color.fg.button = darkGray
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* ###
|
||||||
|
* 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 javax.swing.Icon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon for a close button
|
||||||
|
*/
|
||||||
|
public class CloseIcon implements Icon {
|
||||||
|
private int size;
|
||||||
|
private int margin;
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a close icon.
|
||||||
|
* @param size the width and height of the icon
|
||||||
|
* @param margin the margin around the "x"
|
||||||
|
* @param color the color of the "x"
|
||||||
|
*/
|
||||||
|
public CloseIcon(int size, int margin, Color color) {
|
||||||
|
this.size = size;
|
||||||
|
this.margin = margin;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||||
|
g.setColor(color);
|
||||||
|
int xStart = x + margin;
|
||||||
|
int yStart = y + margin;
|
||||||
|
int xEnd = x + size - margin;
|
||||||
|
int yEnd = y + size - margin;
|
||||||
|
g.drawLine(xStart, yStart, xEnd, yEnd);
|
||||||
|
g.drawLine(xStart, yEnd, xEnd, yStart);
|
||||||
|
g.drawLine(xStart + 1, yStart, xEnd + 1, yEnd);
|
||||||
|
g.drawLine(xStart + 1, yEnd, xEnd + 1, yStart);
|
||||||
|
g.drawLine(xStart - 1, yStart, xEnd - 1, yEnd);
|
||||||
|
g.drawLine(xStart - 1, yEnd, xEnd - 1, yStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconWidth() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconHeight() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package docking;
|
package docking;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.*;
|
||||||
import java.awt.FlowLayout;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
@ -24,17 +23,17 @@ import javax.swing.*;
|
||||||
|
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.menu.*;
|
import docking.menu.*;
|
||||||
|
import generic.theme.GColor;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.task.SwingUpdateManager;
|
import ghidra.util.task.SwingUpdateManager;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages to toolbar for the dockable components.
|
* Manages to toolbar for the dockable components.
|
||||||
*/
|
*/
|
||||||
class DockableToolBarManager {
|
class DockableToolBarManager {
|
||||||
private static final ImageIcon CLOSE_ICON = ResourceManager.loadImage("images/close16.gif");
|
private static final Color BUTTON_COLOR = new GColor("color.fg.button");
|
||||||
private static final ImageIcon MENU_ICON = ResourceManager.loadImage("images/menu16.gif");
|
private static final Icon CLOSE_ICON = new CloseIcon(16, 4, BUTTON_COLOR);
|
||||||
|
private static final Icon MENU_ICON = new DropDownMenuIcon(16, 4, 4, BUTTON_COLOR);
|
||||||
private GenericHeader dockableHeader;
|
private GenericHeader dockableHeader;
|
||||||
private ToolBarManager toolBarManager;
|
private ToolBarManager toolBarManager;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/* ###
|
||||||
|
* 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 javax.swing.Icon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon for a drop down menu button (triangle pointing down)
|
||||||
|
*/
|
||||||
|
public class DropDownMenuIcon implements Icon {
|
||||||
|
private int size;
|
||||||
|
private int xMargin;
|
||||||
|
private int yMargin;
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a drop down menu icon.
|
||||||
|
* @param size the width and height of the icon
|
||||||
|
* @param xMargin the margin around triangle base
|
||||||
|
* @param yMargin the margin around triangle height
|
||||||
|
* @param color the color of the triangle
|
||||||
|
*/
|
||||||
|
public DropDownMenuIcon(int size, int xMargin, int yMargin, Color color) {
|
||||||
|
this.size = size;
|
||||||
|
this.xMargin = xMargin;
|
||||||
|
this.yMargin = yMargin;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||||
|
g.setColor(color);
|
||||||
|
|
||||||
|
// draw a triangle pointing down
|
||||||
|
int p1x = x + size / 2;
|
||||||
|
int p1y = y + size - yMargin;
|
||||||
|
int p2x = x + xMargin;
|
||||||
|
int p2y = y + yMargin;
|
||||||
|
int p3x = x + size - xMargin + 1;
|
||||||
|
int p3y = y + yMargin;
|
||||||
|
int xPoints[] = { p1x, p2x, p3x };
|
||||||
|
int yPoints[] = { p1y, p2y, p3y };
|
||||||
|
g.fillPolygon(xPoints, yPoints, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconWidth() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconHeight() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,7 +21,6 @@ import java.util.Hashtable;
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import generic.Images;
|
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
import resources.icons.UnresolvedIcon;
|
import resources.icons.UnresolvedIcon;
|
||||||
|
|
||||||
|
@ -66,7 +65,7 @@ public class ToolIconURL implements Comparable<ToolIconURL> {
|
||||||
*/
|
*/
|
||||||
public ToolIconURL(String location) {
|
public ToolIconURL(String location) {
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
location = Images.BOMB;
|
location = ResourceManager.BOMB;
|
||||||
}
|
}
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
|
||||||
|
@ -168,7 +167,7 @@ public class ToolIconURL implements Comparable<ToolIconURL> {
|
||||||
// O.K., we will scale the icon. However, if it is the default icon, we know we have
|
// O.K., we will scale the icon. However, if it is the default icon, we know we have
|
||||||
// a 'large' version of that.
|
// a 'large' version of that.
|
||||||
if (unscaledIcon instanceof UnresolvedIcon) {
|
if (unscaledIcon instanceof UnresolvedIcon) {
|
||||||
return ResourceManager.loadImage(Images.BIG_BOMB);
|
return ResourceManager.loadImage(ResourceManager.BIG_BOMB);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResourceManager.getScaledIcon(unscaledIcon, LARGE_ICON_SIZE, LARGE_ICON_SIZE);
|
return ResourceManager.getScaledIcon(unscaledIcon, LARGE_ICON_SIZE, LARGE_ICON_SIZE);
|
||||||
|
|
|
@ -1,22 +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 generic;
|
|
||||||
|
|
||||||
public class Images {
|
|
||||||
public static String BOMB = "images/core.png";
|
|
||||||
public static String BIG_BOMB = "images/core24.png";
|
|
||||||
}
|
|
|
@ -99,7 +99,8 @@ public abstract class AbstractThemeReader {
|
||||||
return IconValue.parse(key, value);
|
return IconValue.parse(key, value);
|
||||||
}
|
}
|
||||||
catch (ParseException e) {
|
catch (ParseException e) {
|
||||||
error(lineNumber, "Could not parse Icon value: " + value + "because " + e.getMessage());
|
error(lineNumber,
|
||||||
|
"Could not parse Icon value: \"" + value + "\" because: " + e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class Gui {
|
||||||
private static GThemeValueMap applicationDarkDefaults = new GThemeValueMap();
|
private static GThemeValueMap applicationDarkDefaults = new GThemeValueMap();
|
||||||
private static GThemeValueMap javaDefaults = new GThemeValueMap();
|
private static GThemeValueMap javaDefaults = new GThemeValueMap();
|
||||||
private static GThemeValueMap currentValues = new GThemeValueMap();
|
private static GThemeValueMap currentValues = new GThemeValueMap();
|
||||||
|
private static GThemeValueMap systemValues = new GThemeValueMap();
|
||||||
|
|
||||||
private static ThemeFileLoader themeFileLoader = new ThemeFileLoader();
|
private static ThemeFileLoader themeFileLoader = new ThemeFileLoader();
|
||||||
private static ThemePreferenceManager themePreferenceManager = new ThemePreferenceManager();
|
private static ThemePreferenceManager themePreferenceManager = new ThemePreferenceManager();
|
||||||
|
@ -114,6 +115,72 @@ public class Gui {
|
||||||
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
|
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the current color value for the given color id to the value established by the
|
||||||
|
* current theme.
|
||||||
|
* @param id the color id to restore back to the original theme value
|
||||||
|
*/
|
||||||
|
public static void restoreColor(String id) {
|
||||||
|
if (changedValuesMap.containsColor(id)) {
|
||||||
|
Gui.setColor(changedValuesMap.getColor(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the current font value for the given font id to the value established by the
|
||||||
|
* current theme.
|
||||||
|
* @param id the font id to restore back to the original theme value
|
||||||
|
*/
|
||||||
|
public static void restoreFont(String id) {
|
||||||
|
if (changedValuesMap.containsFont(id)) {
|
||||||
|
Gui.setFont(changedValuesMap.getFont(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the current icon value for the given icon id to the value established by the
|
||||||
|
* current theme.
|
||||||
|
* @param id the icon id to restore back to the original theme value
|
||||||
|
*/
|
||||||
|
public static void restoreIcon(String id) {
|
||||||
|
if (changedValuesMap.containsIcon(id)) {
|
||||||
|
Gui.setIcon(changedValuesMap.getIcon(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the color associated with the given id has been changed from the current
|
||||||
|
* theme value for that id.
|
||||||
|
* @param id the color id to check if it has been changed
|
||||||
|
* @return true if the color associated with the given id has been changed from the current
|
||||||
|
* theme value for that id.
|
||||||
|
*/
|
||||||
|
public static boolean isChangedColor(String id) {
|
||||||
|
return changedValuesMap.containsColor(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the font associated with the given id has been changed from the current
|
||||||
|
* theme value for that id.
|
||||||
|
* @param id the font id to check if it has been changed
|
||||||
|
* @return true if the font associated with the given id has been changed from the current
|
||||||
|
* theme value for that id.
|
||||||
|
*/
|
||||||
|
public static boolean isChangedFont(String id) {
|
||||||
|
return changedValuesMap.containsFont(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the Icon associated with the given id has been changed from the current
|
||||||
|
* theme value for that id.
|
||||||
|
* @param id the Icon id to check if it has been changed
|
||||||
|
* @return true if the Icon associated with the given id has been changed from the current
|
||||||
|
* theme value for that id.
|
||||||
|
*/
|
||||||
|
public static boolean isChangedIcon(String id) {
|
||||||
|
return changedValuesMap.containsIcon(id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the application's active theme to the given theme.
|
* Sets the application's active theme to the given theme.
|
||||||
* @param theme the theme to make active
|
* @param theme the theme to make active
|
||||||
|
@ -125,8 +192,8 @@ public class Gui {
|
||||||
lookAndFeelManager = lookAndFeel.getLookAndFeelManager();
|
lookAndFeelManager = lookAndFeel.getLookAndFeelManager();
|
||||||
try {
|
try {
|
||||||
lookAndFeelManager.installLookAndFeel();
|
lookAndFeelManager.installLookAndFeel();
|
||||||
notifyThemeChanged(new AllValuesChangedThemeEvent(true));
|
|
||||||
themePreferenceManager.saveThemeToPreferences(theme);
|
themePreferenceManager.saveThemeToPreferences(theme);
|
||||||
|
notifyThemeChanged(new AllValuesChangedThemeEvent(true));
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Msg.error(Gui.class,
|
Msg.error(Gui.class,
|
||||||
|
@ -388,6 +455,10 @@ public class Gui {
|
||||||
return gIcon;
|
return gIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setSystemDefaults(GThemeValueMap map) {
|
||||||
|
systemValues = map;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the map of JavaDefaults defined by the current {@link LookAndFeel}.
|
* Sets the map of JavaDefaults defined by the current {@link LookAndFeel}.
|
||||||
* @param map the default theme values defined by the {@link LookAndFeel}
|
* @param map the default theme values defined by the {@link LookAndFeel}
|
||||||
|
@ -442,6 +513,7 @@ public class Gui {
|
||||||
*/
|
*/
|
||||||
public static GThemeValueMap getDefaults() {
|
public static GThemeValueMap getDefaults() {
|
||||||
GThemeValueMap currentDefaults = new GThemeValueMap(javaDefaults);
|
GThemeValueMap currentDefaults = new GThemeValueMap(javaDefaults);
|
||||||
|
currentDefaults.load(systemValues);
|
||||||
currentDefaults.load(applicationDefaults);
|
currentDefaults.load(applicationDefaults);
|
||||||
if (activeTheme.useDarkDefaults()) {
|
if (activeTheme.useDarkDefaults()) {
|
||||||
currentDefaults.load(applicationDarkDefaults);
|
currentDefaults.load(applicationDarkDefaults);
|
||||||
|
@ -626,6 +698,7 @@ public class Gui {
|
||||||
GThemeValueMap map = new GThemeValueMap();
|
GThemeValueMap map = new GThemeValueMap();
|
||||||
|
|
||||||
map.load(javaDefaults);
|
map.load(javaDefaults);
|
||||||
|
map.load(systemValues);
|
||||||
map.load(applicationDefaults);
|
map.load(applicationDefaults);
|
||||||
if (activeTheme.useDarkDefaults()) {
|
if (activeTheme.useDarkDefaults()) {
|
||||||
map.load(applicationDarkDefaults);
|
map.load(applicationDarkDefaults);
|
||||||
|
|
|
@ -149,11 +149,15 @@ public class IconValue extends ThemeValue<Icon> {
|
||||||
return new IconValue(id, icon, modifier);
|
return new IconValue(id, icon, modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Icon getIcon(String baseIconString) {
|
private static Icon getIcon(String baseIconString) throws ParseException {
|
||||||
if (EMPTY_ICON_STRING.equals(baseIconString)) {
|
if (EMPTY_ICON_STRING.equals(baseIconString)) {
|
||||||
return new EmptyIcon(STANDARD_EMPTY_ICON_SIZE, STANDARD_EMPTY_ICON_SIZE);
|
return new EmptyIcon(STANDARD_EMPTY_ICON_SIZE, STANDARD_EMPTY_ICON_SIZE);
|
||||||
}
|
}
|
||||||
return ResourceManager.loadImage(baseIconString);
|
Icon icon = ResourceManager.loadIcon(baseIconString);
|
||||||
|
if (icon == null) {
|
||||||
|
throw new ParseException("Can't find icon for \"" + baseIconString + "\"", 0);
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IconValue parseRefIcon(String id, String value) throws ParseException {
|
private static IconValue parseRefIcon(String id, String value) throws ParseException {
|
||||||
|
|
|
@ -84,6 +84,7 @@ public abstract class LookAndFeelManager {
|
||||||
IllegalAccessException, UnsupportedLookAndFeelException {
|
IllegalAccessException, UnsupportedLookAndFeelException {
|
||||||
|
|
||||||
cleanUiDefaults();
|
cleanUiDefaults();
|
||||||
|
Gui.setSystemDefaults(systemToLafMap);
|
||||||
doInstallLookAndFeel();
|
doInstallLookAndFeel();
|
||||||
installJavaDefaults();
|
installJavaDefaults();
|
||||||
fixupLookAndFeelIssues();
|
fixupLookAndFeelIssues();
|
||||||
|
@ -262,7 +263,6 @@ public abstract class LookAndFeelManager {
|
||||||
*/
|
*/
|
||||||
private void installJavaDefaults() {
|
private void installJavaDefaults() {
|
||||||
GThemeValueMap javaDefaults = extractJavaDefaults();
|
GThemeValueMap javaDefaults = extractJavaDefaults();
|
||||||
javaDefaults.load(systemToLafMap); // add in our system color mappings
|
|
||||||
ThemeGrouper grouper = getThemeGrouper();
|
ThemeGrouper grouper = getThemeGrouper();
|
||||||
grouper.group(javaDefaults);
|
grouper.group(javaDefaults);
|
||||||
Gui.setJavaDefaults(javaDefaults);
|
Gui.setJavaDefaults(javaDefaults);
|
||||||
|
@ -331,7 +331,6 @@ public abstract class LookAndFeelManager {
|
||||||
Icon icon = UIManager.getIcon(id);
|
Icon icon = UIManager.getIcon(id);
|
||||||
values.addIcon(new IconValue(id, icon));
|
values.addIcon(new IconValue(id, icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,10 @@ public abstract class AbstractOptions implements Options {
|
||||||
public synchronized void registerOption(String optionName, OptionType type, Object defaultValue,
|
public synchronized void registerOption(String optionName, OptionType type, Object defaultValue,
|
||||||
HelpLocation help, String description, PropertyEditor editor) {
|
HelpLocation help, String description, PropertyEditor editor) {
|
||||||
|
|
||||||
|
if (type == OptionType.COLOR_TYPE) {
|
||||||
|
// Msg.warn(this, "Registering color: " + optionName,
|
||||||
|
// ReflectionUtilities.createJavaFilteredThrowable());
|
||||||
|
}
|
||||||
if (type == OptionType.NO_TYPE) {
|
if (type == OptionType.NO_TYPE) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't register an option of type: " + OptionType.NO_TYPE);
|
"Can't register an option of type: " + OptionType.NO_TYPE);
|
||||||
|
@ -151,7 +155,7 @@ public abstract class AbstractOptions implements Options {
|
||||||
ReflectionUtilities.createJavaFilteredThrowable());
|
ReflectionUtilities.createJavaFilteredThrowable());
|
||||||
}
|
}
|
||||||
|
|
||||||
Option currentOption = getExistingComptibleOption(optionName, type, defaultValue);
|
Option currentOption = getExistingComptibleOption(optionName, type);
|
||||||
if (currentOption != null) {
|
if (currentOption != null) {
|
||||||
currentOption.updateRegistration(description, help, defaultValue, editor);
|
currentOption.updateRegistration(description, help, defaultValue, editor);
|
||||||
return;
|
return;
|
||||||
|
@ -163,8 +167,31 @@ public abstract class AbstractOptions implements Options {
|
||||||
valueMap.put(optionName, option);
|
valueMap.put(optionName, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Option getExistingComptibleOption(String optionName, OptionType type,
|
@Override
|
||||||
Object defaultValue) {
|
public void registerThemeColorOption(String optionName, String colorId, HelpLocation help,
|
||||||
|
String description) {
|
||||||
|
Option currentOption = getExistingComptibleOption(optionName, OptionType.COLOR_TYPE);
|
||||||
|
if (currentOption != null && currentOption instanceof ThemeColorOption) {
|
||||||
|
currentOption.updateRegistration(description, help, null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Option option = new ThemeColorOption(optionName, colorId, description, help);
|
||||||
|
valueMap.put(optionName, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerThemeFontOption(String optionName, String fontId, HelpLocation help,
|
||||||
|
String description) {
|
||||||
|
Option currentOption = getExistingComptibleOption(optionName, OptionType.FONT_TYPE);
|
||||||
|
if (currentOption != null && currentOption instanceof ThemeFontOption) {
|
||||||
|
currentOption.updateRegistration(description, help, null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Option option = new ThemeFontOption(optionName, fontId, description, help);
|
||||||
|
valueMap.put(optionName, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Option getExistingComptibleOption(String optionName, OptionType type) {
|
||||||
|
|
||||||
// There are several cases where an existing option may exist when registering an option
|
// There are several cases where an existing option may exist when registering an option
|
||||||
// 1) the option was accessed before it was registered
|
// 1) the option was accessed before it was registered
|
||||||
|
|
|
@ -149,6 +149,32 @@ public interface Options {
|
||||||
public void registerOption(String optionName, OptionType type, Object defaultValue,
|
public void registerOption(String optionName, OptionType type, Object defaultValue,
|
||||||
HelpLocation help, String description, PropertyEditor editor);
|
HelpLocation help, String description, PropertyEditor editor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a theme color as an option. Doing this allows the color to be edited in the
|
||||||
|
* options Gui, but all changes result in a theme change and not an options change. In other
|
||||||
|
* words, changes to this option causes a theme change and is saved to a theme instead of in
|
||||||
|
* the tool with normal options
|
||||||
|
* @param optionName the option name to bind to a theme color id
|
||||||
|
* @param colorId the theme color id to be affected if a users changes this color option
|
||||||
|
* @param help the {@link HelpLocation} for more information on how this color is used
|
||||||
|
* @param description a short description of how this color is used
|
||||||
|
*/
|
||||||
|
public void registerThemeColorOption(String optionName, String colorId, HelpLocation help,
|
||||||
|
String description);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a theme font as an option. Doing this allows the font to be edited in the
|
||||||
|
* options Gui, but all changes result in a theme change and not an options change. In other
|
||||||
|
* words, changes to this option causes a theme change and is saved to a theme instead of in
|
||||||
|
* the tool with normal options
|
||||||
|
* @param optionName the option name to bind to a theme font id
|
||||||
|
* @param fontId the theme font id to be affected if a users changes this font option
|
||||||
|
* @param help the {@link HelpLocation} for more information on how this font is used
|
||||||
|
* @param description a short description of how this font is used
|
||||||
|
*/
|
||||||
|
public void registerThemeFontOption(String optionName, String fontId, HelpLocation help,
|
||||||
|
String description);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the options editor that will handle the editing for all the options or a sub group of options.
|
* Register the options editor that will handle the editing for all the options or a sub group of options.
|
||||||
* @param editor the custom editor panel to be used to edit the options or sub group of options.
|
* @param editor the custom editor panel to be used to edit the options or sub group of options.
|
||||||
|
|
|
@ -92,6 +92,18 @@ public class SubOptions implements Options {
|
||||||
options.registerOption(prefix + optionName, type, defaultValue, help, description, editor);
|
options.registerOption(prefix + optionName, type, defaultValue, help, description, editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerThemeColorOption(String optionName, String colorId, HelpLocation help,
|
||||||
|
String description) {
|
||||||
|
options.registerThemeColorOption(prefix + optionName, colorId, help, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerThemeFontOption(String optionName, String fontId, HelpLocation help,
|
||||||
|
String description) {
|
||||||
|
options.registerThemeFontOption(prefix + optionName, fontId, help, description);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putObject(String optionName, Object obj) {
|
public void putObject(String optionName, Object obj) {
|
||||||
options.putObject(prefix + optionName, obj);
|
options.putObject(prefix + optionName, obj);
|
||||||
|
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
package ghidra.framework.options;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import generic.theme.Gui;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options implementation for theme color options. A ThemeColorOption is an option that, when
|
||||||
|
* changed, affects the current theme and is saved in the theme, instead of being saved with
|
||||||
|
* normal non-theme related options.
|
||||||
|
*/
|
||||||
|
public class ThemeColorOption extends Option {
|
||||||
|
|
||||||
|
private String colorId;
|
||||||
|
|
||||||
|
public ThemeColorOption(String optionName, String colorId, String description,
|
||||||
|
HelpLocation help) {
|
||||||
|
super(optionName, OptionType.COLOR_TYPE, description, help, null, true, null);
|
||||||
|
this.colorId = colorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getCurrentValue() {
|
||||||
|
return Gui.getColor(colorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doSetCurrentValue(Object value) {
|
||||||
|
Gui.setColor(colorId, (Color) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefault() {
|
||||||
|
return !Gui.isChangedColor(colorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreDefault() {
|
||||||
|
Gui.restoreColor(colorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
package ghidra.framework.options;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
|
||||||
|
import generic.theme.Gui;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options implementation for theme font options. A ThemeFontOption is an option that, when
|
||||||
|
* changed, affects the current theme and is saved in the theme, instead of being saved with
|
||||||
|
* normal non-theme related options.
|
||||||
|
*/
|
||||||
|
public class ThemeFontOption extends Option {
|
||||||
|
|
||||||
|
private String fontId;
|
||||||
|
|
||||||
|
public ThemeFontOption(String optionName, String fontId, String description,
|
||||||
|
HelpLocation help) {
|
||||||
|
super(optionName, OptionType.FONT_TYPE, description, help, null, true, null);
|
||||||
|
this.fontId = fontId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Font getCurrentValue() {
|
||||||
|
return Gui.getFont(fontId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doSetCurrentValue(Object value) {
|
||||||
|
Gui.setFont(fontId, (Font) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefault() {
|
||||||
|
return !Gui.isChangedFont(fontId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreDefault() {
|
||||||
|
Gui.restoreFont(fontId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,6 @@ import java.net.URL;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import generic.Images;
|
|
||||||
import generic.util.image.ImageUtils;
|
import generic.util.image.ImageUtils;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
|
@ -123,6 +122,6 @@ public class IconProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private URL getDefaultUrl() {
|
private URL getDefaultUrl() {
|
||||||
return ResourceManager.getResource(Images.BOMB);
|
return ResourceManager.getResource(ResourceManager.BOMB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package resources;
|
package resources;
|
||||||
|
|
||||||
import java.awt.Image;
|
import java.awt.*;
|
||||||
import java.awt.MediaTracker;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -30,7 +30,6 @@ import javax.swing.*;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import generic.Images;
|
|
||||||
import generic.theme.GIcon;
|
import generic.theme.GIcon;
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -48,15 +47,17 @@ import utility.module.ModuleUtilities;
|
||||||
* as opposed to using the flawed constructor {@link ImageIcon#ImageIcon(Image)}.
|
* as opposed to using the flawed constructor {@link ImageIcon#ImageIcon(Image)}.
|
||||||
*/
|
*/
|
||||||
public class ResourceManager {
|
public class ResourceManager {
|
||||||
public final static String EXTERNAL_ICON_PREFIX = "[EXTERNAL]";
|
public static final String BOMB = "images/core.png";
|
||||||
private final static String DEFAULT_ICON_FILENAME = Images.BOMB;
|
public static final String BIG_BOMB = "images/core24.png";
|
||||||
private static ImageIcon DEFAULT_ICON;
|
public static final String EXTERNAL_ICON_PREFIX = "[EXTERNAL]";
|
||||||
private static Map<String, ImageIcon> iconMap = new HashMap<>();
|
|
||||||
|
private static final Map<String, ImageIcon> iconMap = new HashMap<>();
|
||||||
|
|
||||||
private static List<String> defaultSearchPaths;
|
private static List<String> defaultSearchPaths;
|
||||||
private static List<String> testSearchPaths;
|
private static List<String> testSearchPaths;
|
||||||
|
|
||||||
private static ClassLoader classLoader = ResourceManager.class.getClassLoader();
|
private static ClassLoader classLoader = ResourceManager.class.getClassLoader();
|
||||||
|
private static final ImageIcon DEFAULT_ICON = loadDefaultIcon();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a resource with a given name. This method returns null if no
|
* Finds a resource with a given name. This method returns null if no
|
||||||
|
@ -441,26 +442,6 @@ public class ResourceManager {
|
||||||
if (icon instanceof GIcon) {
|
if (icon instanceof GIcon) {
|
||||||
return ((GIcon) icon).getId();
|
return ((GIcon) icon).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
TODO - not sure why we wanted just the name and not the entire URL? Delete this
|
|
||||||
after a bit
|
|
||||||
|
|
||||||
if (iconName == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos = iconName.lastIndexOf(File.separator);
|
|
||||||
if (pos >= 0) {
|
|
||||||
iconName = iconName.substring(pos + 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pos = iconName.lastIndexOf("/");
|
|
||||||
if (pos >= 0) {
|
|
||||||
iconName = iconName.substring(pos + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return iconName;
|
return iconName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,7 +477,7 @@ public class ResourceManager {
|
||||||
if (loadImage == null) {
|
if (loadImage == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (ImageIcon) getScaledIcon(loadImage, width, height);
|
return getScaledIcon(loadImage, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -520,24 +501,43 @@ public class ResourceManager {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the icon specified by iconPath. The iconPath can be either a path to a resource on
|
||||||
|
* the classpath or a relative or absolute path to an icon on the file system. If the iconPath
|
||||||
|
* is a path to a classpath resource, then it will be searched directly or also with an "images/"
|
||||||
|
* prepended to the path. For example, if there exists an icon "home.gif" on the classpath that
|
||||||
|
* was stored in the standard "images" resource directory, then it exists on the classpath
|
||||||
|
* as "images/home.gif". That icon will be found if the iconPath is either "images/home.gif" or
|
||||||
|
* just as "home.gif".
|
||||||
|
*
|
||||||
|
* @param iconPath name of file to load, e.g., "images/home.gif"
|
||||||
|
* @return an Icon from the given iconPath or null, if no such icon can be found
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static Icon loadIcon(String iconPath) {
|
||||||
|
ImageIcon icon = iconMap.get(iconPath);
|
||||||
|
if (icon == null) {
|
||||||
|
icon = doLoadIcon(iconPath);
|
||||||
|
iconMap.put(iconPath, icon == null ? DEFAULT_ICON : icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon == DEFAULT_ICON ? null : icon;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the image specified by filename; returns the default bomb icon
|
* Load the image specified by filename; returns the default bomb icon
|
||||||
* if problems occur trying to load the file.
|
* if problems occur trying to load the file.
|
||||||
*
|
*
|
||||||
* @param filename name of file to load, e.g., "images/home.gif"
|
* @param iconPath name of file to load, e.g., "images/home.gif"
|
||||||
* @return the image icon stored in the bytes
|
* @return the image icon stored in the bytes
|
||||||
*/
|
*/
|
||||||
public static ImageIcon loadImage(String filename) {
|
public static ImageIcon loadImage(String iconPath) {
|
||||||
ImageIcon icon = iconMap.get(filename);
|
ImageIcon icon = iconMap.get(iconPath);
|
||||||
if (icon == null) {
|
if (icon == null) {
|
||||||
icon = doLoadIcon(filename);
|
icon = doLoadIcon(iconPath);
|
||||||
if (icon == null) {
|
iconMap.put(iconPath, icon == null ? DEFAULT_ICON : icon);
|
||||||
Msg.warn(ResourceManager.class, "Can't resolve icon: " + filename);
|
|
||||||
icon = new UnresolvedIcon(filename, getDefaultIcon());
|
|
||||||
}
|
}
|
||||||
iconMap.put(filename, icon);
|
return icon == null ? new UnresolvedIcon(iconPath, DEFAULT_ICON) : icon;
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Icon> getLoadedUrlIcons() {
|
public static Set<Icon> getLoadedUrlIcons() {
|
||||||
|
@ -551,7 +551,7 @@ public class ResourceManager {
|
||||||
return icons;
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImageIcon doLoadIcon(String path) {
|
private static UrlImageIcon doLoadIcon(String path) {
|
||||||
|
|
||||||
// if the has the "external prefix", it is an icon in the user's application directory
|
// if the has the "external prefix", it is an icon in the user's application directory
|
||||||
if (path.startsWith(EXTERNAL_ICON_PREFIX)) {
|
if (path.startsWith(EXTERNAL_ICON_PREFIX)) {
|
||||||
|
@ -628,14 +628,6 @@ public class ResourceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageIcon getDefaultIcon() {
|
public static ImageIcon getDefaultIcon() {
|
||||||
if (DEFAULT_ICON == null) {
|
|
||||||
URL url = getResource(DEFAULT_ICON_FILENAME);
|
|
||||||
if (url == null) {
|
|
||||||
Msg.error(ResourceManager.class,
|
|
||||||
"Could not find default icon: " + DEFAULT_ICON_FILENAME);
|
|
||||||
}
|
|
||||||
DEFAULT_ICON = new UrlImageIcon(DEFAULT_ICON_FILENAME, url);
|
|
||||||
}
|
|
||||||
return DEFAULT_ICON;
|
return DEFAULT_ICON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,6 +637,16 @@ public class ResourceManager {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ImageIcon loadDefaultIcon() {
|
||||||
|
URL url = getResource(BOMB);
|
||||||
|
if (url != null) {
|
||||||
|
return new UrlImageIcon(BOMB, url);
|
||||||
|
}
|
||||||
|
Msg.error(ResourceManager.class,
|
||||||
|
"Could not find default icon: " + BOMB);
|
||||||
|
return getImageIcon(new ColorIcon3D(Color.RED, 16, 16));
|
||||||
|
}
|
||||||
|
|
||||||
private static void filterImages(Set<String> set) {
|
private static void filterImages(Set<String> set) {
|
||||||
Iterator<String> it = set.iterator();
|
Iterator<String> it = set.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
|
|
|
@ -74,6 +74,9 @@ public class CustomTOCView extends TOCView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelpModel getHelpModel() {
|
public HelpModel getHelpModel() {
|
||||||
|
if (ui == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return ui.getHelpModel();
|
return ui.getHelpModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue