mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1981 - Checkpoint - Function Call Graph
This commit is contained in:
parent
16e32317f0
commit
60b1ae8b44
15 changed files with 276 additions and 41 deletions
|
@ -5,6 +5,7 @@
|
||||||
##MODULE IP: Tango Icons - Public Domain
|
##MODULE IP: Tango Icons - Public Domain
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
data/ExtensionPoint.manifest||GHIDRA||||END|
|
data/ExtensionPoint.manifest||GHIDRA||||END|
|
||||||
|
data/functiongraph.theme.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|
|
||||||
src/main/help/help/shared/close16.gif||GHIDRA||reviewed||END|
|
src/main/help/help/shared/close16.gif||GHIDRA||reviewed||END|
|
||||||
|
|
|
@ -24,12 +24,23 @@ color.bg.functiongraph.paint.icon = rgb(189, 221, 252) // gentle pale blue
|
||||||
[Dark Defaults]
|
[Dark Defaults]
|
||||||
|
|
||||||
|
|
||||||
color.bg.functiongraph.vertex.group = rgb(226, 222, 179) // TODO confirm value
|
// color.bg.functiongraph = color.bg
|
||||||
|
|
||||||
|
// color.fg.label.picked = color.fg
|
||||||
|
// color.fg.label.non-picked = color.fg.disabled
|
||||||
|
|
||||||
|
color.bg.functiongraph.vertex.group = rgb(226, 222, 179) // TODO confirm value
|
||||||
|
// color.bg.functiongraph.vertex.entry = color.palette.lightgreen
|
||||||
|
// color.bg.functiongraph.vertex.exit = color.palette.lightred
|
||||||
|
// color.bg.functiongraph.vertex.picked = color.palette.yellow
|
||||||
|
|
||||||
|
// color.bg.functiongraph.edge.fall-through = color.flowtype.fall-through
|
||||||
color.bg.functiongraph.edge.fall-through.highlight = rgb(165, 76, 80)
|
color.bg.functiongraph.edge.fall-through.highlight = rgb(165, 76, 80)
|
||||||
|
// color.bg.functiongraph.edge.jump.conditional = color.flowtype.jump.conditional
|
||||||
color.bg.functiongraph.edge.jump.conditional.highlight = rgb(95, 160, 196)
|
color.bg.functiongraph.edge.jump.conditional.highlight = rgb(95, 160, 196)
|
||||||
|
// color.bg.functiongraph.edge.jump.unconditional = color.flowtype.jump.unconditional
|
||||||
color.bg.functiongraph.edge.jump.unconditional.highlight = rgb(140, 162, 88)
|
color.bg.functiongraph.edge.jump.unconditional.highlight = rgb(140, 162, 88)
|
||||||
|
|
||||||
|
|
||||||
// TODO dark version color.bg.functiongraph.paint.icon =
|
// TODO dark version color.bg.functiongraph.paint.icon = // TODO
|
||||||
|
|
|
@ -59,8 +59,7 @@ import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.model.symbol.SymbolTable;
|
import ghidra.program.model.symbol.SymbolTable;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.util.HTMLUtilities;
|
import ghidra.util.*;
|
||||||
import ghidra.util.HelpLocation;
|
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
|
|
||||||
public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
|
public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
|
||||||
|
@ -561,11 +560,7 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
|
||||||
private Color getToolTipColorForEdge(FGEdge edge) {
|
private Color getToolTipColorForEdge(FGEdge edge) {
|
||||||
FunctionGraphOptions options = controller.getFunctionGraphOptions();
|
FunctionGraphOptions options = controller.getFunctionGraphOptions();
|
||||||
Color c = options.getColor(edge.getFlowType());
|
Color c = options.getColor(edge.getFlowType());
|
||||||
return withAlpha(c, 125);
|
return ColorUtils.withAlpha(c, 125);
|
||||||
}
|
|
||||||
|
|
||||||
private Color withAlpha(Color c, int alpha) {
|
|
||||||
return new Color(c.getRed(), c.getGreen(), c.getBlue(), 125);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address getPreviewAddress(boolean forward) {
|
private Address getPreviewAddress(boolean forward) {
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
[Defaults]
|
[Defaults]
|
||||||
|
|
||||||
color.fcg.satellite.edge = rgba(0,0,0,0.1)
|
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) // lightGreen
|
||||||
|
color.bg.fcg.edge.primary.indirect = rgb(233, 233, 233) // lightGray
|
||||||
|
|
||||||
|
// 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'
|
||||||
|
|
||||||
|
|
||||||
|
[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'
|
|
@ -26,6 +26,8 @@ import javax.swing.*;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.border.LineBorder;
|
import javax.swing.border.LineBorder;
|
||||||
|
|
||||||
|
import docking.theme.GColor;
|
||||||
|
import docking.theme.GThemeDefaults.Colors.Palette;
|
||||||
import docking.widgets.EmptyBorderButton;
|
import docking.widgets.EmptyBorderButton;
|
||||||
import docking.widgets.label.GDLabel;
|
import docking.widgets.label.GDLabel;
|
||||||
import ghidra.graph.viewer.vertex.AbstractVisualVertex;
|
import ghidra.graph.viewer.vertex.AbstractVisualVertex;
|
||||||
|
@ -41,9 +43,10 @@ import resources.ResourceManager;
|
||||||
*/
|
*/
|
||||||
public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvider {
|
public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvider {
|
||||||
|
|
||||||
// TODO to be made an option in an upcoming ticket
|
//@formatter:off
|
||||||
public static final Color DEFAULT_VERTEX_SHAPE_COLOR = new Color(110, 197, 174);
|
public static final Color DEFAULT_VERTEX_SHAPE_COLOR = new GColor("color.bg.fcg.vertex.default");
|
||||||
private static final Color TOO_BIG_VERTEX_SHAPE_COLOR = Color.LIGHT_GRAY;
|
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;
|
public static final Icon NOT_ALLOWED_ICON = Icons.ERROR_ICON;
|
||||||
private static final Icon EXPAND_ICON =
|
private static final Icon EXPAND_ICON =
|
||||||
|
@ -312,8 +315,8 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid
|
||||||
private void addToggleButtons() {
|
private void addToggleButtons() {
|
||||||
|
|
||||||
// hide the button background
|
// hide the button background
|
||||||
toggleInsButton.setBackground(new Color(255, 255, 255, 0));
|
toggleInsButton.setBackground(Palette.NO_COLOR);
|
||||||
toggleOutsButton.setBackground(new Color(255, 255, 255, 0));
|
toggleOutsButton.setBackground(Palette.NO_COLOR);
|
||||||
|
|
||||||
Rectangle parentBounds = vertexImageLabel.getBounds();
|
Rectangle parentBounds = vertexImageLabel.getBounds();
|
||||||
Dimension size = toggleInsButton.getPreferredSize();
|
Dimension size = toggleInsButton.getPreferredSize();
|
||||||
|
|
|
@ -21,13 +21,13 @@ import java.awt.Paint;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
import functioncalls.graph.FcgEdge;
|
import functioncalls.graph.FcgEdge;
|
||||||
|
import ghidra.util.ColorUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates colors for a given {@link FcgEdge}
|
* Generates colors for a given {@link FcgEdge}
|
||||||
*/
|
*/
|
||||||
public class FcgEdgePaintTransformer implements Function<FcgEdge, Paint> {
|
public class FcgEdgePaintTransformer implements Function<FcgEdge, Paint> {
|
||||||
|
|
||||||
// private static final Paint LESS_IMPORTANT_COLOR = new Color(125, 125, 125, 75);
|
|
||||||
private Color directColor;
|
private Color directColor;
|
||||||
private Color indirectColor;
|
private Color indirectColor;
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public class FcgEdgePaintTransformer implements Function<FcgEdge, Paint> {
|
||||||
alphad[0] = c;
|
alphad[0] = c;
|
||||||
for (int i = 1; i < 10; i++) {
|
for (int i = 1; i < 10; i++) {
|
||||||
double newAlpha = 255 - (i * 25.5);
|
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;
|
return alphad;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package functioncalls.graph.view;
|
package functioncalls.graph.view;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
|
|
||||||
import docking.theme.GColor;
|
import docking.theme.GColor;
|
||||||
import edu.uci.ics.jung.visualization.RenderContext;
|
import edu.uci.ics.jung.visualization.RenderContext;
|
||||||
import functioncalls.graph.*;
|
import functioncalls.graph.*;
|
||||||
|
@ -38,19 +36,14 @@ public class FcgComponent extends GraphComponent<FcgVertex, FcgEdge, FunctionCal
|
||||||
private FcgVertexPaintTransformer vertexPaintTransformer =
|
private FcgVertexPaintTransformer vertexPaintTransformer =
|
||||||
new FcgVertexPaintTransformer(FcgVertex.DEFAULT_VERTEX_SHAPE_COLOR);
|
new FcgVertexPaintTransformer(FcgVertex.DEFAULT_VERTEX_SHAPE_COLOR);
|
||||||
|
|
||||||
private Color lightGreen = new Color(143, 197, 143);
|
|
||||||
private Color lightGray = new Color(233, 233, 233);
|
|
||||||
|
|
||||||
// the satellite gets too cluttered, so wash out the edges
|
|
||||||
private Color washedOutBlack = new GColor("color.fcg.satellite.edge");
|
|
||||||
|
|
||||||
private FcgEdgePaintTransformer edgePaintTransformer =
|
private FcgEdgePaintTransformer edgePaintTransformer =
|
||||||
new FcgEdgePaintTransformer(lightGreen, lightGray);
|
new FcgEdgePaintTransformer(new GColor("color.bg.fcg.edge.primary.direct"),
|
||||||
|
new GColor("color.bg.fcg.edge.primary.indirect"));
|
||||||
private FcgEdgePaintTransformer satelliteEdgePaintTransformer =
|
private FcgEdgePaintTransformer satelliteEdgePaintTransformer =
|
||||||
new FcgEdgePaintTransformer(washedOutBlack, new Color(125, 125, 125, 25));
|
new FcgEdgePaintTransformer(new GColor("color.bg.fcg.edge.satellite.direct"),
|
||||||
|
new GColor("color.bg.fcg.edge.satellite.indirect"));
|
||||||
|
|
||||||
FcgComponent(FunctionCallGraph g) {
|
FcgComponent(FunctionCallGraph g) {
|
||||||
|
|
||||||
setGraph(g);
|
setGraph(g);
|
||||||
build();
|
build();
|
||||||
}
|
}
|
||||||
|
@ -75,7 +68,6 @@ public class FcgComponent extends GraphComponent<FcgVertex, FcgEdge, FunctionCal
|
||||||
renderContext.setEdgeDrawPaintTransformer(edgePaintTransformer);
|
renderContext.setEdgeDrawPaintTransformer(edgePaintTransformer);
|
||||||
renderContext.setArrowFillPaintTransformer(edgePaintTransformer);
|
renderContext.setArrowFillPaintTransformer(edgePaintTransformer);
|
||||||
renderContext.setArrowDrawPaintTransformer(edgePaintTransformer);
|
renderContext.setArrowDrawPaintTransformer(edgePaintTransformer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
[Defaults]
|
[Defaults]
|
||||||
|
|
||||||
|
color.palette.nocolor = rgba(255,255,255,0)
|
||||||
|
|
||||||
color.palette.black = black
|
color.palette.black = black
|
||||||
color.palette.cyan = cyan
|
color.palette.cyan = cyan
|
||||||
|
color.palette.lightGray = rgb(192, 192, 192)
|
||||||
color.palette.lightgreen = rgb(127, 255, 127)
|
color.palette.lightgreen = rgb(127, 255, 127)
|
||||||
color.palette.lightred = rgb(255, 127, 127)
|
color.palette.lightred = rgb(255, 127, 127)
|
||||||
color.palette.red = red
|
color.palette.red = red
|
||||||
|
|
|
@ -21,11 +21,20 @@ import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.image.ColorModel;
|
import java.awt.image.ColorModel;
|
||||||
|
|
||||||
public class GColor extends Color implements Refreshable {
|
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||||
|
import ghidra.util.datastruct.WeakSet;
|
||||||
|
|
||||||
|
public class GColor extends Color implements Refreshable {
|
||||||
|
private static WeakSet<GColor> inUseColors = WeakDataStructureFactory.createCopyOnReadWeakSet();
|
||||||
private String id;
|
private String id;
|
||||||
private Color delegate;
|
private Color delegate;
|
||||||
|
|
||||||
|
public static void refreshAll() {
|
||||||
|
for (GColor gcolor : inUseColors) {
|
||||||
|
gcolor.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GColor(String id) {
|
public GColor(String id) {
|
||||||
super(0x808080);
|
super(0x808080);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -33,6 +42,7 @@ public class GColor extends Color implements Refreshable {
|
||||||
if (delegate == null) {
|
if (delegate == null) {
|
||||||
delegate = Color.gray;
|
delegate = Color.gray;
|
||||||
}
|
}
|
||||||
|
inUseColors.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
|
|
@ -55,6 +55,8 @@ public class GThemeDefaults {
|
||||||
* Generic palette colors, using color names, that may be changed along with the theme
|
* Generic palette colors, using color names, that may be changed along with the theme
|
||||||
*/
|
*/
|
||||||
public static class Palette {
|
public static class Palette {
|
||||||
|
public static final Color NO_COLOR = new GColor("color.palette.nocolor");
|
||||||
|
|
||||||
public static final Color BLACK = new GColor("color.palette.black");
|
public static final Color BLACK = new GColor("color.palette.black");
|
||||||
public static final Color CYAN = new GColor("color.palette.cyan");
|
public static final Color CYAN = new GColor("color.palette.cyan");
|
||||||
public static final Color RED = new GColor("color.palette.red");
|
public static final Color RED = new GColor("color.palette.red");
|
||||||
|
|
|
@ -32,7 +32,7 @@ import ghidra.util.filechooser.GhidraFileFilter;
|
||||||
public class GThemeDialog extends DialogComponentProvider {
|
public class GThemeDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
public GThemeDialog() {
|
public GThemeDialog() {
|
||||||
super("Theme Dialog");
|
super("Theme Dialog", false);
|
||||||
addWorkPanel(createMainPanel());
|
addWorkPanel(createMainPanel());
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
|
@ -80,6 +80,9 @@ public class GThemeDialog extends DialogComponentProvider {
|
||||||
colorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
colorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
GFilterTable<ColorValue> filterTable = new GFilterTable<>(colorTableModel);
|
GFilterTable<ColorValue> filterTable = new GFilterTable<>(colorTableModel);
|
||||||
filterTable.getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
filterTable.getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
filterTable.getTable()
|
||||||
|
.setDefaultEditor(ColorValue.class,
|
||||||
|
new ThemeColorEditor(Gui.getAllValues(), colorTableModel));
|
||||||
return filterTable;
|
return filterTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,4 +307,10 @@ public class Gui {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setColor(String id, Color color) {
|
||||||
|
currentValues.addColor(new ColorValue(id, color));
|
||||||
|
GColor.refreshAll();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
/* ###
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.BevelBorder;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.table.TableCellEditor;
|
||||||
|
|
||||||
|
import docking.DialogComponentProvider;
|
||||||
|
import docking.DockingWindowManager;
|
||||||
|
import docking.options.editor.GhidraColorChooser;
|
||||||
|
import docking.widgets.label.GDLabel;
|
||||||
|
|
||||||
|
public class ThemeColorEditor extends AbstractCellEditor implements TableCellEditor {
|
||||||
|
private GhidraColorChooser colorChooser;
|
||||||
|
private Color lastUserSelectedColor;
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
private ColorDialogProvider dialog;
|
||||||
|
private JTable table;
|
||||||
|
private ColorValue colorValue;
|
||||||
|
|
||||||
|
private GThemeValueMap values;
|
||||||
|
private ThemeColorTableModel model;
|
||||||
|
|
||||||
|
public ThemeColorEditor(GThemeValueMap values, ThemeColorTableModel model) {
|
||||||
|
this.values = values;
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTableCellEditorComponent(JTable theTable, Object value, boolean isSelected,
|
||||||
|
int row, int column) {
|
||||||
|
|
||||||
|
this.table = theTable;
|
||||||
|
colorValue = (ColorValue) value;
|
||||||
|
|
||||||
|
JLabel label = new GDLabel();
|
||||||
|
label.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
||||||
|
label.setText(colorValue.getId());
|
||||||
|
|
||||||
|
dialog = new ColorDialogProvider();
|
||||||
|
dialog.setRememberSize(false);
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DockingWindowManager.showDialog(dialog);
|
||||||
|
stopCellEditing();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelCellEditing() {
|
||||||
|
dialog.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCellEditorValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stopCellEditing() {
|
||||||
|
ListSelectionModel columnSelectionModel = table.getColumnModel().getSelectionModel();
|
||||||
|
columnSelectionModel.setValueIsAdjusting(true);
|
||||||
|
int columnAnchor = columnSelectionModel.getAnchorSelectionIndex();
|
||||||
|
int columnLead = columnSelectionModel.getLeadSelectionIndex();
|
||||||
|
|
||||||
|
if (color != null) {
|
||||||
|
Gui.setColor(colorValue.getId(), color);
|
||||||
|
model.refresh();
|
||||||
|
}
|
||||||
|
dialog.close();
|
||||||
|
fireEditingStopped();
|
||||||
|
|
||||||
|
columnSelectionModel.setAnchorSelectionIndex(columnAnchor);
|
||||||
|
columnSelectionModel.setLeadSelectionIndex(columnLead);
|
||||||
|
columnSelectionModel.setValueIsAdjusting(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only double-click edits
|
||||||
|
@Override
|
||||||
|
public boolean isCellEditable(EventObject anEvent) {
|
||||||
|
if (anEvent instanceof MouseEvent) {
|
||||||
|
return ((MouseEvent) anEvent).getClickCount() >= 2;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// Inner Classes
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
class ColorDialogProvider extends DialogComponentProvider {
|
||||||
|
ColorDialogProvider() {
|
||||||
|
super("Color Editor", true);
|
||||||
|
|
||||||
|
addWorkPanel(new ColorEditorPanel());
|
||||||
|
addOKButton();
|
||||||
|
addCancelButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void okCallback() {
|
||||||
|
color = lastUserSelectedColor;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cancelCallback() {
|
||||||
|
color = null;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ColorEditorPanel extends JPanel {
|
||||||
|
|
||||||
|
ColorEditorPanel() {
|
||||||
|
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
if (colorChooser == null) {
|
||||||
|
colorChooser = new GhidraColorChooser();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.setColor(colorValue.get(values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,11 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
colors = Gui.getAllValues().getColors();
|
colors = Gui.getAllValues().getColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
colors = Gui.getAllValues().getColors();
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Users";
|
return "Users";
|
||||||
|
@ -48,6 +53,10 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
return colors;
|
return colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int row, int column) {
|
||||||
|
return getColumnName(column).equals("Current Color");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableColumnDescriptor<ColorValue> createTableColumnDescriptor() {
|
protected TableColumnDescriptor<ColorValue> createTableColumnDescriptor() {
|
||||||
TableColumnDescriptor<ColorValue> descriptor = new TableColumnDescriptor<>();
|
TableColumnDescriptor<ColorValue> descriptor = new TableColumnDescriptor<>();
|
||||||
|
@ -78,7 +87,7 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValueColumn extends AbstractDynamicTableColumn<ColorValue, String, Object> {
|
class ValueColumn extends AbstractDynamicTableColumn<ColorValue, ColorValue, Object> {
|
||||||
private ThemeColorRenderer renderer = new ThemeColorRenderer(Gui.getAllValues());
|
private ThemeColorRenderer renderer = new ThemeColorRenderer(Gui.getAllValues());
|
||||||
private GThemeValueMap valueMap;
|
private GThemeValueMap valueMap;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -95,18 +104,19 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getValue(ColorValue themeColor, Settings settings, Object data,
|
public ColorValue getValue(ColorValue themeColor, Settings settings, Object data,
|
||||||
ServiceProvider provider) throws IllegalArgumentException {
|
ServiceProvider provider) throws IllegalArgumentException {
|
||||||
return themeColor.getId();
|
return themeColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GColumnRenderer<String> getColumnRenderer() {
|
public GColumnRenderer<ColorValue> getColumnRenderer() {
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Comparator<String> getComparator() {
|
public Comparator<ColorValue> getComparator() {
|
||||||
return (s1, s2) -> valueMap.getColor(s1).compareValue(valueMap.getColor(s2));
|
return (v1, v2) -> valueMap.getColor(v1.getId())
|
||||||
|
.compareValue(valueMap.getColor(v2.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -125,7 +135,7 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ThemeColorRenderer extends AbstractGColumnRenderer<String> {
|
private class ThemeColorRenderer extends AbstractGColumnRenderer<ColorValue> {
|
||||||
|
|
||||||
private GThemeValueMap valueMap;
|
private GThemeValueMap valueMap;
|
||||||
|
|
||||||
|
@ -138,7 +148,7 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
||||||
|
|
||||||
JLabel label = (JLabel) super.getTableCellRendererComponent(data);
|
JLabel label = (JLabel) super.getTableCellRendererComponent(data);
|
||||||
String id = (String) data.getValue();
|
String id = ((ColorValue) data.getValue()).getId();
|
||||||
|
|
||||||
ColorValue colorValue = valueMap.getColor(id);
|
ColorValue colorValue = valueMap.getColor(id);
|
||||||
Color color;
|
Color color;
|
||||||
|
@ -169,8 +179,9 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFilterString(String id, Settings settings) {
|
public String getFilterString(ColorValue t, Settings settings) {
|
||||||
return id;
|
return t.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,6 +191,17 @@ public class ColorUtils {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new color that is comprised of the given color's rgb value and the given alpha
|
||||||
|
* value.
|
||||||
|
* @param c the color
|
||||||
|
* @param alpha the alpha
|
||||||
|
* @return the new color
|
||||||
|
*/
|
||||||
|
public static Color withAlpha(Color c, int alpha) {
|
||||||
|
return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blender of colors
|
* Blender of colors
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue