From d28add4e21071108389bf73b2f1be6341c4a9827 Mon Sep 17 00:00:00 2001
From: tobias <thinkdifferent055@gmail.com>
Date: Wed, 8 Dec 2021 21:54:56 +0100
Subject: [PATCH] #182 - Add PlaylistNextAction

---
 .../main/java/de/tobias/playpad/Strings.java  |  1 +
 .../action/actions/PlaylistNextAction.java    | 80 +++++++++++++++++++
 .../action/factory/CartActionProvider.java    |  1 -
 .../factory/PlaylistNextActionProvider.java   | 73 +++++++++++++++++
 .../settings/CartActionSettingsEntry.java     |  4 +-
 .../PlaylistNextActionSettingsEntry.java      | 28 +++++++
 .../actions/AbstractActionViewController.java |  8 ++
 .../actions/CartActionTypeViewController.java | 27 ++++---
 .../actions/CartActionViewController.java     |  3 +-
 .../src/main/resources/components/Actions.xml | 14 +++-
 .../src/main/resources/lang/_de.properties    |  1 +
 .../de/tobias/playpad/profile/Profile.java    |  4 +
 12 files changed, 229 insertions(+), 15 deletions(-)
 create mode 100644 PlayWall/src/main/java/de/tobias/playpad/action/actions/PlaylistNextAction.java
 create mode 100644 PlayWall/src/main/java/de/tobias/playpad/action/factory/PlaylistNextActionProvider.java
 create mode 100644 PlayWall/src/main/java/de/tobias/playpad/action/settings/PlaylistNextActionSettingsEntry.java
 create mode 100644 PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/AbstractActionViewController.java

