diff --git a/VERSION b/VERSION
index dd2601c..cdae3ef 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1,9 @@
+0.2.1
+October 22, 2020
+- COVID lockdown
+- Improvements to fixture/structure/JSON system
+- Many tweaks and improvements, new patterns/effects
+
0.2.0
May 28, 2020
- Lots of API cleanups
@@ -6,12 +12,12 @@ May 28, 2020
0.1.2
August 20, 2018
-- Fix bug with onActive/onInactive messages when pattern is deleted.
+-Fix bug with onActive/onInactive messages when pattern is deleted.
0.1.1
August 15, 2018
-- Dropping alpha tag, updating release packaging with VERSION and LICENSE files.
+-Dropping alpha tag, updating release packaging with VERSION and LICENSE files.
0.1.0-alpha
August 13, 2018
-- Initial release cut for tracking versioned changes across the LX repositories.
+-Initial release cut for tracking versioned changes across the LX repositories.
diff --git a/pom.xml b/pom.xml
index 252a4a3..cb4fe6c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
heronarts
p3lx
- 0.2.0
+ 0.2.1
jar
diff --git a/src/main/java/heronarts/p3lx/P3LX.java b/src/main/java/heronarts/p3lx/P3LX.java
index fa82d57..cfa7dee 100644
--- a/src/main/java/heronarts/p3lx/P3LX.java
+++ b/src/main/java/heronarts/p3lx/P3LX.java
@@ -132,6 +132,14 @@ public P3LX(PApplet applet, Flags flags, LXModel model) {
LX.initProfiler.log("P3LX: registerMethod");
}
+ @Override
+ protected void showConfirmUnsavedProjectDialog(String message, Runnable confirm) {
+ this.ui.showConfirmDialog(
+ "Your project has unsaved changes, really " + message + "?",
+ confirm
+ );
+ }
+
/**
* Subclass may override.
*
diff --git a/src/main/java/heronarts/p3lx/ui/CustomDeviceUI.java b/src/main/java/heronarts/p3lx/ui/CustomDeviceUI.java
deleted file mode 100644
index b1070f6..0000000
--- a/src/main/java/heronarts/p3lx/ui/CustomDeviceUI.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright 2013- Mark C. Slee, Heron Arts LLC
- *
- * This file is part of the LX Studio software library. By using
- * LX, you agree to the terms of the LX Studio Software License
- * and Distribution Agreement, available at: http://lx.studio/license
- *
- * Please note that the LX license is not open-source. The license
- * allows for free, non-commercial use.
- *
- * HERON ARTS MAKES NO WARRANTY, EXPRESS, IMPLIED, STATUTORY, OR
- * OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF
- * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR A PARTICULAR
- * PURPOSE, WITH RESPECT TO THE SOFTWARE.
- *
- * @author Mark C. Slee
- */
-
-package heronarts.p3lx.ui;
-
-public interface CustomDeviceUI {
- public abstract void buildDeviceUI(UI ui, UI2dContainer device);
-}
diff --git a/src/main/java/heronarts/p3lx/ui/UI.java b/src/main/java/heronarts/p3lx/ui/UI.java
index f67645a..a96d7dd 100644
--- a/src/main/java/heronarts/p3lx/ui/UI.java
+++ b/src/main/java/heronarts/p3lx/ui/UI.java
@@ -581,7 +581,7 @@ private boolean isMapping() {
return this.midiMapping || this.modulationSourceMapping || this.modulationTargetMapping || this.triggerSourceMapping || this.triggerTargetMapping;
}
- void setMouseoverHelpText(String helpText) {
+ public void setMouseoverHelpText(String helpText) {
if (!isMapping()) {
this.contextualHelpText.setValue(helpText);
}
diff --git a/src/main/java/heronarts/p3lx/ui/UI3dContext.java b/src/main/java/heronarts/p3lx/ui/UI3dContext.java
index e265c26..7efcd23 100644
--- a/src/main/java/heronarts/p3lx/ui/UI3dContext.java
+++ b/src/main/java/heronarts/p3lx/ui/UI3dContext.java
@@ -60,6 +60,7 @@ public class UI3dContext extends UIObject implements LXSerializable, UITabFocus
public static final int NUM_CAMERA_POSITIONS = 6;
public static interface MovementListener {
+ public void reset();
public void translate(float x, float y, float z);
public void rotate(float theta, float phi);
}
@@ -216,7 +217,7 @@ public String toString() {
*/
private final List movementListeners = new ArrayList();
- public final void addMovementistener(MovementListener listener) {
+ public final void addMovementListener(MovementListener listener) {
Objects.requireNonNull(listener, "Cannot add null UI3dContext.MovementListener");
if (this.movementListeners.contains(listener)) {
throw new IllegalStateException("Cannot add duplicate UI3dContext.MovementListener: " + listener);
@@ -937,6 +938,9 @@ protected void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
if (mouseEvent.getCount() > 1) {
focus(mouseEvent);
}
+ for (MovementListener listener : this.movementListeners) {
+ listener.reset();
+ }
}
private void updateFocusedCamera() {
diff --git a/src/main/java/heronarts/p3lx/ui/UIKeyEvent.java b/src/main/java/heronarts/p3lx/ui/UIKeyEvent.java
new file mode 100644
index 0000000..f3545e2
--- /dev/null
+++ b/src/main/java/heronarts/p3lx/ui/UIKeyEvent.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2018- Mark C. Slee, Heron Arts LLC
+ *
+ * This file is part of the LX Studio software library. By using
+ * LX, you agree to the terms of the LX Studio Software License
+ * and Distribution Agreement, available at: http://lx.studio/license
+ *
+ * Please note that the LX license is not open-source. The license
+ * allows for free, non-commercial use.
+ *
+ * HERON ARTS MAKES NO WARRANTY, EXPRESS, IMPLIED, STATUTORY, OR
+ * OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF
+ * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR A PARTICULAR
+ * PURPOSE, WITH RESPECT TO THE SOFTWARE.
+ *
+ * ##library.name##
+ * ##library.sentence##
+ * ##library.url##
+ *
+ * @author ##author##
+ * @modified ##date##
+ * @version ##library.prettyVersion## (##library.version##)
+ */
+
+package heronarts.p3lx.ui;
+
+import processing.core.PConstants;
+import processing.event.KeyEvent;
+
+public class UIKeyEvent {
+ // Should never be instantiated
+ private UIKeyEvent() {}
+
+ public static boolean isCommand(KeyEvent keyEvent) {
+ return keyEvent.isMetaDown() || keyEvent.isControlDown();
+ }
+
+ public static boolean isDelete(KeyEvent keyEvent, int keyCode) {
+ // NOTE(mcslee): there is serious hackiness under here, P3D surface uses
+ // JOGL key codes, and Processing remaps the character values but not the
+ // key codes...
+ //
+ // See PSurfaceJOGL hackToChar:
+ // https://github.com/processing/processing/blob/4cc297c66908899cd29480c202536ecf749854e8/core/src/processing/opengl/PSurfaceJOGL.java#L1187
+ return
+ (keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE) ||
+ (keyEvent.getKey() == PConstants.DELETE);
+ }
+}
diff --git a/src/main/java/heronarts/p3lx/ui/UIMouseEvent.java b/src/main/java/heronarts/p3lx/ui/UIMouseEvent.java
new file mode 100644
index 0000000..e50d87f
--- /dev/null
+++ b/src/main/java/heronarts/p3lx/ui/UIMouseEvent.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2018- Mark C. Slee, Heron Arts LLC
+ *
+ * This file is part of the LX Studio software library. By using
+ * LX, you agree to the terms of the LX Studio Software License
+ * and Distribution Agreement, available at: http://lx.studio/license
+ *
+ * Please note that the LX license is not open-source. The license
+ * allows for free, non-commercial use.
+ *
+ * HERON ARTS MAKES NO WARRANTY, EXPRESS, IMPLIED, STATUTORY, OR
+ * OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF
+ * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR A PARTICULAR
+ * PURPOSE, WITH RESPECT TO THE SOFTWARE.
+ *
+ * ##library.name##
+ * ##library.sentence##
+ * ##library.url##
+ *
+ * @author ##author##
+ * @modified ##date##
+ * @version ##library.prettyVersion## (##library.version##)
+ */
+
+package heronarts.p3lx.ui;
+
+import processing.event.MouseEvent;
+
+public class UIMouseEvent {
+ private UIMouseEvent() {}
+
+ public static boolean isCommand(MouseEvent mouseEvent) {
+ return mouseEvent.isMetaDown() || mouseEvent.isControlDown();
+ }
+
+ public static boolean isMultiSelect(MouseEvent mouseEvent) {
+ return mouseEvent.isMetaDown() || mouseEvent.isControlDown();
+ }
+
+ public static boolean isRangeSelect(MouseEvent mouseEvent) {
+ return mouseEvent.isShiftDown();
+ }
+}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIButton.java b/src/main/java/heronarts/p3lx/ui/component/UIButton.java
index 00326e2..d0e54fe 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIButton.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIButton.java
@@ -50,11 +50,21 @@ public Action(float w, float h) {
this(0, 0, w, h);
}
+ public Action(float w, float h, String label) {
+ this(0, 0, w, h, label);
+ }
+
public Action(float x, float y, float w, float h) {
super(x, y, w, h);
setBorderRounding(8);
setMomentary(true);
}
+
+ public Action(float x, float y, float w, float h, String label) {
+ this(x, y, w, h);
+ setLabel(label);
+ }
+
}
public static class Trigger extends UIButton {
@@ -62,6 +72,8 @@ public static class Trigger extends UIButton {
public static final int HEIGHT = 12;
public static final int WIDTH = 16;
+ private LXParameter controlTarget = null;
+
public Trigger(UI ui, float x, float y) {
this(ui, null, x, y);
}
@@ -75,6 +87,19 @@ public Trigger(UI ui, BooleanParameter trigger, float x, float y) {
setParameter(trigger);
}
}
+
+ public Trigger setControlTarget(LXParameter controlTarget) {
+ this.controlTarget = controlTarget;
+ return this;
+ }
+
+ @Override
+ public LXParameter getControlTarget() {
+ if (this.controlTarget != null) {
+ return this.controlTarget;
+ }
+ return super.getControlTarget();
+ }
}
protected boolean active = false;
@@ -379,13 +404,21 @@ protected UIButton setActive(boolean active, boolean pushToParameter) {
if (pushToParameter) {
if (this.enumParameter != null) {
if (active) {
- getLX().command.perform(new LXCommand.Parameter.Increment(this.enumParameter));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Increment(this.enumParameter));
+ } else {
+ this.enumParameter.increment();
+ }
}
} else if (this.booleanParameter != null) {
if (this.isMomentary) {
this.booleanParameter.setValue(active);
} else {
- getLX().command.perform(new LXCommand.Parameter.SetNormalized(this.booleanParameter, active));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetNormalized(this.booleanParameter, active));
+ } else {
+ this.booleanParameter.setValue(active);
+ }
}
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIButtonGroup.java b/src/main/java/heronarts/p3lx/ui/component/UIButtonGroup.java
index 7fabe57..e760df3 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIButtonGroup.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIButtonGroup.java
@@ -69,9 +69,17 @@ public UIButtonGroup(final DiscreteParameter parameter, float x, float y, float
public void onToggle(boolean enabled) {
if (!inParameterUpdate) {
if (enabled) {
- getLX().command.perform(new LXCommand.Parameter.SetValue(parameter, iv));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(parameter, iv));
+ } else {
+ parameter.setValue(iv);
+ }
} else if (hideFirst) {
- getLX().command.perform(new LXCommand.Parameter.SetValue(parameter, 0));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(parameter, 0));
+ } else {
+ parameter.setValue(0);
+ }
}
}
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UICheckbox.java b/src/main/java/heronarts/p3lx/ui/component/UICheckbox.java
new file mode 100644
index 0000000..4571e25
--- /dev/null
+++ b/src/main/java/heronarts/p3lx/ui/component/UICheckbox.java
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2013- Mark C. Slee, Heron Arts LLC
+ *
+ * This file is part of the LX Studio software library. By using
+ * LX, you agree to the terms of the LX Studio Software License
+ * and Distribution Agreement, available at: http://lx.studio/license
+ *
+ * Please note that the LX license is not open-source. The license
+ * allows for free, non-commercial use.
+ *
+ * HERON ARTS MAKES NO WARRANTY, EXPRESS, IMPLIED, STATUTORY, OR
+ * OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF
+ * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR A PARTICULAR
+ * PURPOSE, WITH RESPECT TO THE SOFTWARE.
+ *
+ * ##library.name##
+ * ##library.sentence##
+ * ##library.url##
+ *
+ * @author ##author##
+ * @modified ##date##
+ * @version ##library.prettyVersion## (##library.version##)
+ */
+
+package heronarts.p3lx.ui.component;
+
+import java.util.Objects;
+
+import heronarts.lx.command.LXCommand;
+import heronarts.lx.parameter.BooleanParameter;
+import heronarts.lx.parameter.LXListenableNormalizedParameter;
+import heronarts.lx.parameter.LXParameter;
+import heronarts.lx.parameter.LXParameterListener;
+import heronarts.p3lx.ui.UI;
+import heronarts.p3lx.ui.UIFocus;
+import heronarts.p3lx.ui.UITriggerSource;
+import heronarts.p3lx.ui.UITriggerTarget;
+import heronarts.p3lx.ui.UIControlTarget;
+import processing.core.PGraphics;
+import processing.event.KeyEvent;
+import processing.event.MouseEvent;
+
+public class UICheckbox extends UIParameterComponent implements UIControlTarget, UITriggerSource, UITriggerTarget, UIFocus {
+
+ public final static int DEFAULT_WIDTH = 10;
+ public final static int DEFAULT_HEIGHT = 10;
+
+ protected boolean active = false;
+ protected boolean isMomentary = false;
+
+ private boolean triggerable = false;
+
+ protected boolean enabled = true;
+
+ private BooleanParameter parameter = null;
+
+ private final LXParameterListener parameterListener = (p) -> {
+ setActive(this.parameter.isOn(), false);
+ };
+
+ public UICheckbox() {
+ this(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+
+ public UICheckbox(float w, BooleanParameter p) {
+ this(0, 0, w, w, p);
+ }
+
+ public UICheckbox(float x, float y) {
+ this(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ }
+
+ public UICheckbox(float x, float y, BooleanParameter p) {
+ this(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT, p);
+ }
+
+ public UICheckbox(float x, float y, float w, float h) {
+ this(x, y, w, h, null);
+ }
+
+ public UICheckbox(float x, float y, float w, float h, BooleanParameter p) {
+ super(x, y, w, h);
+ setParameter(p);
+ }
+
+ public UICheckbox setEnabled(boolean enabled) {
+ if (this.enabled != enabled) {
+ this.enabled = enabled;
+ redraw();
+ }
+ return this;
+ }
+
+ public UICheckbox setTriggerable(boolean triggerable) {
+ this.triggerable = triggerable;
+ return this;
+ }
+
+ @Override
+ public String getDescription() {
+ if (this.parameter != null) {
+ return UIParameterControl.getDescription(this.parameter);
+ }
+ return super.getDescription();
+ }
+
+ @Override
+ public LXListenableNormalizedParameter getParameter() {
+ return this.parameter;
+ }
+
+ public UICheckbox removeParameter() {
+ if (this.parameter != null) {
+ this.parameter.removeListener(this.parameterListener);
+ }
+ this.parameter = null;
+ return this;
+ }
+
+ public UICheckbox setParameter(BooleanParameter parameter) {
+ Objects.requireNonNull(parameter, "Cannot set null UICheckbox.setParameter() - use removeParameter() instead");
+ if (parameter != this.parameter) {
+ removeParameter();
+ if (parameter != null) {
+ this.parameter = parameter;
+ this.parameter.addListener(this.parameterListener);
+ setMomentary(this.parameter.getMode() == BooleanParameter.Mode.MOMENTARY);
+ setActive(this.parameter.isOn(), false);
+ }
+ }
+ return this;
+ }
+
+ public UICheckbox setMomentary(boolean momentary) {
+ this.isMomentary = momentary;
+ return this;
+ }
+
+ @Override
+ protected void onDraw(UI ui, PGraphics pg) {
+ // A lighter gray background color when the button is disabled, or it's engaged
+ // with a mouse press but the mouse has moved off the active button
+ int color = this.enabled ? ui.theme.getControlTextColor() : ui.theme.getControlDisabledColor();
+
+ pg.noFill();
+ pg.stroke(color);
+ pg.rect(1, 1, this.width-3, this.height-3);
+
+ if (this.active) {
+ pg.noStroke();
+ pg.fill(color);
+ pg.rect(3, 3, this.width - 6, this.height - 6);
+ }
+ }
+
+ @Override
+ protected void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
+ if (this.enabled) {
+ setActive(this.isMomentary ? true : !this.active);
+ }
+ }
+
+ @Override
+ protected void onMouseReleased(MouseEvent mouseEvent, float mx, float my) {
+ if (this.enabled) {
+ if (this.isMomentary) {
+ setActive(false);
+ }
+ }
+ }
+
+ @Override
+ protected void onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
+ if ((keyCode == java.awt.event.KeyEvent.VK_SPACE) || (keyCode == java.awt.event.KeyEvent.VK_ENTER)) {
+ if (this.enabled) {
+ setActive(this.isMomentary ? true : !this.active);
+ }
+ consumeKeyEvent();
+ }
+ }
+
+ @Override
+ protected void onKeyReleased(KeyEvent keyEvent, char keyChar, int keyCode) {
+ if ((keyCode == java.awt.event.KeyEvent.VK_SPACE) || (keyCode == java.awt.event.KeyEvent.VK_ENTER)) {
+ consumeKeyEvent();
+ if (this.enabled && this.isMomentary) {
+ setActive(false);
+ }
+ }
+ }
+
+ public boolean isActive() {
+ return this.active;
+ }
+
+ public UICheckbox setActive(boolean active) {
+ return setActive(active, true);
+ }
+
+ protected UICheckbox setActive(boolean active, boolean pushToParameter) {
+ if (this.active != active) {
+ this.active = active;
+ if (pushToParameter) {
+ if (this.parameter != null) {
+ if (this.isMomentary) {
+ this.parameter.setValue(active);
+ } else {
+ getLX().command.perform(new LXCommand.Parameter.SetNormalized(this.parameter, active));
+ }
+ }
+ }
+ onToggle(active);
+ redraw();
+ }
+ return this;
+ }
+
+ public UICheckbox toggle() {
+ return setActive(!this.active);
+ }
+
+ /**
+ * Subclasses may override this to handle changes to the button's state
+ *
+ * @param active Whether button is active
+ */
+ protected void onToggle(boolean active) {
+ }
+
+
+ @Override
+ public LXParameter getControlTarget() {
+ if (isMappable()) {
+ if (this.parameter != null) {
+ if (this.parameter.getParent() != null) {
+ return this.parameter;
+ }
+ } else {
+ return getTriggerParameter();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public BooleanParameter getTriggerSource() {
+ return this.triggerable ? getTriggerParameter() : null;
+ }
+
+ @Override
+ public BooleanParameter getTriggerTarget() {
+ return this.triggerable ? getTriggerParameter() : null;
+ }
+
+ private BooleanParameter getTriggerParameter() {
+ if (this.parameter != null && this.parameter.isMappable() && this.parameter.getParent() != null) {
+ return this.parameter;
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UICollapsibleSection.java b/src/main/java/heronarts/p3lx/ui/component/UICollapsibleSection.java
index 29c9756..dbc4537 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UICollapsibleSection.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UICollapsibleSection.java
@@ -108,16 +108,12 @@ public void onDraw(UI ui, PGraphics pg) {
pg.fill(0xff333333);
pg.rect(width-16, PADDING, 12, 12, 4);
pg.fill(ui.theme.getControlTextColor());
- if (this.expanded) {
- pg.beginShape();
- pg.vertex(this.width-7, 8.5f);
- pg.vertex(this.width-13, 8.5f);
- pg.vertex(this.width-10, 12.5f);
- pg.endShape(PConstants.CLOSE);
- } else {
- pg.ellipseMode(PConstants.CENTER);
- pg.ellipse(width-10, 10, 4, 4);
+
+ pg.rect(width-13, 9, 6, 2);
+ if (!this.expanded) {
+ pg.rect(width-11, 7, 2, 6);
}
+
}
/**
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIColorPicker.java b/src/main/java/heronarts/p3lx/ui/component/UIColorPicker.java
index c6b7b0c..623770b 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIColorPicker.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIColorPicker.java
@@ -48,6 +48,8 @@ public enum Corner {
private UIColorOverlay uiColorOverlay = null;
+ private boolean enabled = true;
+
public UIColorPicker(ColorParameter color) {
this(UIKnob.WIDTH, UIKnob.WIDTH, color);
}
@@ -82,6 +84,11 @@ protected void run() {
}
}
+ public UIColorPicker setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ return this;
+ }
+
private final LXParameterListener redrawSwatch = (p) -> {
if (this.uiColorOverlay != null) {
this.uiColorOverlay.swatch.redraw();
@@ -139,20 +146,24 @@ private void showOverlay() {
@Override
public void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
- consumeMousePress();
- showOverlay();
+ if (this.enabled) {
+ consumeMousePress();
+ showOverlay();
+ }
super.onMousePressed(mouseEvent, mx, my);
}
@Override
public void onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
- if (keyCode == java.awt.event.KeyEvent.VK_ENTER || keyCode == java.awt.event.KeyEvent.VK_SPACE) {
- consumeKeyEvent();
- showOverlay();
- } else if (keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
- if ((this.uiColorOverlay != null) && (this.uiColorOverlay.isVisible())) {
+ if (this.enabled) {
+ if (keyCode == java.awt.event.KeyEvent.VK_ENTER || keyCode == java.awt.event.KeyEvent.VK_SPACE) {
consumeKeyEvent();
- hideOverlay();
+ showOverlay();
+ } else if (keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
+ if ((this.uiColorOverlay != null) && (this.uiColorOverlay.isVisible())) {
+ consumeKeyEvent();
+ hideOverlay();
+ }
}
}
super.onKeyPressed(keyEvent, keyChar, keyCode);
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIDoubleBox.java b/src/main/java/heronarts/p3lx/ui/component/UIDoubleBox.java
index b218003..d6ed6f2 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIDoubleBox.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIDoubleBox.java
@@ -65,8 +65,16 @@ public UIDoubleBox(float w, BoundedParameter parameter) {
this(0, 0, w, parameter);
}
+ public UIDoubleBox(float w, float h, BoundedParameter parameter) {
+ this(0, 0, w, h, parameter);
+ }
+
public UIDoubleBox(float x, float y, float w, BoundedParameter parameter) {
- this(x, y, w, DEFAULT_HEIGHT);
+ this(x, y, w, DEFAULT_HEIGHT, parameter);
+ }
+
+ public UIDoubleBox(float x, float y, float w, float h, BoundedParameter parameter) {
+ this(x, y, w, h);
setParameter(parameter);
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIDropMenu.java b/src/main/java/heronarts/p3lx/ui/component/UIDropMenu.java
index e641370..4601085 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIDropMenu.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIDropMenu.java
@@ -107,7 +107,11 @@ public UIDropMenu setParameter(DiscreteParameter parameter) {
this.actions[i] = new UIContextActions.Action(String.valueOf(i)) {
@Override
public void onContextAction(UI ui) {
- getLX().command.perform(new LXCommand.Parameter.SetValue(parameter, ii));
+ if (useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(parameter, ii));
+ } else {
+ parameter.setValue(ii);
+ }
}
};
}
@@ -214,10 +218,18 @@ public void onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
toggleExpanded();
} else if (keyCode == java.awt.event.KeyEvent.VK_DOWN) {
consumeKeyEvent();
- getLX().command.perform(new LXCommand.Parameter.Increment(this.parameter));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Increment(this.parameter));
+ } else {
+ this.parameter.increment();
+ }
} else if (keyCode == java.awt.event.KeyEvent.VK_UP) {
consumeKeyEvent();
- getLX().command.perform(new LXCommand.Parameter.Decrement(this.parameter));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Decrement(this.parameter));
+ } else {
+ this.parameter.decrement();
+ }
} else if (keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
if (this.contextMenu.isVisible()) {
consumeKeyEvent();
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIDynamicColorPicker.java b/src/main/java/heronarts/p3lx/ui/component/UIDynamicColorPicker.java
index 4918724..a688b92 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIDynamicColorPicker.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIDynamicColorPicker.java
@@ -25,6 +25,7 @@
import heronarts.p3lx.ui.UI2dComponent;
import heronarts.p3lx.ui.UI2dContainer;
import heronarts.p3lx.ui.UIFocus;
+import heronarts.p3lx.ui.UIKeyEvent;
import heronarts.p3lx.ui.UITimerTask;
import processing.core.PConstants;
import processing.core.PGraphics;
@@ -62,7 +63,7 @@ protected void drawFocus(UI ui, PGraphics pg) {
@Override
public void onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
- if (keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE || keyCode == java.awt.event.KeyEvent.VK_DELETE) {
+ if (UIKeyEvent.isDelete(keyEvent, keyCode)) {
if (this.dynamicColor.getIndex() > 0) {
consumeKeyEvent();
hideOverlay();
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIInputBox.java b/src/main/java/heronarts/p3lx/ui/component/UIInputBox.java
index 1ade6c1..6e8d1f0 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIInputBox.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIInputBox.java
@@ -54,6 +54,7 @@ public interface ProgressIndicator {
protected boolean returnKeyEdit = true;
+ private boolean mousePressEdit = false;
private boolean immediateEdit = false;
private ProgressIndicator progressMeter;
@@ -134,6 +135,11 @@ public UIInputBox enableImmediateEdit(boolean immediateEdit) {
return this;
}
+ public UIInputBox enableMousePressEdit(boolean mousePressEdit) {
+ this.mousePressEdit = mousePressEdit;
+ return this;
+ }
+
protected abstract String getValueString();
protected abstract void saveEditBuffer();
@@ -345,7 +351,11 @@ protected void setValueCommand(double value) {
if (this.mouseDragSetValue != null) {
getLX().command.perform(this.mouseDragSetValue.update(value));
} else if (getParameter() != null){
- getLX().command.perform(new LXCommand.Parameter.SetValue(getParameter(), value));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(getParameter(), value));
+ } else {
+ getParameter().setValue(value);
+ }
}
}
@@ -355,7 +365,13 @@ protected void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
this.dAccum = 0;
LXParameter parameter = getParameter();
if (parameter != null) {
- this.mouseDragSetValue = new LXCommand.Parameter.SetValue(parameter, 0);
+ if (this.useCommandEngine) {
+ this.mouseDragSetValue = new LXCommand.Parameter.SetValue(parameter, 0);
+ }
+ }
+ if (this.enabled && this.editable && !this.editing && this.mousePressEdit) {
+ edit();
+ redraw();
}
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIIntegerBox.java b/src/main/java/heronarts/p3lx/ui/component/UIIntegerBox.java
index 787e2a7..bd655f2 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIIntegerBox.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIIntegerBox.java
@@ -43,10 +43,8 @@ public class UIIntegerBox extends UINumberBox implements UIControlTarget {
protected DiscreteParameter parameter = null;
protected int editMultiplier = 1;
- private final LXParameterListener parameterListener = new LXParameterListener() {
- public void onParameterChanged(LXParameter p) {
- setValue(parameter.getValuei(), false);
- }
+ private final LXParameterListener parameterListener = (p) -> {
+ setValue(this.parameter.getValuei(), false);
};
public UIIntegerBox() {
@@ -71,6 +69,11 @@ public String getDescription() {
return UIParameterControl.getDescription(this.parameter);
}
+ @Override
+ public LXParameter getParameter() {
+ return this.parameter;
+ }
+
public UIIntegerBox setParameter(final DiscreteParameter parameter) {
if (this.parameter != parameter) {
if (this.parameter != null) {
@@ -150,7 +153,11 @@ protected UIIntegerBox setValue(int value, boolean pushToParameter) {
}
this.value = min + (value - min) % range;
if (this.parameter != null && pushToParameter) {
- getLX().command.perform(new LXCommand.Parameter.SetValue(this.parameter, this.value));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(this.parameter, this.value));
+ } else {
+ this.parameter.setValue(this.value);
+ }
}
this.onValueChange(this.value);
redraw();
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIItemList.java b/src/main/java/heronarts/p3lx/ui/component/UIItemList.java
index f2d189e..d03aff5 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIItemList.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIItemList.java
@@ -35,6 +35,7 @@
import heronarts.p3lx.ui.UI2dContainer;
import heronarts.p3lx.ui.UI2dScrollContext;
import heronarts.p3lx.ui.UIFocus;
+import heronarts.p3lx.ui.UIKeyEvent;
import processing.core.PConstants;
import processing.core.PGraphics;
import processing.event.Event;
@@ -813,7 +814,7 @@ private boolean onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
}
activate();
}
- } else if (keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE) {
+ } else if (UIKeyEvent.isDelete(keyEvent, keyCode)) {
consume = true;
delete();
} else if (keyEvent.isControlDown() || keyEvent.isMetaDown()) {
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIKnob.java b/src/main/java/heronarts/p3lx/ui/component/UIKnob.java
index ae49049..5595435 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIKnob.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIKnob.java
@@ -197,9 +197,17 @@ protected void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
if (isEditable() && (this.parameter != null) && (mouseEvent.getCount() > 1)) {
LXCompoundModulation modulation = getModulation(mouseEvent.isShiftDown());
if (modulation != null && (mouseEvent.isControlDown() || mouseEvent.isMetaDown())) {
- getLX().command.perform(new LXCommand.Parameter.Reset(modulation.range));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Reset(modulation.range));
+ } else {
+ modulation.range.reset();
+ }
} else {
- getLX().command.perform(new LXCommand.Parameter.Reset(this.parameter));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Reset(this.parameter));
+ } else {
+ this.parameter.reset();
+ }
}
}
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIParameterComponent.java b/src/main/java/heronarts/p3lx/ui/component/UIParameterComponent.java
index 0cd79a0..045409a 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIParameterComponent.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIParameterComponent.java
@@ -16,13 +16,13 @@ public abstract class UIParameterComponent extends UI2dComponent implements UICo
public static final float DEFAULT_HEIGHT = 16;
+ protected boolean useCommandEngine = true;
+
protected UIParameterComponent(float x, float y, float w, float h) {
super(x, y, w, h);
}
- public LXParameter getParameter() {
- return null;
- }
+ public abstract LXParameter getParameter();
public String getOscAddress() {
LXParameter parameter = getParameter();
@@ -32,6 +32,11 @@ public String getOscAddress() {
return null;
}
+ public UIParameterComponent setUseCommandEngine(boolean useCommandEngine) {
+ this.useCommandEngine = useCommandEngine;
+ return this;
+ }
+
@Override
public List getContextActions() {
List actions = new ArrayList();
@@ -53,7 +58,9 @@ protected void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
super.onMousePressed(mouseEvent, mx, my);
LXParameter parameter = getParameter();
if (parameter != null && parameter instanceof LXNormalizedParameter) {
- this.mouseEditCommand = new LXCommand.Parameter.SetNormalized((LXNormalizedParameter) parameter);
+ if (this.useCommandEngine) {
+ this.mouseEditCommand = new LXCommand.Parameter.SetNormalized((LXNormalizedParameter) parameter);
+ }
}
}
@@ -69,7 +76,11 @@ protected void setNormalizedCommand(double newValue) {
} else {
LXParameter parameter = getParameter();
if (parameter != null && parameter instanceof LXNormalizedParameter) {
- getLX().command.perform(new LXCommand.Parameter.SetNormalized((LXNormalizedParameter) parameter, newValue));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetNormalized((LXNormalizedParameter) parameter, newValue));
+ } else {
+ ((LXNormalizedParameter) parameter).setNormalized(newValue);
+ }
}
}
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UIParameterControl.java b/src/main/java/heronarts/p3lx/ui/component/UIParameterControl.java
index 0282cfa..5cd252f 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UIParameterControl.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UIParameterControl.java
@@ -46,6 +46,7 @@
import heronarts.p3lx.ui.UI;
import heronarts.p3lx.ui.UIControlTarget;
import heronarts.p3lx.ui.UICopy;
+import heronarts.p3lx.ui.UIKeyEvent;
import heronarts.p3lx.ui.UIModulationSource;
import heronarts.p3lx.ui.UIModulationTarget;
import heronarts.p3lx.ui.UIPaste;
@@ -262,7 +263,11 @@ protected void saveEditBuffer() {
for (String part : parts) {
value = value * 60 + Double.parseDouble(part);
}
- getLX().command.perform(new LXCommand.Parameter.SetValue(this.parameter, value * multiplier));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(this.parameter, value * multiplier));
+ } else {
+ this.parameter.setValue(value * multiplier);
+ }
break;
default:
// No colon character allowed for other types
@@ -270,7 +275,11 @@ protected void saveEditBuffer() {
}
} else {
double value = Double.parseDouble(this.editBuffer);
- getLX().command.perform(new LXCommand.Parameter.SetValue(this.parameter, value));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetValue(this.parameter, value));
+ } else {
+ this.parameter.setValue(value);
+ }
}
} catch (NumberFormatException nfx) {}
}
@@ -317,9 +326,17 @@ protected void decrementValue(KeyEvent keyEvent) {
consumeKeyEvent();
if (this.parameter instanceof DiscreteParameter) {
DiscreteParameter dp = (DiscreteParameter) this.parameter;
- getLX().command.perform(new LXCommand.Parameter.Decrement(dp, keyEvent.isShiftDown() ? dp.getRange() / 10 : 1));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Decrement(dp, keyEvent.isShiftDown() ? dp.getRange() / 10 : 1));
+ } else {
+ dp.decrement(keyEvent.isShiftDown() ? dp.getRange() / 10 : 1);
+ }
} else if (this.parameter instanceof BooleanParameter) {
- getLX().command.perform(new LXCommand.Parameter.SetNormalized((BooleanParameter) this.parameter, false));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetNormalized((BooleanParameter) this.parameter, false));
+ } else {
+ ((BooleanParameter) this.parameter).setValue(false);
+ }
} else {
setNormalized(getNormalized() - getIncrement(keyEvent));
}
@@ -338,9 +355,17 @@ protected void incrementValue(KeyEvent keyEvent) {
consumeKeyEvent();
if (this.parameter instanceof DiscreteParameter) {
DiscreteParameter dp = (DiscreteParameter) this.parameter;
- getLX().command.perform(new LXCommand.Parameter.Increment(dp, keyEvent.isShiftDown() ? dp.getRange() / 10 : 1));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Increment(dp, keyEvent.isShiftDown() ? dp.getRange() / 10 : 1));
+ } else {
+ dp.increment(keyEvent.isShiftDown() ? dp.getRange() / 10 : 1);
+ }
} else if (this.parameter instanceof BooleanParameter) {
- getLX().command.perform(new LXCommand.Parameter.SetNormalized((BooleanParameter) this.parameter, true));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.SetNormalized((BooleanParameter) this.parameter, true));
+ } else {
+ ((BooleanParameter) this.parameter).setValue(true);
+ }
} else {
setNormalized(getNormalized() + getIncrement(keyEvent));
}
@@ -353,7 +378,7 @@ protected void onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
if ((keyCode == java.awt.event.KeyEvent.VK_SPACE) || (keyCode == java.awt.event.KeyEvent.VK_ENTER)) {
consumeKeyEvent();
setShowValue(true);
- } else if (isEnabled() && isEditable() && keyEvent.isShiftDown() && keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE) {
+ } else if (isEnabled() && isEditable() && keyEvent.isShiftDown() && UIKeyEvent.isDelete(keyEvent, keyCode)) {
consumeKeyEvent();
if (this.parameter != null) {
this.parameter.reset();
diff --git a/src/main/java/heronarts/p3lx/ui/component/UISwitch.java b/src/main/java/heronarts/p3lx/ui/component/UISwitch.java
index 794b7e9..e552795 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UISwitch.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UISwitch.java
@@ -106,7 +106,11 @@ protected void onKeyPressed(KeyEvent keyEvent, char keyChar, int keyCode) {
if (this.isMomentary) {
getBooleanParameter().setValue(true);
} else {
- getLX().command.perform(new LXCommand.Parameter.Toggle(getBooleanParameter()));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Toggle(getBooleanParameter()));
+ } else {
+ getBooleanParameter().toggle();
+ }
}
}
}
@@ -137,7 +141,11 @@ protected void onMousePressed(MouseEvent mouseEvent, float mx, float my) {
if (this.isMomentary) {
getBooleanParameter().setValue(true);
} else {
- getLX().command.perform(new LXCommand.Parameter.Toggle(getBooleanParameter()));
+ if (this.useCommandEngine) {
+ getLX().command.perform(new LXCommand.Parameter.Toggle(getBooleanParameter()));
+ } else {
+ getBooleanParameter().toggle();
+ }
}
}
}
diff --git a/src/main/java/heronarts/p3lx/ui/component/UITextBox.java b/src/main/java/heronarts/p3lx/ui/component/UITextBox.java
index c5e7fb2..e04c197 100644
--- a/src/main/java/heronarts/p3lx/ui/component/UITextBox.java
+++ b/src/main/java/heronarts/p3lx/ui/component/UITextBox.java
@@ -40,10 +40,8 @@ public class UITextBox extends UIInputBox implements UICopy, UIPaste {
private String value = NO_VALUE;
private StringParameter parameter = null;
- private final LXParameterListener parameterListener = new LXParameterListener() {
- public void onParameterChanged(LXParameter p) {
- setValue(parameter.getString(), false);
- }
+ private final LXParameterListener parameterListener = (p) -> {
+ setValue(this.parameter.getString(), false);
};
public UITextBox() {
@@ -54,6 +52,11 @@ public UITextBox(float x, float y, float w, float h) {
super(x, y, w, h);
}
+ @Override
+ public LXParameter getParameter() {
+ return this.parameter;
+ }
+
public UITextBox setParameter(StringParameter parameter) {
if (this.parameter != null) {
this.parameter.removeListener(this.parameterListener);
@@ -95,7 +98,11 @@ public UITextBox setValue(String value, boolean pushToParameter) {
if (!this.value.equals(value)) {
this.value = value;
if (pushToParameter && (this.parameter != null)) {
- getUI().lx.command.perform(new LXCommand.Parameter.SetString(this.parameter, value));
+ if (this.useCommandEngine) {
+ getUI().lx.command.perform(new LXCommand.Parameter.SetString(this.parameter, value));
+ } else {
+ this.parameter.setValue(value);
+ }
}
this.onValueChange(this.value);
redraw();