[#2224] Add hex color input field in appearance panel
This commit is contained in:
parent
29598ef1b1
commit
0153c89ddc
@ -1058,6 +1058,8 @@ AppearanceCfg.lbl.ttip.separateInsideOutside = Use a separate appearance for out
|
|||||||
AppearanceCfg.lbl.ttip.separateLeftSideRightSide = Use a separate appearance for left and right side(s)
|
AppearanceCfg.lbl.ttip.separateLeftSideRightSide = Use a separate appearance for left and right side(s)
|
||||||
AppearanceCfg.lbl.AppearanceEdges = Appearance for edges:
|
AppearanceCfg.lbl.AppearanceEdges = Appearance for edges:
|
||||||
AppearanceCfg.lbl.ttip.AppearanceEdges = Select the appearance that should be used for the edges
|
AppearanceCfg.lbl.ttip.AppearanceEdges = Select the appearance that should be used for the edges
|
||||||
|
AppearanceCfg.placeholder.HexColor = Hex color
|
||||||
|
AppearanceCfg.ttip.HexColor = Hexadecimal representation of the color
|
||||||
|
|
||||||
! Texture Wrap Modes
|
! Texture Wrap Modes
|
||||||
TextureWrap.Repeat = Repeat
|
TextureWrap.Repeat = Repeat
|
||||||
|
@ -17,6 +17,7 @@ import javax.swing.JCheckBox;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JSeparator;
|
import javax.swing.JSeparator;
|
||||||
|
import javax.swing.JTextField;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
@ -27,6 +28,7 @@ import javax.swing.event.ChangeEvent;
|
|||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import info.openrocket.core.util.Invalidatable;
|
import info.openrocket.core.util.Invalidatable;
|
||||||
|
import info.openrocket.swing.gui.widgets.PlaceholderTextField;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import info.openrocket.core.appearance.Appearance;
|
import info.openrocket.core.appearance.Appearance;
|
||||||
import info.openrocket.core.appearance.AppearanceBuilder;
|
import info.openrocket.core.appearance.AppearanceBuilder;
|
||||||
@ -126,7 +128,7 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ColorActionListener implements ActionListener {
|
private abstract class ColorActionListener {
|
||||||
private final String valueName;
|
private final String valueName;
|
||||||
private final Object o;
|
private final Object o;
|
||||||
|
|
||||||
@ -139,23 +141,35 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
Changes the color of the selected component to <color>
|
Changes the color of the selected component to <color>
|
||||||
@param color: color to change the component to
|
@param color: color to change the component to
|
||||||
*/
|
*/
|
||||||
private void changeComponentColor(Color color) {
|
protected void setComponentColor(Color color) {
|
||||||
try {
|
try {
|
||||||
final Method setMethod = o.getClass().getMethod(
|
final Method setMethod = o.getClass().getMethod("set" + valueName, ORColor.class);
|
||||||
"set" + valueName, ORColor.class);
|
|
||||||
if (color == null)
|
if (color == null)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
setMethod.invoke(o, ColorConversion
|
setMethod.invoke(o, ColorConversion.fromAwtColor(color));
|
||||||
.fromAwtColor(color));
|
|
||||||
} catch (Throwable e1) {
|
} catch (Throwable e1) {
|
||||||
Application.getExceptionHandler()
|
Application.getExceptionHandler().handleErrorCondition(e1);
|
||||||
.handleErrorCondition(e1);
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e1) {
|
} catch (Throwable e1) {
|
||||||
Application.getExceptionHandler().handleErrorCondition(e1);
|
Application.getExceptionHandler().handleErrorCondition(e1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ORColor getComponentColor() {
|
||||||
|
try {
|
||||||
|
final Method getMethod = o.getClass().getMethod("get" + valueName);
|
||||||
|
return (ORColor) getMethod.invoke(o);
|
||||||
|
} catch (Throwable e1) {
|
||||||
|
Application.getExceptionHandler().handleErrorCondition(e1);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ColorButtonActionListener extends ColorActionListener implements ActionListener {
|
||||||
|
ColorButtonActionListener(final Object o, final String valueName) {
|
||||||
|
super(o, valueName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,10 +180,7 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent colorClickEvent) {
|
public void actionPerformed(ActionEvent colorClickEvent) {
|
||||||
try {
|
try {
|
||||||
final Method getMethod = o.getClass().getMethod(
|
ORColor c = getComponentColor();
|
||||||
"get" + valueName);
|
|
||||||
ORColor c = (ORColor) getMethod
|
|
||||||
.invoke(o);
|
|
||||||
|
|
||||||
Color awtColor = ColorConversion.toAwtColor(c);
|
Color awtColor = ColorConversion.toAwtColor(c);
|
||||||
colorChooser.setColor(awtColor);
|
colorChooser.setColor(awtColor);
|
||||||
@ -180,7 +191,7 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
ChangeListener changeListener = new ChangeListener() {
|
ChangeListener changeListener = new ChangeListener() {
|
||||||
public void stateChanged(ChangeEvent changeEvent) {
|
public void stateChanged(ChangeEvent changeEvent) {
|
||||||
Color selected = colorChooser.getColor();
|
Color selected = colorChooser.getColor();
|
||||||
changeComponentColor(selected);
|
setComponentColor(selected);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
model.addChangeListener(changeListener);
|
model.addChangeListener(changeListener);
|
||||||
@ -191,14 +202,14 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
new ActionListener() {
|
new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent okEvent) {
|
public void actionPerformed(ActionEvent okEvent) {
|
||||||
changeComponentColor(colorChooser.getColor());
|
setComponentColor(colorChooser.getColor());
|
||||||
// Unbind listener to avoid the current component's appearance to change with other components
|
// Unbind listener to avoid the current component's appearance to change with other components
|
||||||
model.removeChangeListener(changeListener);
|
model.removeChangeListener(changeListener);
|
||||||
}
|
}
|
||||||
}, new ActionListener() {
|
}, new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent cancelEvent) {
|
public void actionPerformed(ActionEvent cancelEvent) {
|
||||||
changeComponentColor(awtColor);
|
setComponentColor(awtColor);
|
||||||
// Unbind listener to avoid the current component's appearance to change with other components
|
// Unbind listener to avoid the current component's appearance to change with other components
|
||||||
model.removeChangeListener(changeListener);
|
model.removeChangeListener(changeListener);
|
||||||
}
|
}
|
||||||
@ -210,6 +221,28 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ColorHexActionListener extends ColorActionListener implements ActionListener {
|
||||||
|
public ColorHexActionListener(final Object o, final String valueName) {
|
||||||
|
super(o, valueName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JTextField field = (JTextField) e.getSource();
|
||||||
|
String hex = field.getText();
|
||||||
|
try {
|
||||||
|
ORColor color = ColorConversion.fromHexColor(hex);
|
||||||
|
if (color == null) {
|
||||||
|
field.setText(ColorConversion.toHexColor(getComponentColor()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setComponentColor(ColorConversion.toAwtColor(color));
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
field.setText(ColorConversion.toHexColor(getComponentColor()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appearance panel for the appearance of a rocket component.
|
* Appearance panel for the appearance of a rocket component.
|
||||||
* @param document current document
|
* @param document current document
|
||||||
@ -271,10 +304,17 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
}
|
}
|
||||||
final JButton figureColorButton = new JButton(
|
final JButton figureColorButton = new JButton(
|
||||||
new ColorIcon(figureColor));
|
new ColorIcon(figureColor));
|
||||||
|
PlaceholderTextField figureColorHexField = new PlaceholderTextField(7);
|
||||||
|
figureColorHexField.setPlaceholder(trans.get("AppearanceCfg.placeholder.HexColor"));
|
||||||
|
figureColorHexField.setToolTipText(trans.get("AppearanceCfg.ttip.HexColor"));
|
||||||
|
figureColorHexField.setText(ColorConversion.toHexColor(c.getColor()));
|
||||||
|
|
||||||
ab.addChangeListener(new StateChangeListener() {
|
ab.addChangeListener(new StateChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(EventObject e) { figureColorButton.setIcon(new ColorIcon(c.getColor())); }
|
public void stateChanged(EventObject e) {
|
||||||
|
figureColorButton.setIcon(new ColorIcon(c.getColor()));
|
||||||
|
figureColorHexField.setText(ColorConversion.toHexColor(c.getColor()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
c.addChangeListener(new StateChangeListener() {
|
c.addChangeListener(new StateChangeListener() {
|
||||||
@ -285,11 +325,12 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
col = ((SwingPreferences) Application.getPreferences()).getDefaultColor(c.getClass());
|
col = ((SwingPreferences) Application.getPreferences()).getDefaultColor(c.getClass());
|
||||||
}
|
}
|
||||||
figureColorButton.setIcon(new ColorIcon(col));
|
figureColorButton.setIcon(new ColorIcon(col));
|
||||||
|
figureColorHexField.setText(ColorConversion.toHexColor(col));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
figureColorButton
|
figureColorButton.addActionListener(new ColorButtonActionListener(c, "Color"));
|
||||||
.addActionListener(new ColorActionListener(c, "Color"));
|
figureColorHexField.addActionListener(new ColorHexActionListener(c, "Color"));
|
||||||
|
|
||||||
BooleanModel fDefault = new BooleanModel(c.getColor() == null);
|
BooleanModel fDefault = new BooleanModel(c.getColor() == null);
|
||||||
register(fDefault);
|
register(fDefault);
|
||||||
@ -342,9 +383,15 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
|
|
||||||
{// Figure Color
|
{// Figure Color
|
||||||
add(new JLabel(trans.get("RocketCompCfg.lbl.Componentcolor")));
|
add(new JLabel(trans.get("RocketCompCfg.lbl.Componentcolor")));
|
||||||
|
JPanel colorPanel = new JPanel(new MigLayout("ins 0"));
|
||||||
|
colorPanel.add(figureColorButton);
|
||||||
|
figureColorHexField.setColumns(7);
|
||||||
|
colorPanel.add(figureColorHexField);
|
||||||
fDefault.addEnableComponent(figureColorButton, false);
|
fDefault.addEnableComponent(figureColorButton, false);
|
||||||
add(figureColorButton);
|
fDefault.addEnableComponent(figureColorHexField, false);
|
||||||
|
add(colorPanel, "growx");
|
||||||
order.add(figureColorButton);
|
order.add(figureColorButton);
|
||||||
|
order.add(figureColorHexField);
|
||||||
}
|
}
|
||||||
|
|
||||||
order.add(saveAsDefault);
|
order.add(saveAsDefault);
|
||||||
@ -532,8 +579,13 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
});
|
});
|
||||||
|
|
||||||
JButton colorButton = new JButton(new ColorIcon(builder.getPaint()));
|
JButton colorButton = new JButton(new ColorIcon(builder.getPaint()));
|
||||||
|
PlaceholderTextField colorHexField = new PlaceholderTextField(7);
|
||||||
|
colorHexField.setPlaceholder(trans.get("AppearanceCfg.placeholder.HexColor"));
|
||||||
|
colorHexField.setToolTipText(trans.get("AppearanceCfg.ttip.HexColor"));
|
||||||
|
colorHexField.setText(ColorConversion.toHexColor(builder.getPaint()));
|
||||||
|
|
||||||
colorButton.addActionListener(new ColorActionListener(builder, "Paint"));
|
colorButton.addActionListener(new ColorButtonActionListener(builder, "Paint"));
|
||||||
|
colorHexField.addActionListener(new ColorHexActionListener(builder, "Paint"));
|
||||||
|
|
||||||
// Texture Header Row
|
// Texture Header Row
|
||||||
panel.add(new StyledLabel(trans.get("AppearanceCfg.lbl.Appearance"),
|
panel.add(new StyledLabel(trans.get("AppearanceCfg.lbl.Appearance"),
|
||||||
@ -630,9 +682,15 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
// TODO: move the separate columns in two separate panels instead of adding them in a zig-zag way
|
// TODO: move the separate columns in two separate panels instead of adding them in a zig-zag way
|
||||||
// Color
|
// Color
|
||||||
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.color.Color")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.color.Color")));
|
||||||
|
JPanel colorPanel = new JPanel(new MigLayout("ins 0"));
|
||||||
|
colorPanel.add(colorButton);
|
||||||
|
colorHexField.setColumns(7);
|
||||||
|
colorPanel.add(colorHexField);
|
||||||
mDefault.addEnableComponent(colorButton, false);
|
mDefault.addEnableComponent(colorButton, false);
|
||||||
panel.add(colorButton);
|
mDefault.addEnableComponent(colorHexField, false);
|
||||||
|
panel.add(colorPanel, "growx");
|
||||||
order.add(colorButton);
|
order.add(colorButton);
|
||||||
|
order.add(colorHexField);
|
||||||
|
|
||||||
// Scale
|
// Scale
|
||||||
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.scale")), "gapleft para");
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.scale")), "gapleft para");
|
||||||
@ -674,7 +732,7 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
panel.add(spinShine, "split 3, w 60");
|
panel.add(spinShine, "split 3, w 60");
|
||||||
panel.add(unitShine);
|
panel.add(unitShine);
|
||||||
panel.add(slideShine, "w 100lp");
|
panel.add(slideShine, "w 100lp");
|
||||||
order.add(order.indexOf(colorButton) + 1, ((SpinnerEditor) spinShine.getEditor()).getTextField());
|
order.add(order.indexOf(colorHexField) + 1, ((SpinnerEditor) spinShine.getEditor()).getTextField());
|
||||||
|
|
||||||
// Offset
|
// Offset
|
||||||
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.offset")), "gapleft para");
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.offset")), "gapleft para");
|
||||||
@ -749,6 +807,7 @@ public class AppearancePanel extends JPanel implements Invalidatable, Invalidati
|
|||||||
@Override
|
@Override
|
||||||
public void stateChanged(EventObject e) {
|
public void stateChanged(EventObject e) {
|
||||||
colorButton.setIcon(new ColorIcon(builder.getPaint()));
|
colorButton.setIcon(new ColorIcon(builder.getPaint()));
|
||||||
|
colorHexField.setText(ColorConversion.toHexColor(builder.getPaint()));
|
||||||
if (lastOpacity != builder.getOpacity()) {
|
if (lastOpacity != builder.getOpacity()) {
|
||||||
opacityModel.stateChanged(null);
|
opacityModel.stateChanged(null);
|
||||||
lastOpacity = builder.getOpacity();
|
lastOpacity = builder.getOpacity();
|
||||||
|
@ -27,4 +27,28 @@ public class ColorConversion {
|
|||||||
String hexColor = String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue());
|
String hexColor = String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue());
|
||||||
return String.format("<font color=\"%s\">%s</font>", hexColor, content);
|
return String.format("<font color=\"%s\">%s</font>", hexColor, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toHexColor(ORColor c) {
|
||||||
|
if (c == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue()).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ORColor fromHexColor(String hexColor) {
|
||||||
|
if (hexColor == null || hexColor.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (hexColor.startsWith("#")) {
|
||||||
|
hexColor = hexColor.substring(1);
|
||||||
|
}
|
||||||
|
hexColor = hexColor.trim();
|
||||||
|
if (hexColor.length() != 6 || hexColor.matches("^#[0-9A-Fa-f]{6}$")) {
|
||||||
|
throw new IllegalArgumentException("Invalid hex color: " + hexColor);
|
||||||
|
}
|
||||||
|
int red = Integer.parseInt(hexColor.substring(0, 2), 16);
|
||||||
|
int green = Integer.parseInt(hexColor.substring(2, 4), 16);
|
||||||
|
int blue = Integer.parseInt(hexColor.substring(4, 6), 16);
|
||||||
|
return new ORColor(red, green, blue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user