diff --git a/vassal-app/src/main/java/VASSAL/build/module/properties/EnumeratedPropertyPrompt.java b/vassal-app/src/main/java/VASSAL/build/module/properties/EnumeratedPropertyPrompt.java index 09dc106cb9..5bcb551d07 100644 --- a/vassal-app/src/main/java/VASSAL/build/module/properties/EnumeratedPropertyPrompt.java +++ b/vassal-app/src/main/java/VASSAL/build/module/properties/EnumeratedPropertyPrompt.java @@ -17,6 +17,7 @@ */ package VASSAL.build.module.properties; +import VASSAL.build.GameModule; import VASSAL.build.module.GlobalOptions; import VASSAL.script.expression.AuditTrail; import VASSAL.script.expression.Auditable; @@ -61,7 +62,7 @@ public String getNewValue(String oldValue) { try { final AuditTrail audit = AuditTrail.create(constraints == null ? null : constraints.getPropertySource(), valueExpressions[i].getExpression()); if (constraints == null) { - value = valueExpressions[i].evaluate(constraints.getPropertySource(), audit); + value = valueExpressions[i].evaluate(GameModule.getGameModule(), null, audit); } else { value = valueExpressions[i].evaluate(constraints.getPropertySource(), constraints.getPropertySource(), audit); diff --git a/vassal-app/src/main/java/VASSAL/build/module/properties/IncrementProperty.java b/vassal-app/src/main/java/VASSAL/build/module/properties/IncrementProperty.java index d012bcc974..ff020375d0 100644 --- a/vassal-app/src/main/java/VASSAL/build/module/properties/IncrementProperty.java +++ b/vassal-app/src/main/java/VASSAL/build/module/properties/IncrementProperty.java @@ -55,6 +55,10 @@ public Constraints getPropSource() { return constraints; } + public void setConstraints(Constraints constraints) { + this.constraints = constraints; + } + @Override public String getNewValue(String oldValue) { int value; diff --git a/vassal-app/src/main/java/VASSAL/build/module/properties/RemoteIncrementProperty.java b/vassal-app/src/main/java/VASSAL/build/module/properties/RemoteIncrementProperty.java index c6dab99cb5..a357a606f8 100644 --- a/vassal-app/src/main/java/VASSAL/build/module/properties/RemoteIncrementProperty.java +++ b/vassal-app/src/main/java/VASSAL/build/module/properties/RemoteIncrementProperty.java @@ -32,7 +32,11 @@ public class RemoteIncrementProperty extends IncrementProperty implements Remote protected PropertySource targetPropertySource; public RemoteIncrementProperty(IncrementProperty ip) { - super(ip.getProp(), ip.getRawValue(), ip.constraints); + this(ip.getProp(), ip.getRawValue(), ip.constraints); + } + + public RemoteIncrementProperty(PropertyChangerConfigurer prop, String incr, Constraints constraints) { + super(prop, incr, constraints); } @Override diff --git a/vassal-app/src/main/java/VASSAL/counters/SetPieceProperty.java b/vassal-app/src/main/java/VASSAL/counters/SetPieceProperty.java index 33db1043e7..8ac55b8a95 100644 --- a/vassal-app/src/main/java/VASSAL/counters/SetPieceProperty.java +++ b/vassal-app/src/main/java/VASSAL/counters/SetPieceProperty.java @@ -79,6 +79,7 @@ public class SetPieceProperty extends DynamicProperty implements RecursionLimite protected boolean fixedRange = true; protected int range; protected String rangeProperty = ""; + protected boolean overrideConstrants = false; protected Decorator dec; @@ -144,6 +145,7 @@ public void mySetType(String s) { fixedRange = sd.nextBoolean(true); rangeProperty = sd.nextToken(""); globalSetter.setSelectFromDeckExpression(sd.nextToken("-1")); + overrideConstrants = sd.nextBoolean(false); } @Override @@ -160,6 +162,7 @@ public String myGetType() { se.append(fixedRange); se.append(rangeProperty); se.append(globalSetter.getSelectFromDeckExpression()); + se.append(overrideConstrants); return ID + se.getValue(); } @@ -243,6 +246,7 @@ public HelpFile getHelpFile() { private RemotePropertyChanger changer = null; private String newValue = null; private boolean cancelled; + private DynamicProperty currentDPTarget = null; /** * Our filter has found a matching piece. Check it for a matching Dynamic Property and if found apply our setter. @@ -263,6 +267,7 @@ public Command makeSetTargetCommand(GamePiece p) { if (propName.equals(currentDP.getKey())) { if ((newValue == null) || !(changer instanceof PropertyPrompt)) { + currentDPTarget = currentDP; final String userValue = changer.getNewValue(currentDP, this, Decorator.getOutermost(this)); // A changer only returns null if the user pressed cancel in a Prompt or List dialog. @@ -357,6 +362,34 @@ else if (changer instanceof PropertyPrompt) { return null; } + // + // The following 4 over-rides are called when the PropertyChanger is activated to determine + // the numeric constraints to follow when applying the change to a specific remote DP. + // If this trait is not over-riding the numeric constraints, then use the constraints of the + // target DP. + // NOTE: Constraints.getPropertySource() is not over-ridden, it is handled separately by the + // Remote Property Setters. + // + @Override + public int getMaximumValue() { + return (overrideConstrants || currentDPTarget == null) ? super.getMaximumValue() : currentDPTarget.getMaximumValue(); + } + + @Override + public int getMinimumValue() { + return (overrideConstrants || currentDPTarget == null) ? super.getMinimumValue() : currentDPTarget.getMinimumValue(); + } + + @Override + public boolean isNumeric() { + return (overrideConstrants || currentDPTarget == null) ? super.isNumeric() : currentDPTarget.isNumeric(); + } + + @Override + public boolean isWrap() { + return (overrideConstrants || currentDPTarget == null) ? super.isWrap() : currentDPTarget.isWrap(); + } + @Override public PieceEditor getEditor() { return new Ed(this); @@ -377,12 +410,15 @@ public boolean testEquals(Object o) { if (! Objects.equals(range, c.range)) return false; if (! Objects.equals(fixedRange, c.fixedRange)) return false; if (! Objects.equals(rangeProperty, c.rangeProperty)) return false; + if (! Objects.equals(overrideConstrants, c.overrideConstrants)) return false; return Objects.equals(globalSetter.getSelectFromDeckExpression(), c.globalSetter.getSelectFromDeckExpression()); } protected static class Ed implements PieceEditor { protected StringConfigurer descConfig; protected FormattedExpressionConfigurer nameConfig; + protected BooleanConfigurer overrideConfig; + protected JLabel numericLabel; protected BooleanConfigurer numericConfig; protected JLabel minLabel; protected IntConfigurer minConfig; @@ -427,8 +463,12 @@ public Ed(final SetPieceProperty m) { nameConfig.setHintKey("Editor.SetPieceProperty.property_name_hint"); controls.add("Editor.SetPieceProperty.property_name", nameConfig); + overrideConfig = new BooleanConfigurer(m.overrideConstrants); + controls.add("Editor.SetPieceProperty.override_constraints", overrideConfig); + + numericLabel = new JLabel(Resources.getString("Editor.DynamicProperty.is_numeric")); numericConfig = new BooleanConfigurer(m.isNumeric()); - controls.add("Editor.DynamicProperty.is_numeric", numericConfig); + controls.add(numericLabel, numericConfig); minLabel = new JLabel(Resources.getString("Editor.GlobalProperty.minimum_value")); minConfig = new IntConfigurer(m.getMinimumValue()); @@ -474,16 +514,21 @@ public Ed(final SetPieceProperty m) { controls.add("Editor.DynamicProperty.key_commands", keyCommandListConfig); - numericConfig.addPropertyChangeListener(evt -> { + final PropertyChangeListener nl = evt -> { + final boolean isOverride = overrideConfig.booleanValue(); final boolean isNumeric = numericConfig.booleanValue(); - minConfig.getControls().setVisible(isNumeric); - minLabel.setVisible(isNumeric); - maxConfig.getControls().setVisible(isNumeric); - maxLabel.setVisible(isNumeric); - wrapConfig.getControls().setVisible(isNumeric); - wrapLabel.setVisible(isNumeric); + numericLabel.setVisible(isOverride); + numericConfig.getControls().setVisible(isOverride); + minConfig.getControls().setVisible(isOverride && isNumeric); + minLabel.setVisible(isOverride && isNumeric); + maxConfig.getControls().setVisible(isOverride && isNumeric); + maxLabel.setVisible(isOverride && isNumeric); + wrapConfig.getControls().setVisible(isOverride && isNumeric); + wrapLabel.setVisible(isOverride && isNumeric); keyCommandListConfig.repack(); - }); + }; + overrideConfig.addPropertyChangeListener(nl); + numericConfig.addPropertyChangeListener(nl); numericConfig.fireUpdate(); @@ -504,6 +549,7 @@ public Ed(final SetPieceProperty m) { restrictRange.addPropertyChangeListener(pl); fixedRange.addPropertyChangeListener(pl); + fixedRange.fireUpdate(); pl.propertyChange(null); } @@ -537,6 +583,7 @@ public String getType() { se.append(fixedRange.getValueString()); se.append(rangeProperty.getValueString()); se.append(deckPolicy.getValueString()); + se.append(overrideConfig.getValueString()); return ID + se.getValue(); } diff --git a/vassal-app/src/main/resources/VASSAL/i18n/Editor.properties b/vassal-app/src/main/resources/VASSAL/i18n/Editor.properties index 9f5436b32e..851cf663ea 100644 --- a/vassal-app/src/main/resources/VASSAL/i18n/Editor.properties +++ b/vassal-app/src/main/resources/VASSAL/i18n/Editor.properties @@ -2136,6 +2136,7 @@ Editor.SetPieceProperty.trait_description=Set Piece Property Editor.SetPieceProperty.property_name=Property Name Editor.SetPieceProperty.property_name_hint=Name of property to set (Can be expression) Editor.SetPieceProperty.matching_properties=Property Match Expression +Editor.SetPieceProperty.override_constraints=Over-ride numeric constraints in target properties # Setup Stack Editor.SetupStack.reposition_stack=Reposition stack diff --git a/vassal-doc/src/main/readme-referencemanual/ReferenceManual/SetPieceProperty.adoc b/vassal-doc/src/main/readme-referencemanual/ReferenceManual/SetPieceProperty.adoc index eddf0ec0a5..cb2713c19f 100644 --- a/vassal-doc/src/main/readme-referencemanual/ReferenceManual/SetPieceProperty.adoc +++ b/vassal-doc/src/main/readme-referencemanual/ReferenceManual/SetPieceProperty.adoc @@ -19,7 +19,10 @@ _{ "Resources" + GetProperty("Side")_ }. In this case when the property Side hol NOTE: The <> trait must exist on the target pieces. This trait does not 'create' new <>. -*Is numeric:*:: If true, then changes to the value of the property by this trait will be restricted to integer values. +*Over-ride numeric constraints in target properties:*:: If left unticked, then the Set Property Piece trait will use whatever (if any) numeric constraints have been specified in the Dynamic Properties that it updates. If ticked, then the following 4 options appear and allow you to ignore or over-ride any numeric constraints in the target property. + + +*Is numeric:*:: If true, then changes to the value of the property by this trait will be restricted to integer values. If left unticked, then the following 3 options do not appear and this trait will set exactly the value specified. *Minimum value:*:: Numeric values will be restricted to no less than this number when changed by this trait. diff --git a/vassal-doc/src/main/readme-referencemanual/ReferenceManual/images/SetPieceProperty.png b/vassal-doc/src/main/readme-referencemanual/ReferenceManual/images/SetPieceProperty.png index 16e716f6af..97e73fa860 100644 Binary files a/vassal-doc/src/main/readme-referencemanual/ReferenceManual/images/SetPieceProperty.png and b/vassal-doc/src/main/readme-referencemanual/ReferenceManual/images/SetPieceProperty.png differ