diff --git a/PlayWall/src/main/java/de/tobias/playpad/Strings.java b/PlayWall/src/main/java/de/tobias/playpad/Strings.java
index e71f1944..e7dd1a75 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/Strings.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/Strings.java
@@ -183,6 +183,7 @@ public class Strings {
 	public static final String ACTION_PAGE_TO_STRING = "Action.Page.toString";
 	public static final String ACTION_NAVIGATE_TO_STRING = "Action.Navigate.toString";
 	public static final String ACTION_CART_NAME = "Action.Cart.Name";
+	public static final String ACTION_PLAYLIST_NEXT_NAME = "Action.PlaylistNext.Name";
 	public static final String ACTION_STOP_NAME = "Action.Stop.Name";
 	public static final String ACTION_PAGE_NAME = "Action.Page.Name";
 	public static final String ACTION_NAVIGATE_NAME = "Action.Navigate.Name";
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/actions/PlaylistNextAction.java b/PlayWall/src/main/java/de/tobias/playpad/action/actions/PlaylistNextAction.java
new file mode 100644
index 00000000..0ed0a95f
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/actions/PlaylistNextAction.java
@@ -0,0 +1,80 @@
+package de.tobias.playpad.action.actions;
+
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.event.KeyEvent;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.tobias.playpad.PlayPadPlugin;
+import de.tobias.playpad.pad.Pad;
+import de.tobias.playpad.pad.content.Playlistable;
+import de.tobias.playpad.project.Project;
+import de.tobias.playpad.viewcontroller.main.IMainViewController;
+
+public class PlaylistNextAction extends ActionHandler {
+	public static final String TYPE = "PlaylistNextAction";
+	public static final String PAYLOAD_X = "x";
+	public static final String PAYLOAD_Y = "y";
+
+	@Override
+	public String actionType() {
+		return TYPE;
+	}
+
+	@Override
+	public FeedbackType handle(KeyEvent keyEvent, Action action) {
+		final Pad pad = getPad(action);
+		if (pad == null) {
+			return FeedbackType.NONE;
+		}
+
+		if (pad.hasVisibleContent() && pad.getContent() instanceof Playlistable) {
+			((Playlistable) pad.getContent()).next();
+		}
+		return getCurrentFeedbackType(action);
+	}
+
+	@Override
+	public FeedbackType getCurrentFeedbackType(Action action) {
+		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+
+		Pad pad = project.getPad(getX(action), getY(action), mainViewController.getPage());
+
+		if (pad == null || !(pad.getContent() instanceof Playlistable)) {
+			return FeedbackType.NONE;
+		}
+		return FeedbackType.DEFAULT;
+	}
+
+	public Pad getPad(Action action) {
+		Project project = PlayPadPlugin.getInstance().getCurrentProject();
+		IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController();
+
+		int x = getX(action);
+		int y = getY(action);
+		final int page = mainViewController.getPage();
+
+		return project.getPad(x, y, page);
+	}
+
+	/*
+	Property accessors
+	 */
+
+	public static int getY(Action action) {
+		return Integer.parseInt(action.getPayload(PAYLOAD_Y));
+	}
+
+	public static int getX(Action action) {
+		return Integer.parseInt(action.getPayload(PAYLOAD_X));
+	}
+
+	public static void setX(Action action, int x) {
+		action.addPayloadEntry(CartAction.PAYLOAD_X, String.valueOf(x));
+	}
+
+	public static void setY(Action action, int y) {
+		action.addPayloadEntry(CartAction.PAYLOAD_Y, String.valueOf(y));
+	}
+
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java b/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java
index 7b078335..43e38b7c 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/factory/CartActionProvider.java
@@ -8,7 +8,6 @@ import de.thecodelabs.midi.mapping.KeyType;
 import de.tobias.playpad.action.ActionProvider;
 import de.tobias.playpad.action.ActionType;
 import de.tobias.playpad.action.actions.CartAction;
-import de.tobias.playpad.action.actions.CartAction.*;
 import de.tobias.playpad.action.settings.ActionSettingsEntry;
 import de.tobias.playpad.action.settings.CartActionSettingsEntry;
 import de.tobias.playpad.project.ProjectSettings;
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/factory/PlaylistNextActionProvider.java b/PlayWall/src/main/java/de/tobias/playpad/action/factory/PlaylistNextActionProvider.java
new file mode 100644
index 00000000..f317e7e0
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/factory/PlaylistNextActionProvider.java
@@ -0,0 +1,73 @@
+package de.tobias.playpad.action.factory;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.midi.action.ActionHandler;
+import de.thecodelabs.midi.feedback.FeedbackType;
+import de.thecodelabs.midi.mapping.KeyType;
+import de.tobias.playpad.action.ActionProvider;
+import de.tobias.playpad.action.ActionType;
+import de.tobias.playpad.action.actions.PlaylistNextAction;
+import de.tobias.playpad.action.settings.ActionSettingsEntry;
+import de.tobias.playpad.action.settings.PlaylistNextActionSettingsEntry;
+import de.tobias.playpad.project.ProjectSettings;
+import javafx.scene.control.TreeItem;
+
+import java.util.List;
+
+import static de.tobias.playpad.action.actions.PlaylistNextAction.*;
+
+public class PlaylistNextActionProvider extends ActionProvider {
+
+	public PlaylistNextActionProvider(String type) {
+		super(TYPE);
+	}
+
+	@Override
+	public String getType() {
+		return TYPE;
+	}
+
+	@Override
+	public ActionHandler getActionHandler() {
+		return new PlaylistNextAction();
+	}
+
+	@Override
+	public void createDefaultActions(Mapping mapping) {
+		for (int x = 0; x < ProjectSettings.MAX_COLUMNS; x++) {
+			for (int y = 0; y < ProjectSettings.MAX_ROWS; y++) {
+				Action action = newInstance(x, y);
+				mapping.addUniqueAction(action);
+			}
+		}
+	}
+
+	private Action newInstance(int x, int y) {
+		Action action = new Action(getType());
+		action.addPayloadEntry(PAYLOAD_X, String.valueOf(x));
+		action.addPayloadEntry(PAYLOAD_Y, String.valueOf(y));
+		return action;
+	}
+
+	@Override
+	public FeedbackType[] supportedFeedbackOptions(Action action, KeyType keyType) {
+		switch (keyType) {
+			case KEYBOARD:
+				return new FeedbackType[0];
+			case MIDI:
+				return new FeedbackType[]{FeedbackType.DEFAULT};
+		}
+		return new FeedbackType[0];
+	}
+
+	@Override
+	public ActionType getActionType() {
+		return ActionType.CONTROL;
+	}
+
+	@Override
+	public TreeItem<ActionSettingsEntry> getTreeItemForActions(List<Action> actions, Mapping mapping) {
+		return new TreeItem<>(new PlaylistNextActionSettingsEntry());
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java
index ea345132..725a321b 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/CartActionSettingsEntry.java
@@ -5,8 +5,10 @@ import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.ui.icon.FontIcon;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
+import de.tobias.playpad.action.actions.CartAction;
 import de.tobias.playpad.viewcontroller.IMappingTabViewController;
 import de.tobias.playpad.viewcontroller.actions.CartActionTypeViewController;
+import de.tobias.playpad.viewcontroller.actions.CartActionViewController;
 
 public class CartActionSettingsEntry implements ActionSettingsEntry {
 
@@ -22,6 +24,6 @@ public class CartActionSettingsEntry implements ActionSettingsEntry {
 
 	@Override
 	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
-		return new CartActionTypeViewController(mapping, controller);
+		return new CartActionTypeViewController(mapping, controller, CartAction.TYPE, new CartActionViewController());
 	}
 }
diff --git a/PlayWall/src/main/java/de/tobias/playpad/action/settings/PlaylistNextActionSettingsEntry.java b/PlayWall/src/main/java/de/tobias/playpad/action/settings/PlaylistNextActionSettingsEntry.java
new file mode 100644
index 00000000..8548c9d5
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/action/settings/PlaylistNextActionSettingsEntry.java
@@ -0,0 +1,28 @@
+package de.tobias.playpad.action.settings;
+
+import de.thecodelabs.midi.Mapping;
+import de.thecodelabs.utils.ui.NVC;
+import de.thecodelabs.utils.ui.icon.FontIcon;
+import de.thecodelabs.utils.util.Localization;
+import de.tobias.playpad.Strings;
+import de.tobias.playpad.action.actions.PlaylistNextAction;
+import de.tobias.playpad.viewcontroller.IMappingTabViewController;
+import de.tobias.playpad.viewcontroller.actions.CartActionTypeViewController;
+
+public class PlaylistNextActionSettingsEntry implements ActionSettingsEntry {
+
+	@Override
+	public String getName() {
+		return Localization.getString(Strings.ACTION_PLAYLIST_NEXT_NAME);
+	}
+
+	@Override
+	public FontIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public NVC getDetailSettingsController(Mapping mapping, IMappingTabViewController controller) {
+		return new CartActionTypeViewController(mapping, controller, PlaylistNextAction.TYPE);
+	}
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/AbstractActionViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/AbstractActionViewController.java
new file mode 100644
index 00000000..6f378756
--- /dev/null
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/AbstractActionViewController.java
@@ -0,0 +1,8 @@
+package de.tobias.playpad.viewcontroller.actions;
+
+import de.thecodelabs.midi.action.Action;
+import de.thecodelabs.utils.ui.NVC;
+
+public abstract class AbstractActionViewController extends NVC {
+	public abstract void setCartAction(Action action);
+}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java
index 8573b914..da08e59d 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionTypeViewController.java
@@ -36,17 +36,24 @@ public class CartActionTypeViewController extends NVC {
 	@FXML
 	private VBox cartActionContainer;
 
-	private CartActionViewController cartActionViewController;
+	private final AbstractActionViewController actionViewController;
+	private final String actionType;
 
-	private Mapping mapping;
-	private IMappingTabViewController parentController;
+	private final Mapping mapping;
+	private final IMappingTabViewController parentController;
 
-	public CartActionTypeViewController(Mapping mapping, IMappingTabViewController parentController) {
+
+	public CartActionTypeViewController(Mapping mapping, IMappingTabViewController parentController, String actionType) {
+		this(mapping, parentController, actionType,null);
+	}
+
+	public CartActionTypeViewController(Mapping mapping, IMappingTabViewController parentController, String actionType, AbstractActionViewController actionViewController) {
 		load("view/actions", "CartActions", Localization.getBundle());
 		this.mapping = mapping;
 		this.parentController = parentController;
 
-		cartActionViewController = new CartActionViewController();
+		this.actionType = actionType;
+		this.actionViewController = actionViewController;
 
 		Project currentProject = PlayPadMain.getProgramInstance().getCurrentProject();
 		ProjectSettings settings = currentProject.getSettings();
@@ -106,12 +113,14 @@ public class CartActionTypeViewController extends NVC {
 			int currentY = data[1];
 
 			try {
-				List<Action> cartActions = mapping.getActionsForType(CartAction.TYPE);
+				List<Action> cartActions = mapping.getActionsForType(actionType);
 				for (Action action : cartActions) {
 					if (CartAction.getX(action) == currentX && CartAction.getY(action) == currentY) {
-						cartActionContainer.getChildren().setAll(cartActionViewController.getParent());
-						cartActionContainer.setVisible(true);
-						cartActionViewController.setCartAction(action);
+						if (actionViewController != null) {
+							cartActionContainer.getChildren().setAll(actionViewController.getParent());
+							cartActionContainer.setVisible(true);
+							actionViewController.setCartAction(action);
+						}
 						parentController.showMapperFor(action);
 					}
 				}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java
index b43977c2..737251c6 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/actions/CartActionViewController.java
@@ -13,7 +13,7 @@ import javafx.scene.control.ComboBox;
 import javafx.scene.layout.Priority;
 import javafx.scene.layout.VBox;
 
-public class CartActionViewController extends NVC {
+public class CartActionViewController extends AbstractActionViewController {
 
 	@FXML
 	private ComboBox<CartActionMode> controlMode;
@@ -41,6 +41,7 @@ public class CartActionViewController extends NVC {
 		VBox.setVgrow(rootContainer, Priority.ALWAYS);
 	}
 
+	@Override
 	public void setCartAction(Action action) {
 		this.action = action;
 
diff --git a/PlayWall/src/main/resources/components/Actions.xml b/PlayWall/src/main/resources/components/Actions.xml
index f992162e..39e66640 100644
--- a/PlayWall/src/main/resources/components/Actions.xml
+++ b/PlayWall/src/main/resources/components/Actions.xml
@@ -1,16 +1,24 @@
 <Actions>
-    <Component id="CartAction" name="Action.Cart.Name" icon="TH" class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
+    <Component id="CartAction" name="Action.Cart.Name" icon="TH"
+               class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
                size="11">
         de.tobias.playpad.action.factory.CartActionProvider
     </Component>
-    <Component id="PageAction" name="Action.Page.Name" icon="FILE_TEXT" class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
+    <Component id="PlaylistNextAction" name="Action.PlaylistNext.Name" icon="TH"
+               class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
+               size="11">
+        de.tobias.playpad.action.factory.PlaylistNextActionProvider
+    </Component>
+    <Component id="PageAction" name="Action.Page.Name" icon="FILE_TEXT"
+               class="de.thecodelabs.utils.ui.icon.FontAwesomeType"
                size="11">de.tobias.playpad.action.factory.PageActionProvider
     </Component>
     <Component id="NavigateAction" name="Action.Navigate.Name" icon="NAVIGATION"
                class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon" size="11">
         de.tobias.playpad.action.factory.NavigateActionProvider
     </Component>
-    <Component id="StopAction" name="Action.Stop.Name" icon="STOP" class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon"
+    <Component id="StopAction" name="Action.Stop.Name" icon="STOP"
+               class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon"
                size="11">de.tobias.playpad.action.factory.StopActionProvider
     </Component>
 </Actions>
\ No newline at end of file
diff --git a/PlayWall/src/main/resources/lang/_de.properties b/PlayWall/src/main/resources/lang/_de.properties
index 7058dabd..36d62169 100755
--- a/PlayWall/src/main/resources/lang/_de.properties
+++ b/PlayWall/src/main/resources/lang/_de.properties
@@ -167,6 +167,7 @@ Action.Cart.toString=Kachel {}
 Action.Page.toString=Seite {}
 Action.Navigate.toString={}
 Action.Cart.Name=Kacheln
+Action.PlaylistNext.Name=Playlist
 Action.Stop.Name=Stop
 Action.Page.Name=Seiten
 Action.Navigate.Name=Navigation
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
index 7e50c4dc..e33b1d13 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java
@@ -146,6 +146,10 @@ public class Profile {
 
 			setCurrentProfile(profile);
 
+			// Update mapping with new actions
+			final Registry<ActionProvider> actions = PlayPadPlugin.getRegistries().getActions();
+			actions.getComponents().forEach(provider -> provider.createDefaultActions(currentMapping));
+
 			return profile;
 		}
 		throw new ProfileNotFoundException(ref);
-- 
GitLab