diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 573656f6b552ab704fd9f1ad893286475dda5049..c1500a33cb5596556ab38560f449acbae8fbe473 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -16,6 +16,7 @@ <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/src/main/resources" charset="UTF-8" /> + <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/src/main/resources" charset="UTF-8" /> @@ -32,6 +33,7 @@ <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI" charset="UTF-8" /> + <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources" charset="UTF-8" /> <file url="PROJECT" charset="UTF-8" /> </component> diff --git a/.idea/modules.xml b/.idea/modules.xml index 71a1574f2f6df494b2028c78bb51cb89fc3ba39e..ae20783ca82797f27ca5b049467c233d031158e8 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -7,6 +7,7 @@ <module fileurl="file://$PROJECT_DIR$/PlayWallCore/PlayWallCore.iml" filepath="$PROJECT_DIR$/PlayWallCore/PlayWallCore.iml" /> <module fileurl="file://$PROJECT_DIR$/PlayWallDesktop.iml" filepath="$PROJECT_DIR$/PlayWallDesktop.iml" /> <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/PlayWallPluginAwake.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginAwake/PlayWallPluginAwake.iml" /> + <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginContentPlayer/PlayWallPluginContentPlayer.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginContentPlayer/PlayWallPluginContentPlayer.iml" /> <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/PlayWallPluginEqualizer.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginEqualizer/PlayWallPluginEqualizer.iml" /> <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginLaunchpad/PlayWallPluginLaunchpad.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginLaunchpad/PlayWallPluginLaunchpad.iml" /> <module fileurl="file://$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginMedia/PlayWallPluginMedia.iml" filepath="$PROJECT_DIR$/PlayWallPlugins/PlayWallPluginMedia/PlayWallPluginMedia.iml" /> diff --git a/PlayWall/pom.xml b/PlayWall/pom.xml index ccb9aec7567cc8e913e7b5c597793d72e9e1183f..e339a9b3049ae791a35ba7f8a2a48e8804854d16 100644 --- a/PlayWall/pom.xml +++ b/PlayWall/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallDesktop</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWall</artifactId> diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java index f3f434f50447c73577d67fdb21460933fcb5ea93..a8590e8ec2ffe39a877e882a444c9b82085d98f3 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java +++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java @@ -26,6 +26,8 @@ import de.tobias.playpad.viewcontroller.dialog.project.ProjectLoadDialog; import de.tobias.playpad.viewcontroller.dialog.project.ProjectReaderDelegateImpl; import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.main.MainViewController; +import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController; +import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; import javafx.application.Application; import javafx.application.Platform; import javafx.scene.image.Image; @@ -37,21 +39,24 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import java.util.function.Supplier; public class PlayPadImpl implements PlayPad { - private Application.Parameters parameters; + private final Application.Parameters parameters; - private List<MainWindowListener> mainViewListeners = new ArrayList<>(); - private List<SettingsListener> settingsListeners = new ArrayList<>(); - private List<PadListener> padListeners = new ArrayList<>(); - private List<GlobalListener> globalListeners = new ArrayList<>(); + private final List<MainWindowListener> mainViewListeners = new ArrayList<>(); + private final List<SettingsListener> settingsListeners = new ArrayList<>(); + private final List<PadListener> padListeners = new ArrayList<>(); + private final List<GlobalListener> globalListeners = new ArrayList<>(); + private final List<Supplier<ProfileSettingsTabViewController>> additionalProfileSettingsTabs = new ArrayList<>(); + private final List<Supplier<GlobalSettingsTabViewController>> additionalGlobalSettingsTabs = new ArrayList<>(); private MainViewController mainViewController; private Image stageIcon; private Project currentProject; - private Module module; + private final Module module; private UpdateService updateService; protected GlobalSettings globalSettings; @@ -242,6 +247,26 @@ public class PlayPadImpl implements PlayPad { return updateService; } + @Override + public void addAdditionalProfileSettingsTab(Supplier<ProfileSettingsTabViewController> tab) { + additionalProfileSettingsTabs.add(tab); + } + + @Override + public List<Supplier<ProfileSettingsTabViewController>> getAdditionalProfileSettingsTabs() { + return additionalProfileSettingsTabs; + } + + @Override + public void addGlobalSettingsTab(Supplier<GlobalSettingsTabViewController> tab) { + additionalGlobalSettingsTabs.add(tab); + } + + @Override + public List<Supplier<GlobalSettingsTabViewController>> getGlobalSettingsTabs() { + return additionalGlobalSettingsTabs; + } + /* Getter / Setter */ diff --git a/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java index 47696ffe718bf872dd71584a00689ac476f8d041..79b2b7b6aae33c837fff88e2546954a85186fb52 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java +++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadMain.java @@ -18,6 +18,7 @@ import de.tobias.playpad.profile.ref.ProfileReferenceManager; import de.tobias.playpad.project.Project; import de.tobias.playpad.project.ref.ProjectReferenceManager; import de.tobias.playpad.update.VersionUpdater; +import de.tobias.playpad.util.ListSerializer; import de.tobias.playpad.util.UUIDSerializer; import de.tobias.playpad.viewcontroller.SplashScreenViewController; import io.github.openunirest.http.Unirest; @@ -36,6 +37,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.UUID; /* @@ -65,6 +67,7 @@ public class PlayPadMain extends Application { // Register UserDefaults Serializer UserDefaults.registerLoader(new UUIDSerializer(), UUID.class); + UserDefaults.registerLoader(new ListSerializer(), ArrayList.class); ApplicationUtils.addAppListener(PlayPadMain::applicationWillStart); App app = ApplicationUtils.registerMainApplication(PlayPadMain.class); @@ -89,6 +92,7 @@ public class PlayPadMain extends Application { @Override public void init() { App app = ApplicationUtils.getApplication(); + Logger.info("Running on Java: " + System.getProperty("java.version") + " (" + System.getProperty("java.vendor") + ")"); Logger.info("Run Path: {0}", SystemUtils.getRunPath()); // Init SSLContext diff --git a/PlayWall/src/main/java/de/tobias/playpad/Strings.java b/PlayWall/src/main/java/de/tobias/playpad/Strings.java index b28adcf21884f13366e14acc1b2f28b5a7ad0b00..e71f1944b156d2853018669b92e0ba6366fa9595 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/Strings.java +++ b/PlayWall/src/main/java/de/tobias/playpad/Strings.java @@ -173,6 +173,7 @@ public class Strings { // UI - Window - PadSettings public static final String UI_WINDOW_PAD_SETTINGS_GENERAL_TITLE = "UI.Window.PadSettings.General.Title"; + public static final String UI_WINDOW_PAD_SETTINGS_PLAYLIST_TITLE = "UI.Window.PadSettings.Playlist.Title"; public static final String UI_WINDOW_PAD_SETTINGS_PLAYER_TITLE = "UI.Window.PadSettings.Player.Title"; public static final String UI_WINDOW_PAD_SETTINGS_LAYOUT_TITLE = "UI.Window.PadSettings.Layout.Title"; public static final String UI_WINDOW_PAD_SETTINGS_TRIGGER_TITLE = "UI.Window.PadSettings.Trigger.Title"; diff --git a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java index d7ebadfc7f1e14ae7e77ffa5cad5ae4d618f71e5..ffd70e7b8b949a039aeb21718fdd335de4193f16 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java +++ b/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignAnimator.java @@ -1,7 +1,7 @@ package de.tobias.playpad.design; import de.tobias.playpad.pad.view.IPadView; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.util.FadeableColor; import de.tobias.playpad.view.PseudoClasses; import javafx.animation.KeyFrame; @@ -23,7 +23,7 @@ public class ModernDesignAnimator { private static HashMap<Integer, Timeline> timelines = new HashMap<>(); - public static void animateFade(IPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) { + public static void animateFade(AbstractPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) { ObjectProperty<FadeableColor> backgroundColor = new SimpleObjectProperty<>(); Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0), new KeyValue(backgroundColor, startColor)), @@ -32,7 +32,7 @@ public class ModernDesignAnimator { animate(padViewController, timeline, backgroundColor); } - public static void animateWarn(IPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) { + public static void animateWarn(AbstractPadViewController padViewController, FadeableColor startColor, FadeableColor endColor, Duration duration) { ObjectProperty<FadeableColor> backgroundColor = new SimpleObjectProperty<>(); Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0), new KeyValue(backgroundColor, startColor)), @@ -45,7 +45,7 @@ public class ModernDesignAnimator { animate(padViewController, timeline, backgroundColor); } - private static void animate(IPadViewController padViewController, Timeline timeline, ObjectProperty<FadeableColor> objectProperty) { + private static void animate(AbstractPadViewController padViewController, Timeline timeline, ObjectProperty<FadeableColor> objectProperty) { int index = padViewController.getPad().getPosition(); if (timelines.containsKey(index)) { @@ -68,7 +68,7 @@ public class ModernDesignAnimator { timelines.put(index, timeline); } - public static void stopAnimation(IPadViewController controller) { + public static void stopAnimation(AbstractPadViewController controller) { int index = controller.getPad().getPosition(); if (timelines.containsKey(index)) { @@ -76,7 +76,7 @@ public class ModernDesignAnimator { } } - public static void warnFlash(IPadViewController controller) { + public static void warnFlash(AbstractPadViewController controller) { final IPadView view = controller.getView(); try { while (!Thread.interrupted()) { diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java index ef01fa96ae6a41cef3f5c94a11d706aa28e51410..a3aa32c486a7ef02b1d297b042edbfe8249baafb 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMainLayoutFactory.java @@ -21,9 +21,9 @@ import java.util.Deque; public class DesktopMainLayoutFactory extends MainLayoutFactory { private DesktopMenuToolbarViewController desktopMenuToolbarViewController; - private ObjectProperty<DesktopEditMode> editMode = new SimpleObjectProperty<>(DesktopEditMode.PLAY); + private final ObjectProperty<DesktopEditMode> editMode = new SimpleObjectProperty<>(DesktopEditMode.PLAY); - private Deque<IPadView> recyclingStack; + private final Deque<IPadView> recyclingStack; public DesktopMainLayoutFactory(String type) { super(type); diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java index fc6d030e7c7ca0032590d9df3395200e4f7c1371..aacddf3f434ca9ed7d05381521cfaeb3d870b95b 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java @@ -26,6 +26,7 @@ import de.tobias.playpad.project.Project; import de.tobias.playpad.project.ProjectNotFoundException; import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbortException; import de.tobias.playpad.project.ProjectSettings; +import de.tobias.playpad.project.ProjectSettingsValidator; import de.tobias.playpad.project.page.Page; import de.tobias.playpad.project.ref.ProjectReference; import de.tobias.playpad.project.ref.ProjectReferenceManager; @@ -65,6 +66,7 @@ import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.TextField; import javafx.scene.control.*; +import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCombination; import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBox; @@ -155,7 +157,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro private transient DesktopColorPickerView colorPickerView; private transient PadRemoveMouseListener padRemoveMouseListener; - private DesktopMainLayoutFactory connect; + private final DesktopMainLayoutFactory connect; DesktopMenuToolbarViewController(IMainViewController controller, DesktopMainLayoutFactory connect) { super("Header", "view/main/desktop", Localization.getBundle()); @@ -303,8 +305,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro int index = 1; // Für Tastenkombination for (MainLayoutFactory connect : mainLayouts.getComponents()) { - if(connect.getType().equals(profileSettings.getMainLayoutType())) - { + if (connect.getType().equals(profileSettings.getMainLayoutType())) { continue; } @@ -324,7 +325,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro layoutMenu.getItems().add(item); index++; - } + } } @Override @@ -699,6 +700,34 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro } } + @FXML + void addColumnToProject() { + ProjectSettingsValidator projectSettingsValidator = new ProjectSettingsValidator(mainViewController.getScreen()); + final int maxValue = projectSettingsValidator.maxValue(ProjectSettingsValidator.Dimension.COLUMNS); + if (maxValue < openProject.getSettings().getColumns() + 1) { + showErrorMessage(Localization.getString("Error.Screen.TooMuch", maxValue)); + return; + } + + openProject.addColumn(); + mainViewController.createPadViews(); + mainViewController.showPage(mainViewController.getPage()); + } + + @FXML + void addRowToProject() { + ProjectSettingsValidator projectSettingsValidator = new ProjectSettingsValidator(mainViewController.getScreen()); + final int maxValue = projectSettingsValidator.maxValue(ProjectSettingsValidator.Dimension.ROWS); + if (maxValue < openProject.getSettings().getRows() + 1) { + showErrorMessage(Localization.getString("Error.Screen.TooMuch", maxValue)); + return; + } + + openProject.addRow(); + mainViewController.createPadViews(); + mainViewController.showPage(mainViewController.getPage()); + } + @FXML void alwaysOnTopItemHandler(ActionEvent event) { boolean selected = alwaysOnTopItem.isSelected(); @@ -728,6 +757,12 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro NotificationPane pane = mainViewController.getNotificationPane(); pane.setOnShown(e -> searchField.requestFocus()); pane.show("", box); + + searchField.setOnKeyPressed(e -> { + if (e.getCode() == KeyCode.ESCAPE) { + pane.hide(); + } + }); } @FXML diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java index 94c9d6cb155705a2eb67eb7b6bcef255ef71517f..ff626503c43c96606ff23dbf7dea99e14cc0ce81 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopPageEditButtonView.java @@ -2,11 +2,13 @@ package de.tobias.playpad.layout.desktop; import de.thecodelabs.utils.ui.icon.FontAwesomeType; import de.thecodelabs.utils.ui.icon.FontIcon; +import de.thecodelabs.utils.ui.icon.FontIconType; import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.PlayPadMain; import de.tobias.playpad.PlayPadPlugin; import de.tobias.playpad.Strings; import de.tobias.playpad.project.Project; +import de.tobias.playpad.project.ProjectSettings; import de.tobias.playpad.project.page.Page; import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController; @@ -20,17 +22,21 @@ import javafx.stage.Stage; import java.util.Optional; -public class DesktopPageEditButtonView extends HBox implements EventHandler<ActionEvent> { +public class DesktopPageEditButtonView extends HBox { - private Page page; - private Button leftMoveButton; - private Button rightMoveButton; - private Button editTextButton; - private Button cloneButton; - private Button deleteButton; + private static class EditButton extends Button { + private EditButton(FontIconType icon, EventHandler<ActionEvent> onAction, String tooltip) { + super("", new FontIcon(icon)); + setOnAction(onAction); + setTooltip(new Tooltip(tooltip)); + setFocusTraversable(false); + } + } - private transient MenuToolbarViewController controller; - private transient IMainViewController mainViewController; + private final Page page; + + private final transient MenuToolbarViewController controller; + private final transient IMainViewController mainViewController; DesktopPageEditButtonView(MenuToolbarViewController controller, IMainViewController mainViewController, Page page) { this.page = page; @@ -38,112 +44,98 @@ public class DesktopPageEditButtonView extends HBox implements EventHandler<Acti this.controller = controller; this.mainViewController = mainViewController; - leftMoveButton = new Button("", new FontIcon(FontAwesomeType.ARROW_LEFT)); - leftMoveButton.setOnAction(this); - leftMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_LEFT_MOVE))); - leftMoveButton.setFocusTraversable(false); + Button leftMoveButton = new EditButton(FontAwesomeType.ARROW_LEFT, this::onLeftButton, Localization.getString(Strings.TOOLTIP_PAGE_LEFT_MOVE)); + Button rightMoveButton = new EditButton(FontAwesomeType.ARROW_RIGHT, this::onRightButton, Localization.getString(Strings.TOOLTIP_PAGE_RIGHT_MOVE)); + Button editTextButton = new EditButton(FontAwesomeType.EDIT, this::onRenameButton, Localization.getString(Strings.TOOLTIP_PAGE_RENAME)); + Button cloneButton = new EditButton(FontAwesomeType.COPY, this::onCloneButton, Localization.getString(Strings.TOOLTIP_PAGE_CLONE)); + Button deleteButton = new EditButton(FontAwesomeType.TRASH, this::onDeleteButton, Localization.getString(Strings.TOOLTIP_PAGE_DELETE)); - rightMoveButton = new Button("", new FontIcon(FontAwesomeType.ARROW_RIGHT)); - rightMoveButton.setOnAction(this); - rightMoveButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_RIGHT_MOVE))); - rightMoveButton.setFocusTraversable(false); + getChildren().addAll(leftMoveButton, rightMoveButton, editTextButton, cloneButton, deleteButton); + setSpacing(7); + } - editTextButton = new Button("", new FontIcon(FontAwesomeType.EDIT)); - editTextButton.setOnAction(this); - editTextButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_RENAME))); - editTextButton.setFocusTraversable(false); + private void onLeftButton(ActionEvent event) { + final Project project = page.getProject(); + if (page.getPosition() > 0) { + final Page leftPage = project.getPage(page.getPosition() - 1); - cloneButton = new Button("", new FontIcon(FontAwesomeType.COPY)); - cloneButton.setOnAction(this); - cloneButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_CLONE))); - cloneButton.setFocusTraversable(false); + final int leftIndex = leftPage.getPosition(); + final int rightIndex = page.getPosition(); - deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH)); - deleteButton.setOnAction(this); - deleteButton.setTooltip(new Tooltip(Localization.getString(Strings.TOOLTIP_PAGE_DELETE))); - deleteButton.setFocusTraversable(false); + project.setPage(rightIndex, leftPage); + project.setPage(leftIndex, page); - getChildren().addAll(leftMoveButton, rightMoveButton, editTextButton, cloneButton, deleteButton); - setSpacing(7); + if (mainViewController.getMenuToolbarController() != null) + mainViewController.getMenuToolbarController().initPageButtons(); + mainViewController.showPage(leftIndex); + } + event.consume(); } - @Override - public void handle(ActionEvent event) { - if (event.getSource() == leftMoveButton) { - Project project = page.getProject(); - if (page.getPosition() > 0) { - Page leftPage = project.getPage(page.getPosition() - 1); + private void onRightButton(ActionEvent event) { + final Project project = page.getProject(); + if (page.getPosition() < project.getPages().size()) { + final Page rightPage = project.getPage(page.getPosition() + 1); - int leftIndex = leftPage.getPosition(); - int rightIndex = page.getPosition(); + final int rightIndex = rightPage.getPosition(); + final int leftIndex = page.getPosition(); - project.setPage(rightIndex, leftPage); - project.setPage(leftIndex, page); + project.setPage(leftIndex, rightPage); + project.setPage(rightIndex, page); - IMainViewController controller = PlayPadPlugin.getInstance().getMainViewController(); - if (controller.getMenuToolbarController() != null) - controller.getMenuToolbarController().initPageButtons(); - controller.showPage(leftIndex); - } - event.consume(); - } else if (event.getSource() == rightMoveButton) { - Project project = page.getProject(); - if (page.getPosition() < project.getPages().size()) { - Page rightPage = project.getPage(page.getPosition() + 1); + if (mainViewController.getMenuToolbarController() != null) + mainViewController.getMenuToolbarController().initPageButtons(); + mainViewController.showPage(rightIndex); + } + event.consume(); + } - int rightIndex = rightPage.getPosition(); - int leftIndex = page.getPosition(); + private void onRenameButton(ActionEvent event) { + showPageNameDialog(page); + } - project.setPage(leftIndex, rightPage); - project.setPage(rightIndex, page); + private void onCloneButton(ActionEvent event) { + final Page clone = page.copy(); - IMainViewController controller = PlayPadPlugin.getInstance().getMainViewController(); - if (controller.getMenuToolbarController() != null) - controller.getMenuToolbarController().initPageButtons(); - controller.showPage(rightIndex); - } - event.consume(); - } else if (event.getSource() == editTextButton) { - showPageNameDialog(page); + // Show Rename dialog for cloned page + boolean success = showPageNameDialog(clone); - event.consume(); - } else if (event.getSource() == cloneButton) { - Page clone = page.copy(); + if (!success) { + return; + } - // Show Rename dialog for cloned page - boolean success = showPageNameDialog(clone); + Project project = page.getProject(); + boolean added = project.addPage(clone); - if (!success) { - return; - } + if (!added) { + mainViewController.showErrorMessage(Localization.getString(Strings.ERROR_PROJECT_PAGE_COUNT, ProjectSettings.MAX_PAGES)); + return; + } - Project project = page.getProject(); - project.addPage(clone); + controller.initPageButtons(); + mainViewController.showPage(clone); + } + + private void onDeleteButton(ActionEvent event) { + Alert alert = new Alert(AlertType.CONFIRMATION); + + alert.setHeaderText(Localization.getString(Strings.UI_DIALOG_PAGE_DELETE_HEADER)); + alert.setContentText(Localization.getString(Strings.UI_DIALOG_PAGE_DELETE_CONTENT)); + alert.initOwner(controller.getContainingWindow()); + alert.initModality(Modality.WINDOW_MODAL); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(PlayPadPlugin.getInstance().getIcon()); + Optional<ButtonType> result = alert.showAndWait(); + result.filter(r -> r == ButtonType.OK).ifPresent(r -> + { + Project project = page.getProject(); + project.removePage(page); + PlayPadMain.getProgramInstance().getMainViewController().showPage(0); controller.initPageButtons(); - mainViewController.showPage(clone); + controller.highlightPageButton(0); // Show first page event.consume(); - } else if (event.getSource() == deleteButton) { - Alert alert = new Alert(AlertType.CONFIRMATION); - - alert.setHeaderText(Localization.getString(Strings.UI_DIALOG_PAGE_DELETE_HEADER)); - alert.setContentText(Localization.getString(Strings.UI_DIALOG_PAGE_DELETE_CONTENT)); - alert.initOwner(controller.getContainingWindow()); - alert.initModality(Modality.WINDOW_MODAL); - Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); - stage.getIcons().add(PlayPadPlugin.getInstance().getIcon()); - - Optional<ButtonType> result = alert.showAndWait(); - result.filter(r -> r == ButtonType.OK).ifPresent(r -> - { - Project project = page.getProject(); - project.removePage(page); - PlayPadMain.getProgramInstance().getMainViewController().showPage(0); - controller.initPageButtons(); - controller.highlightPageButton(0); // Show first page - event.consume(); - }); - } + }); } private boolean showPageNameDialog(Page page) { diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/PadNewContentListener.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/PadNewContentListener.java new file mode 100644 index 0000000000000000000000000000000000000000..fedd12aea0879dbda04f8cc41b28c335c4807a8e --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/listener/PadNewContentListener.java @@ -0,0 +1,100 @@ +package de.tobias.playpad.layout.desktop.listener; + +import de.thecodelabs.utils.application.ApplicationUtils; +import de.thecodelabs.utils.util.Localization; +import de.tobias.playpad.PlayPadPlugin; +import de.tobias.playpad.Strings; +import de.tobias.playpad.layout.desktop.pad.DesktopPadViewController; +import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.content.PadContentFactory; +import de.tobias.playpad.pad.content.PadContentRegistry; +import de.tobias.playpad.registry.NoSuchComponentException; +import de.tobias.playpad.settings.GlobalSettings; +import javafx.event.ActionEvent; +import javafx.scene.Node; +import javafx.stage.FileChooser; +import javafx.stage.Window; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +public class PadNewContentListener { + + private final Pad pad; + + public PadNewContentListener(Pad pad) { + this.pad = pad; + } + + public List<File> showMediaOpenFileChooser(ActionEvent event, String[] supportedFileTypes, boolean multiSelect) { + GlobalSettings settings = PlayPadPlugin.getInstance().getGlobalSettings(); + if (pad.getProject() != null && settings.isLiveMode() && settings.isLiveModeFile() && pad.getProject().getActivePlayers() > 0) { + return Collections.emptyList(); + } + + final FileChooser chooser = new FileChooser(); + final FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(Localization.getString(Strings.FILE_FILTER_MEDIA), supportedFileTypes); + chooser.getExtensionFilters().add(extensionFilter); + + // Last Folder + final Object openFolder = ApplicationUtils.getApplication().getUserDefaults().getData(DesktopPadViewController.OPEN_FOLDER); + if (openFolder != null) { + File folder = new File(openFolder.toString()); + if (folder.exists()) { + chooser.setInitialDirectory(folder); + } + } + + final List<File> selectedFiles; + final Window window = ((Node) event.getTarget()).getScene().getWindow(); + if (multiSelect) { + selectedFiles = chooser.showOpenMultipleDialog(window); + } else { + selectedFiles = Collections.singletonList(chooser.showOpenDialog(window)); + } + + if (selectedFiles != null && !selectedFiles.isEmpty()) { + ApplicationUtils.getApplication().getUserDefaults().setData(DesktopPadViewController.OPEN_FOLDER, selectedFiles.get(0).getParent()); + } + return selectedFiles; + } + + public void onNew(ActionEvent event, PadContentFactory.PadContentTypeChooser padContentTypeChooser) throws NoSuchComponentException { + final PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents(); + final List<File> files = showMediaOpenFileChooser(event, registry.getSupportedFileTypes(), false); + + if (files != null) { + final Path path = files.get(0).toPath(); + + final List<PadContentFactory> connects = registry.getPadContentConnectsForFile(path); + if (!connects.isEmpty()) { + if (connects.size() > 1) { // Multiple content types possible + padContentTypeChooser.showOptions(connects, padContent -> + { + if (padContent != null) { + setNewPadContent(path, padContent); + } + }); + } else { + PadContentFactory padContent = connects.iterator().next(); + setNewPadContent(path, padContent); + } + } + } + } + + private void setNewPadContent(Path path, PadContentFactory connect) { + if (pad.getContent() == null || !pad.getContent().getType().equals(connect.getType())) { + this.pad.setContentType(connect.getType()); + } + + if (pad.isPadVisible()) { + pad.getController().getView().showBusyView(true); + } + + pad.setPath(path); + } + +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java index 86347f6aa5f964cc26359dbbe7d49bbfdc102ad5..fff46f264a0632184ab597a851d5eba90fcf7b47 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadDragListener.java @@ -7,7 +7,10 @@ import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.content.PadContentFactory; import de.tobias.playpad.pad.content.PadContentRegistry; +import de.tobias.playpad.pad.content.Playlistable; +import de.tobias.playpad.pad.drag.ContentDragOption; import de.tobias.playpad.pad.drag.PadDragMode; +import de.tobias.playpad.pad.drag.PlaylistDragOption; import de.tobias.playpad.pad.view.IPadView; import de.tobias.playpad.profile.Profile; import de.tobias.playpad.project.Project; @@ -26,18 +29,21 @@ import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; -import java.util.Set; +import java.util.List; +import java.util.stream.Collectors; public class DesktopPadDragListener implements EventHandler<DragEvent> { - private static final String PADINDEX_DATATYPE = "de.tobias.playpad.padindex"; - private static final DataFormat dataFormat = new DataFormat(PADINDEX_DATATYPE); + private static final String PAD_INDEX_DATATYPE = "de.tobias.playpad.pad_index"; + private static final DataFormat dataFormat = new DataFormat(PAD_INDEX_DATATYPE); - private Pad currentPad; - private final Pane padView; // Node der PadView + private final Pad currentPad; + private final Pane padViewNode; // Node der PadView - private DesktopMainLayoutFactory connect; + private final DesktopMainLayoutFactory connect; private PadDragOptionView padHud; private FileDragOptionView fileHud; @@ -46,21 +52,21 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> { this.currentPad = currentPad; this.connect = connect; - this.padView = view.getRootNode(); + this.padViewNode = view.getRootNode(); } public void addListener() { - this.padView.setOnDragOver(this::dragOver); - this.padView.setOnDragExited(event -> dragExited()); - this.padView.setOnDragDropped(this::dragDropped); - this.padView.setOnDragDetected(this::dragDetacted); + this.padViewNode.setOnDragOver(this::dragOver); + this.padViewNode.setOnDragExited(event -> dragExited()); + this.padViewNode.setOnDragDropped(this::dragDropped); + this.padViewNode.setOnDragDetected(this::dragDetected); } void removeListener() { - this.padView.setOnDragOver(null); - this.padView.setOnDragExited(null); - this.padView.setOnDragDropped(null); - this.padView.setOnDragDetected(null); + this.padViewNode.setOnDragOver(null); + this.padViewNode.setOnDragExited(null); + this.padViewNode.setOnDragDropped(null); + this.padViewNode.setOnDragDetected(null); } @Override @@ -75,52 +81,67 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> { } private void dragOver(DragEvent event) { - if (Profile.currentProfile().getProfileSettings().isLocked()) { + if (Profile.currentProfile().getProfileSettings().isLocked() || checkLiveMode()) { return; } if (event.getGestureSource() != this && event.getDragboard().hasFiles()) { - File file = event.getDragboard().getFiles().get(0); - if (file.isFile()) { - // Check Live Mode - if (checkLiveMode()) { - return; - } + handleFileDropOver(event); + } else if (event.getDragboard().hasContent(dataFormat)) { + handlePadDragOver(event); + } + event.consume(); + } + + @SuppressWarnings("java:S1066") + private void handleFileDropOver(DragEvent event) { + final File file = event.getDragboard().getFiles().get(0); + if (file.isFile()) { - // Build In Filesupport - PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents(); - Set<PadContentFactory> connects = registry.getPadContentConnectsForFile(file.toPath()); + final List<Path> paths = event.getDragboard().getFiles().stream().map(File::toPath).collect(Collectors.toList()); - if (!connects.isEmpty()) { - if (fileHud == null) { - fileHud = new FileDragOptionView(padView); - } - fileHud.showDropOptions(connects); + // built-in file support + final PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents(); + final List<PadContentFactory> supportedContentTypes = registry.getPadContentConnectsForFiles(paths); - event.acceptTransferModes(TransferMode.LINK); - return; + if (currentPad.getContent() != null && currentPad.getContent().isPadLoading()) { + return; + } + + final List<ContentDragOption> contentDragOptions = new ArrayList<>(supportedContentTypes); + + if (currentPad.getContent() instanceof Playlistable) { + if (supportedContentTypes.stream().anyMatch(factory -> factory.getType().equals(currentPad.getContent().getType()))) { + contentDragOptions.add(new PlaylistDragOption()); } } - } - // Drag and Drop von Pads - if (event.getDragboard().hasContent(dataFormat)) { - PadIndex index = (PadIndex) event.getDragboard().getContent(dataFormat); - if (!currentPad.getPadIndex().equals(index)) { + if (!contentDragOptions.isEmpty()) { + if (fileHud == null) { + fileHud = new FileDragOptionView(padViewNode); + } + fileHud.showOptions(contentDragOptions); + + event.acceptTransferModes(TransferMode.LINK); + } + } + } - Collection<PadDragMode> connects = PlayPadPlugin.getRegistries().getDragModes().getComponents(); + private void handlePadDragOver(DragEvent event) { + PadIndex index = (PadIndex) event.getDragboard().getContent(dataFormat); + if (!currentPad.getPadIndex().equals(index)) { - if (!connects.isEmpty()) { - if (padHud == null) { - padHud = new PadDragOptionView(padView); - } - padHud.showDropOptions(connects); + Collection<PadDragMode> connects = PlayPadPlugin.getRegistries().getDragModes().getComponents(); - event.acceptTransferModes(TransferMode.MOVE); + if (!connects.isEmpty()) { + if (padHud == null) { + padHud = new PadDragOptionView(padViewNode); } + padHud.showDropOptions(connects); + + event.acceptTransferModes(TransferMode.MOVE); } } - event.consume(); } private void dragExited() { @@ -134,79 +155,83 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> { // Drag Content ist los gelassen am Ziel private void dragDropped(DragEvent event) { - Project project = PlayPadPlugin.getInstance().getCurrentProject(); + final Project project = PlayPadPlugin.getInstance().getCurrentProject(); - Dragboard db = event.getDragboard(); + final Dragboard dragboard = event.getDragboard(); boolean success = false; // File Handling - if (db.hasFiles()) { - File file = db.getFiles().get(0); - - PadContentFactory connect = fileHud.getSelectedConnect(); - if (connect != null) { - // stop pad if playing - if(currentPad.getContent() != null && currentPad.getStatus().equals(PadStatus.PLAY)) { - currentPad.getContent().stop(); - currentPad.stop(); - } + if (dragboard.hasFiles()) { + success = handleFileDragDropped(dragboard); + } - if (currentPad.getContent() == null || !currentPad.getContent().getType().equals(connect.getType())) { - currentPad.setContentType(connect.getType()); - } + // Pad DnD + if (dragboard.hasContent(dataFormat)) { + success = handlePadDragDropped(project, dragboard); + } + // Event Completion + event.setDropCompleted(success); + event.consume(); + } - if (currentPad.isPadVisible()) { - currentPad.getController().getView().showBusyView(true); - } + private boolean handleFileDragDropped(Dragboard dragboard) { + final ContentDragOption dragOption = fileHud.getSelectedConnect(); + if (dragOption != null) { + // stop pad if playing + if (currentPad.getContent() != null && currentPad.getStatus().equals(PadStatus.PLAY)) { + currentPad.getContent().stop(); + currentPad.stop(); + } - this.currentPad.setPath(file.toPath()); + dragOption.handleDrop(currentPad, dragboard.getFiles()); - if (currentPad.getController() != null) { - IPadView padView = currentPad.getController().getView(); - padView.setContentView(currentPad); - padView.addDefaultElements(currentPad); - } + if (currentPad.getController() != null) { + final IPadView padView = currentPad.getController().getView(); + padView.setContentView(currentPad); + padView.addDefaultElements(currentPad); } + + return true; } + return false; + } - // Pad DnD - if (db.hasContent(dataFormat)) { - Object data = db.getContent(dataFormat); - if (data instanceof PadIndex) { - PadIndex srcIndex = (PadIndex) data; - PadIndex newIndex = currentPad.getPadIndex(); // Lister ist auf Ziel Pad, daher ist der Index von currentPad - - // Drag handle - PadDragMode mode = padHud.getSelectedPadDragMode(); - success = mode.handle(srcIndex, newIndex, project); - padHud.hide(); - - // Update der Pad Views nach dem DnD - IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController(); - mainViewController.showPage(mainViewController.getPage()); - - if (project.getProjectReference().isSync()) { - CommandManager.execute(Commands.PAD_MOVE); - } + private boolean handlePadDragDropped(Project project, Dragboard dragboard) { + boolean success = false; + + Object data = dragboard.getContent(dataFormat); + if (data instanceof PadIndex) { + PadIndex srcIndex = (PadIndex) data; + PadIndex newIndex = currentPad.getPadIndex(); // Lister ist auf Ziel Pad, daher ist der Index von currentPad + + // Drag handle + PadDragMode mode = padHud.getSelectedPadDragMode(); + success = mode.handle(srcIndex, newIndex, project); + padHud.hide(); + + // Update der Pad Views nach dem DnD + IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController(); + mainViewController.showPage(mainViewController.getPage()); + + if (project.getProjectReference().isSync()) { + CommandManager.execute(Commands.PAD_MOVE); } } - // Event Completion - event.setDropCompleted(success); - event.consume(); + return success; } - private void dragDetacted(MouseEvent event) { + private void dragDetected(MouseEvent event) { if (connect.getEditMode() == DesktopEditMode.DRAG) { if (checkLiveMode()) { return; } - Dragboard dragboard = padView.startDragAndDrop(TransferMode.MOVE); + Dragboard dragboard = padViewNode.startDragAndDrop(TransferMode.MOVE); // Create Snapshot SnapshotParameters parameters = new SnapshotParameters(); parameters.setFill(Color.TRANSPARENT); - WritableImage snapshot = padView.snapshot(parameters, null); + WritableImage snapshot = padViewNode.snapshot(parameters, null); for (int x = 0; x < snapshot.getWidth(); x++) { for (int y = 0; y < snapshot.getHeight(); y++) { Color oldColor = snapshot.getPixelReader().getColor(x, y).darker().darker(); @@ -229,9 +254,7 @@ public class DesktopPadDragListener implements EventHandler<DragEvent> { private boolean checkLiveMode() { GlobalSettings globalSettings = PlayPadPlugin.getInstance().getGlobalSettings(); if (currentPad.getProject() != null) { - if (globalSettings.isLiveMode() && globalSettings.isLiveModeFile() && currentPad.getProject().getActivePlayers() > 0) { - return true; - } + return globalSettings.isLiveMode() && globalSettings.isLiveModeFile() && currentPad.getProject().getActivePlayers() > 0; } return false; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java index 6d0b659e2464756bf60529e5533697aa164c9611..e1489f3445343db9ef7b1b3a46be0e6030a8f690 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadView.java @@ -14,30 +14,37 @@ import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.content.PadContent; import de.tobias.playpad.pad.content.PadContentFactory; import de.tobias.playpad.pad.content.PadContentRegistry; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.pad.content.play.Pauseable; import de.tobias.playpad.pad.view.IPadContentView; import de.tobias.playpad.pad.view.IPadView; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.profile.Profile; import de.tobias.playpad.project.page.PadIndex; import de.tobias.playpad.registry.NoSuchComponentException; +import de.tobias.playpad.util.NodeWalker; import de.tobias.playpad.view.EmptyPadView; import de.tobias.playpad.view.PseudoClasses; +import de.tobias.playpad.view.pad.*; import javafx.beans.property.Property; import javafx.css.PseudoClass; import javafx.geometry.Pos; import javafx.scene.Node; +import javafx.scene.Parent; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; import javafx.scene.layout.*; import javafx.scene.paint.Color; +import static de.tobias.playpad.view.pad.PadStyleClasses.*; + public class DesktopPadView implements IPadView { private Label indexLabel; private Label loopLabel; private Label triggerLabel; + private Label playlistLabel; private Label errorLabel; private HBox infoBox; @@ -51,6 +58,7 @@ public class DesktopPadView implements IPadView { private ProgressBar playBar; private Button playButton; private Button pauseButton; + private Button nextButton; private Button stopButton; private Button newButton; private Button settingsButton; @@ -60,10 +68,10 @@ public class DesktopPadView implements IPadView { private VBox root; private BusyView busyView; - private VBox cueInContainer; private Label cueInLayer; - private transient DesktopPadViewController controller; // Reference to its controller + // Reference to its controller + private final transient DesktopPadViewController controller; public DesktopPadView(DesktopMainLayoutFactory connect) { controller = new DesktopPadViewController(this, connect); @@ -71,31 +79,25 @@ public class DesktopPadView implements IPadView { } private void setupView() { - superRoot = new StackPane(); - root = new VBox(); + superRoot = new PadStackPane(STYLE_CLASS_PAD, STYLE_CLASS_PAD_INDEX); + root = new PadVBox(STYLE_CLASS_PAD_BUTTON_ROOT); busyView = new BusyView(superRoot); - cueInLayer = new Label(); + cueInLayer = PadLabel.empty(STYLE_CLASS_PAD_CUE_IN, STYLE_CLASS_PAD_CUE_IN_INDEX); cueInLayer.prefHeightProperty().bind(root.heightProperty()); - cueInContainer = new VBox(cueInLayer); - - indexLabel = new Label(); - - loopLabel = new Label(); // Active über Visible - loopLabel.setGraphic(new FontIcon(FontAwesomeType.REPEAT)); - - triggerLabel = new Label(); - triggerLabel.setGraphic(new FontIcon(FontAwesomeType.EXTERNAL_LINK)); + VBox cueInContainer = new VBox(cueInLayer); - errorLabel = new Label(); - errorLabel.setGraphic(new FontIcon(FontAwesomeType.WARNING)); + indexLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX); + timeLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX); - timeLabel = new Label(); + loopLabel = new PadLabel(new FontIcon(FontAwesomeType.REPEAT)); + triggerLabel = new PadLabel(new FontIcon(FontAwesomeType.EXTERNAL_LINK)); + playlistLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX); + errorLabel = new PadLabel(new FontIcon(FontAwesomeType.WARNING)); - infoBox = new HBox(); // childern in addDefaultButton() - infoBox.setSpacing(5); + infoBox = new PadHBox(5); - preview = new HBox(); + preview = PadHBox.deepStyled(STYLE_CLASS_PAD_TITLE, STYLE_CLASS_PAD_TITLE_INDEX); HBox.setHgrow(preview, Priority.ALWAYS); VBox.setVgrow(preview, Priority.ALWAYS); @@ -103,25 +105,16 @@ public class DesktopPadView implements IPadView { timeLabel.setMaxWidth(Double.MAX_VALUE); timeLabel.setAlignment(Pos.CENTER_RIGHT); - playBar = new ProgressBar(0); + playBar = new PadProgressBar(0, STYLE_CLASS_PAD_PLAYBAR, STYLE_CLASS_PAD_PLAYBAR_INDEX); playBar.prefWidthProperty().bind(root.widthProperty()); // Buttons - playButton = new Button("", new FontIcon(FontAwesomeType.PLAY)); - playButton.setFocusTraversable(false); - playButton.setOnAction(controller); - pauseButton = new Button("", new FontIcon(FontAwesomeType.PAUSE)); - pauseButton.setFocusTraversable(false); - pauseButton.setOnAction(controller); - stopButton = new Button("", new FontIcon(FontAwesomeType.STOP)); - stopButton.setFocusTraversable(false); - stopButton.setOnAction(controller); - newButton = new Button("", new FontIcon(FontAwesomeType.FOLDER_OPEN)); - newButton.setFocusTraversable(false); - newButton.setOnAction(controller); - settingsButton = new Button("", new FontIcon(FontAwesomeType.GEAR)); - settingsButton.setFocusTraversable(false); - settingsButton.setOnAction(controller); + playButton = new PadButton(new FontIcon(FontAwesomeType.PLAY), controller); + pauseButton = new PadButton(new FontIcon(FontAwesomeType.PAUSE), controller); + nextButton = new PadButton(new FontIcon(FontAwesomeType.STEP_FORWARD), controller); + stopButton = new PadButton(new FontIcon(FontAwesomeType.STOP), controller); + newButton = new PadButton(new FontIcon(FontAwesomeType.FOLDER_OPEN), controller); + settingsButton = new PadButton(new FontIcon(FontAwesomeType.GEAR), controller); // Not Found Label notFoundLabel = new FontIcon(FontAwesomeType.EXCLAMATION_TRIANGLE); @@ -129,11 +122,10 @@ public class DesktopPadView implements IPadView { notFoundLabel.setOpacity(0.75); notFoundLabel.setSize(80); notFoundLabel.setMouseTransparent(true); - notFoundLabel.setVisible(false); // Button HBOX - buttonBox = new HBox(); // childern in addDefaultButton() + buttonBox = new PadHBox(STYLE_CLASS_PAD_BUTTON_BOX); root.getChildren().addAll(infoBox, preview, playBar, buttonBox); superRoot.getChildren().addAll(cueInContainer, root, notFoundLabel); @@ -160,13 +152,11 @@ public class DesktopPadView implements IPadView { PadContentFactory connect = registry.getFactory(content.getType()); previewContent = connect.getPadContentPreview(pad, preview); - Node node = previewContent.getNode(); - - node.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title"); + Parent node = previewContent.getNode(); - // Copy Pseudoclasses + // Copy Pseudo classes for (PseudoClass pseudoClass : superRoot.getPseudoClassStates()) { - node.pseudoClassStateChanged(pseudoClass, true); + NodeWalker.getAllNodes(node).forEach(element -> element.pseudoClassStateChanged(pseudoClass, true)); } preview.getChildren().setAll(node); @@ -177,16 +167,11 @@ public class DesktopPadView implements IPadView { } } EmptyPadView view = new EmptyPadView(preview); - if (pad != null) { - view.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title"); - } else { - view.getStyleClass().addAll("pad-title"); - } preview.getChildren().setAll(view); } @Override - public IPadViewController getViewController() { + public AbstractPadViewController getViewController() { return controller; } @@ -209,31 +194,10 @@ public class DesktopPadView implements IPadView { this.indexLabel.setText(text); } - ProgressBar getPlayBar() { - return playBar; - } - @Override public void pseudoClassState(PseudoClass pseudoClass, boolean active) { - superRoot.pseudoClassStateChanged(pseudoClass, active); - cueInLayer.pseudoClassStateChanged(pseudoClass, active); - indexLabel.pseudoClassStateChanged(pseudoClass, active); - timeLabel.pseudoClassStateChanged(pseudoClass, active); - loopLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active); - triggerLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active); - errorLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active); - - if (preview != null) { - preview.getChildren().forEach(i -> i.pseudoClassStateChanged(pseudoClass, active)); - } - - playBar.pseudoClassStateChanged(pseudoClass, active); - - playButton.getGraphic().pseudoClassStateChanged(pseudoClass, active); - pauseButton.getGraphic().pseudoClassStateChanged(pseudoClass, active); - stopButton.getGraphic().pseudoClassStateChanged(pseudoClass, active); - newButton.getGraphic().pseudoClassStateChanged(pseudoClass, active); - settingsButton.getGraphic().pseudoClassStateChanged(pseudoClass, active); + NodeWalker.getAllNodes(getRootNode()) + .forEach(node -> node.pseudoClassStateChanged(pseudoClass, active)); } @Override @@ -254,6 +218,10 @@ public class DesktopPadView implements IPadView { return pauseButton; } + Button getNextButton() { + return nextButton; + } + Button getStopButton() { return stopButton; } @@ -278,8 +246,7 @@ public class DesktopPadView implements IPadView { triggerLabel.setVisible(hasTriggerItems); } - void - setTime(String time) { + void setTime(String time) { if (time == null) { timeLabel.setText(""); } else { @@ -293,18 +260,23 @@ public class DesktopPadView implements IPadView { if (pad.getContent() != null) { if (pad.getContent() instanceof Pauseable) { if (pad.getStatus() == PadStatus.PLAY) { - buttonBox.getChildren().setAll(pauseButton, stopButton, newButton, settingsButton); + if (pad.getContent() instanceof Playlistable) { + buttonBox.getChildren().setAll(pauseButton, nextButton, stopButton, settingsButton); + } else { + buttonBox.getChildren().setAll(pauseButton, stopButton, settingsButton); + } } else { - buttonBox.getChildren().setAll(playButton, stopButton, newButton, settingsButton); + buttonBox.getChildren().setAll(playButton, stopButton, settingsButton); } } else { - buttonBox.getChildren().setAll(playButton, stopButton, newButton, settingsButton); + buttonBox.getChildren().setAll(playButton, stopButton, settingsButton); } } else { buttonBox.getChildren().setAll(newButton, settingsButton); } + applyStyleClasses(pad.getPadIndex()); } - infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, errorLabel, timeLabel); + infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, playlistLabel, errorLabel, timeLabel); // Buttons unten Full Width buttonBox.prefWidthProperty().bind(superRoot.widthProperty()); @@ -325,64 +297,18 @@ public class DesktopPadView implements IPadView { @Override public void applyStyleClasses(PadIndex index) { - superRoot.getStyleClass().addAll("pad", "pad" + index); - cueInLayer.getStyleClass().addAll("pad-cue-in", "pad" + index + "-cue-in"); - - indexLabel.getStyleClass().addAll("pad-index", "pad" + index + "-index", "pad-info", "pad" + index + "-info"); - timeLabel.getStyleClass().addAll("pad-time", "pad" + index + "-time", "pad-info", "pad" + index + "-info"); - loopLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - triggerLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - errorLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - - preview.getChildren().forEach(i -> i.getStyleClass().addAll("pad-title", "pad" + index + "-title")); - - playBar.getStyleClass().addAll("pad-playbar", "pad" + index + "-playbar"); - - playButton.getStyleClass().addAll("pad-button", "pad" + index + "-button"); - pauseButton.getStyleClass().addAll("pad-button", "pad" + index + "-button"); - stopButton.getStyleClass().addAll("pad-button", "pad" + index + "-button"); - newButton.getStyleClass().addAll("pad-button", "pad" + index + "-button"); - settingsButton.getStyleClass().addAll("pad-button", "pad" + index + "-button"); - - playButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - pauseButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - stopButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - newButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - settingsButton.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - - buttonBox.getStyleClass().add("pad-button-box"); - root.getStyleClass().add("pad-root"); + NodeWalker.getAllNodes(getRootNode()) + .stream() + .filter(node -> node instanceof PadIndexable) + .forEach(node -> ((PadIndexable) node).setIndex(index)); } @Override public void removeStyleClasses() { - superRoot.getStyleClass().removeIf(c -> c.startsWith("pad")); - cueInLayer.getStyleClass().removeIf(c -> c.startsWith("pad")); - - indexLabel.getStyleClass().removeIf(c -> c.startsWith("pad")); - timeLabel.getStyleClass().removeIf(c -> c.startsWith("pad")); - loopLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - triggerLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - errorLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - - preview.getChildren().forEach(i -> i.getStyleClass().removeIf(c -> c.startsWith("pad"))); - - playBar.getStyleClass().removeIf(c -> c.startsWith("pad")); - - playButton.getStyleClass().removeIf(c -> c.startsWith("pad")); - pauseButton.getStyleClass().removeIf(c -> c.startsWith("pad")); - stopButton.getStyleClass().removeIf(c -> c.startsWith("pad")); - newButton.getStyleClass().removeIf(c -> c.startsWith("pad")); - settingsButton.getStyleClass().removeIf(c -> c.startsWith("pad")); - - playButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - pauseButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - stopButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - newButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - settingsButton.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - - buttonBox.getStyleClass().remove("pad-button-box"); - root.getStyleClass().remove("pad-root"); + NodeWalker.getAllNodes(getRootNode()) + .stream() + .filter(node -> node instanceof PadIndexable) + .forEach(node -> ((PadIndexable) node).setIndex(null)); } @Override @@ -406,6 +332,10 @@ public class DesktopPadView implements IPadView { setContentView(null); } + public Label getPlaylistLabel() { + return playlistLabel; + } + @Override public void setPlaybarVisible(boolean visible) { playBar.setVisible(visible); diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java index 21700d33e55e8d33b0dd52bc5e10075c6f48b331..fd9acc77f4555699721cdea533a759b8a673a3fd 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/pad/DesktopPadViewController.java @@ -1,22 +1,19 @@ package de.tobias.playpad.layout.desktop.pad; import de.thecodelabs.logger.Logger; -import de.thecodelabs.utils.application.ApplicationUtils; import de.thecodelabs.utils.ui.NVCStage; -import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.PlayPadPlugin; -import de.tobias.playpad.Strings; import de.tobias.playpad.layout.desktop.DesktopEditMode; import de.tobias.playpad.layout.desktop.DesktopMainLayoutFactory; +import de.tobias.playpad.layout.desktop.listener.PadNewContentListener; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.TimeMode; -import de.tobias.playpad.pad.content.PadContentFactory; -import de.tobias.playpad.pad.content.PadContentRegistry; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.pad.content.play.Durationable; import de.tobias.playpad.pad.listener.*; import de.tobias.playpad.pad.view.IPadView; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.profile.Profile; import de.tobias.playpad.profile.ProfileSettings; import de.tobias.playpad.registry.NoSuchComponentException; @@ -27,29 +24,21 @@ import de.tobias.playpad.viewcontroller.option.pad.PadSettingsViewController; import javafx.beans.value.ChangeListener; import javafx.event.ActionEvent; import javafx.event.EventHandler; -import javafx.scene.Node; -import javafx.stage.FileChooser; -import javafx.stage.FileChooser.ExtensionFilter; -import javafx.stage.Stage; import javafx.util.Duration; -import java.io.File; -import java.nio.file.Path; -import java.util.Set; - -public class DesktopPadViewController implements IPadViewController, EventHandler<ActionEvent> { +public class DesktopPadViewController extends AbstractPadViewController implements EventHandler<ActionEvent> { public static final String OPEN_FOLDER = "openFolder"; private static final String DURATION_FORMAT = "%d:%02d"; - private DesktopPadView padView; + private final DesktopPadView padView; private Pad pad; - private PadLockedListener padLockedListener; - private PadStatusListener padStatusListener; - private PadContentListener padContentListener; - private PadDurationListener padDurationListener; - private IPadPositionListener padPositionListener; + private final PadLockedListener padLockedListener; + private final PadStatusListener padStatusListener; + private final PadContentListener padContentListener; + private final PadDurationListener padDurationListener; + private final IPadPositionListener padPositionListener; private DesktopPadDragListener padDragListener; @@ -95,6 +84,8 @@ public class DesktopPadViewController implements IPadViewController, EventHandle padView.loopLabelVisibleProperty().bind(pad.getPadSettings().loopProperty()); padView.setTriggerLabelActive(pad.getPadSettings().hasTriggerItems()); + updatePlaylistLabelBinding(pad); + // Update Listener padContentListener.setPad(pad); padPositionListener.setPad(pad); @@ -103,9 +94,9 @@ public class DesktopPadViewController implements IPadViewController, EventHandle pad.contentProperty().addListener(padContentListener); pad.statusProperty().addListener(padStatusListener); - // Inital Listener call with new data + // Initial Listener call with new data padContentListener.changed(null, null, pad.getContent()); // Add Duration listener - padStatusListener.changed(null, null, pad.getStatus()); + padStatusListener.changed(null, null, pad.getStatus()); // Show correct pseudo classes ... // Add Drag and Drop Listener padDragListener = new DesktopPadDragListener(pad, padView, connect); @@ -128,6 +119,9 @@ public class DesktopPadViewController implements IPadViewController, EventHandle padView.setTriggerLabelActive(false); padView.loopLabelVisibleProperty().unbind(); + padView.getPlaylistLabel().textProperty().unbind(); + padView.getPlaylistLabel().setText(""); + // Remove Bindings & Listener pad.contentProperty().removeListener(padContentListener); pad.statusProperty().removeListener(padStatusListener); @@ -163,6 +157,8 @@ public class DesktopPadViewController implements IPadViewController, EventHandle onPlay(); } else if (event.getSource() == padView.getPauseButton()) { onPause(); + } else if (event.getSource() == padView.getNextButton()) { + onNext(); } else if (event.getSource() == padView.getStopButton()) { onStop(); } else if (event.getSource() == padView.getNewButton()) { @@ -190,72 +186,21 @@ public class DesktopPadViewController implements IPadViewController, EventHandle } } - private void onStop() { - if (pad.getContent() != null) { - pad.setStatus(PadStatus.STOP); + private void onNext() { + if (pad.getContent() instanceof Playlistable) { + ((Playlistable) pad.getContent()).next(); } } - private void onNew(ActionEvent event) throws NoSuchComponentException { - GlobalSettings settings = PlayPadPlugin.getInstance().getGlobalSettings(); - if (pad.getProject() != null) { - if (settings.isLiveMode() && settings.isLiveModeFile() && pad.getProject().getActivePlayers() > 0) { - return; - } - } - - FileChooser chooser = new FileChooser(); - PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents(); - - // File Extension - ExtensionFilter extensionFilter = new ExtensionFilter(Localization.getString(Strings.FILE_FILTER_MEDIA), - registry.getSupportedFileTypes()); - chooser.getExtensionFilters().add(extensionFilter); - - // Last Folder - Object openFolder = ApplicationUtils.getApplication().getUserDefaults().getData(OPEN_FOLDER); - if (openFolder != null) { - File folder = new File(openFolder.toString()); - if (folder.exists()) { - chooser.setInitialDirectory(folder); - } - } - - File file = chooser.showOpenDialog(((Node) event.getTarget()).getScene().getWindow()); - if (file != null) { - Path path = file.toPath(); - - Set<PadContentFactory> connects = registry.getPadContentConnectsForFile(file.toPath()); - if (!connects.isEmpty()) { - if (connects.size() > 1) { // Multiple content types possible - FileDragOptionView hud = new FileDragOptionView(padView.getRootNode()); - hud.showDropOptions(connects, connect -> - { - if (connect != null) { - setNewPadContent(path, connect); - hud.hide(); - } - }); - } else { - PadContentFactory connect = connects.iterator().next(); - setNewPadContent(path, connect); - } - } - - ApplicationUtils.getApplication().getUserDefaults().setData(OPEN_FOLDER, path.getParent().toString()); + private void onStop() { + if (pad.getContent() != null) { + pad.setStatus(PadStatus.STOP); } } - private void setNewPadContent(Path path, PadContentFactory connect) { - if (pad.getContent() == null || !pad.getContent().getType().equals(connect.getType())) { - this.pad.setContentType(connect.getType()); - } - - if (pad.isPadVisible()) { - pad.getController().getView().showBusyView(true); - } - - pad.setPath(path); + public void onNew(ActionEvent event) throws NoSuchComponentException { + final PadNewContentListener listener = new PadNewContentListener(pad); + listener.onNew(event, new FileDragOptionView(padView.getRootNode())); } private void onSettings() { @@ -263,15 +208,11 @@ public class DesktopPadViewController implements IPadViewController, EventHandle IMainViewController mvc = PlayPadPlugin.getInstance().getMainViewController(); if (mvc != null) { - if (pad.getProject() != null) { - if (settings.isLiveMode() && settings.isLiveModeSettings() && pad.getProject().getActivePlayers() > 0) { - return; - } + if (pad.getProject() != null && settings.isLiveMode() && settings.isLiveModeSettings() && pad.getProject().getActivePlayers() > 0) { + return; } - Stage owner = mvc.getStage(); - - PadSettingsViewController padSettingsViewController = new PadSettingsViewController(pad, owner); + PadSettingsViewController padSettingsViewController = new PadSettingsViewController(pad, mvc); padSettingsViewController.getStageContainer().ifPresent(nvcStage -> nvcStage.addCloseHook(() -> { if (padView != null && pad != null) padView.setTriggerLabelActive(pad.getPadSettings().hasTriggerItems()); @@ -394,7 +335,7 @@ public class DesktopPadViewController implements IPadViewController, EventHandle padView.getSettingsButton().setDisable(true); } - // Alles Desktivieren, wenn nicht Play Mode + // Alles Deaktivieren, wenn nicht Play Mode if (connect.getEditMode() != DesktopEditMode.PLAY) { padView.getPlayButton().setDisable(true); padView.getPauseButton().setDisable(true); diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java index c094f0df8c0058df0096424b0d132f1bfdd4f122..3c220b8ba255b641ea8355d2cc818418e90e1a5f 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadView.java @@ -14,12 +14,14 @@ import de.tobias.playpad.pad.content.PadContent; import de.tobias.playpad.pad.content.PadContentFactory; import de.tobias.playpad.pad.view.IPadContentView; import de.tobias.playpad.pad.view.IPadView; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.profile.Profile; import de.tobias.playpad.project.page.PadIndex; import de.tobias.playpad.registry.NoSuchComponentException; +import de.tobias.playpad.util.NodeWalker; import de.tobias.playpad.view.EmptyPadView; import de.tobias.playpad.view.PseudoClasses; +import de.tobias.playpad.view.pad.*; import javafx.beans.property.Property; import javafx.css.PseudoClass; import javafx.geometry.Pos; @@ -29,11 +31,14 @@ import javafx.scene.control.ProgressBar; import javafx.scene.layout.*; import javafx.scene.paint.Color; +import static de.tobias.playpad.view.pad.PadStyleClasses.*; + public class TouchPadView implements IPadView { private Label indexLabel; private Label loopLabel; private Label triggerLabel; + private Label playlistLabel; private Label errorLabel; private HBox infoBox; @@ -50,10 +55,9 @@ public class TouchPadView implements IPadView { private VBox root; private BusyView busyView; - private VBox cueInContainer; private Label cueInLayer; - private transient TouchPadViewController controller; // Reference to its controller + private final transient TouchPadViewController controller; // Reference to its controller public TouchPadView() { controller = new TouchPadViewController(this); @@ -61,31 +65,25 @@ public class TouchPadView implements IPadView { } private void setupView() { - superRoot = new StackPane(); - root = new VBox(); + superRoot = new PadStackPane(STYLE_CLASS_PAD, STYLE_CLASS_PAD_INDEX); + root = new PadVBox(STYLE_CLASS_PAD_BUTTON_ROOT); busyView = new BusyView(superRoot); - cueInLayer = new Label(); + cueInLayer = PadLabel.empty(STYLE_CLASS_PAD_CUE_IN, STYLE_CLASS_PAD_CUE_IN_INDEX); cueInLayer.prefHeightProperty().bind(root.heightProperty()); - cueInContainer = new VBox(cueInLayer); - - indexLabel = new Label(); - - loopLabel = new Label(); // Active über Visible - loopLabel.setGraphic(new FontIcon(FontAwesomeType.REPEAT)); + VBox cueInContainer = new VBox(cueInLayer); - triggerLabel = new Label(); - triggerLabel.setGraphic(new FontIcon(FontAwesomeType.EXTERNAL_LINK)); + indexLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX); + timeLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX); - errorLabel = new Label(); - errorLabel.setGraphic(new FontIcon(FontAwesomeType.WARNING)); + loopLabel = new PadLabel(new FontIcon(FontAwesomeType.REPEAT)); + triggerLabel = new PadLabel(new FontIcon(FontAwesomeType.EXTERNAL_LINK)); + playlistLabel = PadLabel.empty(STYLE_CLASS_PAD_INFO, STYLE_CLASS_PAD_INFO_INDEX); + errorLabel = new PadLabel(new FontIcon(FontAwesomeType.WARNING)); - timeLabel = new Label(); + infoBox = new PadHBox(5); - infoBox = new HBox(); // childern in addDefaultButton() - infoBox.setSpacing(5); - - preview = new HBox(); + preview = PadHBox.deepStyled(STYLE_CLASS_PAD_TITLE, STYLE_CLASS_PAD_TITLE_INDEX); HBox.setHgrow(preview, Priority.ALWAYS); VBox.setVgrow(preview, Priority.ALWAYS); @@ -93,16 +91,15 @@ public class TouchPadView implements IPadView { timeLabel.setMaxWidth(Double.MAX_VALUE); timeLabel.setAlignment(Pos.CENTER_RIGHT); - playBar = new ProgressBar(0); + playBar = new PadProgressBar(0, STYLE_CLASS_PAD_PLAYBAR, STYLE_CLASS_PAD_PLAYBAR_INDEX); playBar.prefWidthProperty().bind(root.widthProperty()); // Not Found Label notFoundLabel = new FontIcon(FontAwesomeType.EXCLAMATION_TRIANGLE); - notFoundLabel.getStyleClass().add("pad-notfound"); + notFoundLabel.getStyleClass().clear(); notFoundLabel.setOpacity(0.5); notFoundLabel.setSize(50); notFoundLabel.setMouseTransparent(true); - notFoundLabel.setVisible(false); root.getChildren().addAll(infoBox, preview, playBar); @@ -135,8 +132,6 @@ public class TouchPadView implements IPadView { previewContent = connect.getPadContentPreview(pad, preview); Node node = previewContent.getNode(); - node.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title"); - // Copy Pseudoclasses for (PseudoClass pseudoClass : superRoot.getPseudoClassStates()) { node.pseudoClassStateChanged(pseudoClass, true); @@ -150,16 +145,11 @@ public class TouchPadView implements IPadView { } } EmptyPadView view = new EmptyPadView(preview); - if (pad != null) { - view.getStyleClass().addAll("pad-title", "pad" + pad.getPadIndex() + "-title"); - } else { - view.getStyleClass().addAll("pad-title"); - } preview.getChildren().setAll(view); } @Override - public IPadViewController getViewController() { + public AbstractPadViewController getViewController() { return controller; } @@ -188,19 +178,8 @@ public class TouchPadView implements IPadView { @Override public void pseudoClassState(PseudoClass pseudoClass, boolean active) { - superRoot.pseudoClassStateChanged(pseudoClass, active); - cueInLayer.pseudoClassStateChanged(pseudoClass, active); - indexLabel.pseudoClassStateChanged(pseudoClass, active); - timeLabel.pseudoClassStateChanged(pseudoClass, active); - loopLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active); - triggerLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active); - errorLabel.getGraphic().pseudoClassStateChanged(pseudoClass, active); - - if (preview != null) { - preview.getChildren().forEach(i -> i.pseudoClassStateChanged(pseudoClass, active)); - } - - playBar.pseudoClassStateChanged(pseudoClass, active); + NodeWalker.getAllNodes(getRootNode()) + .forEach(node -> node.pseudoClassStateChanged(pseudoClass, active)); } @Override @@ -235,7 +214,7 @@ public class TouchPadView implements IPadView { @Override public void addDefaultElements(Pad pad) { - infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, errorLabel, timeLabel); + infoBox.getChildren().setAll(indexLabel, loopLabel, triggerLabel, playlistLabel, errorLabel, timeLabel); // alle Labels in der InfoBox sollen die gleiche Höhe haben, damit die Icons auf gleicher höhe sind for (Node child : infoBox.getChildren()) { @@ -247,38 +226,18 @@ public class TouchPadView implements IPadView { @Override public void applyStyleClasses(PadIndex index) { - superRoot.getStyleClass().addAll("pad", "pad" + index); - cueInLayer.getStyleClass().addAll("pad-cue-in", "pad" + index + "-cue-in"); - - indexLabel.getStyleClass().addAll("pad-index", "pad" + index + "-index", "pad-info", "pad" + index + "-info"); - timeLabel.getStyleClass().addAll("pad-time", "pad" + index + "-time", "pad-info", "pad" + index + "-info"); - loopLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - triggerLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - errorLabel.getGraphic().getStyleClass().addAll("pad-icon", "pad" + index + "-icon"); - - preview.getChildren().forEach(i -> i.getStyleClass().addAll("pad-title", "pad" + index + "-title")); - - playBar.getStyleClass().addAll("pad-playbar", "pad" + index + "-playbar"); - - root.getStyleClass().add("pad-root"); + NodeWalker.getAllNodes(getRootNode()) + .stream() + .filter(node -> node instanceof PadIndexable) + .forEach(node -> ((PadIndexable) node).setIndex(index)); } @Override public void removeStyleClasses() { - superRoot.getStyleClass().removeIf(c -> c.startsWith("pad")); - cueInLayer.getStyleClass().removeIf(c -> c.startsWith("pad")); - - indexLabel.getStyleClass().removeIf(c -> c.startsWith("pad")); - timeLabel.getStyleClass().removeIf(c -> c.startsWith("pad")); - loopLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - triggerLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - errorLabel.getGraphic().getStyleClass().removeIf(c -> c.startsWith("pad")); - - preview.getChildren().forEach(i -> i.getStyleClass().removeIf(c -> c.startsWith("pad"))); - - playBar.getStyleClass().removeIf(c -> c.startsWith("pad")); - - root.getStyleClass().remove("pad-root"); + NodeWalker.getAllNodes(getRootNode()) + .stream() + .filter(node -> node instanceof PadIndexable) + .forEach(node -> ((PadIndexable) node).setIndex(null)); } @Override @@ -301,6 +260,10 @@ public class TouchPadView implements IPadView { setContentView(null); } + public Label getPlaylistLabel() { + return playlistLabel; + } + @Override public void setPlaybarVisible(boolean visible) { playBar.setVisible(visible); diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java index d6a75430cb0063cd1191e25e9a2499c2f7080f92..c43b9679075c400a0e949b80e2b9ab64e28d4f50 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/touch/pad/TouchPadViewController.java @@ -7,7 +7,7 @@ import de.tobias.playpad.pad.TimeMode; import de.tobias.playpad.pad.content.play.Durationable; import de.tobias.playpad.pad.listener.*; import de.tobias.playpad.pad.view.IPadView; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.profile.Profile; import de.tobias.playpad.profile.ProfileSettings; import javafx.beans.value.ChangeListener; @@ -18,7 +18,7 @@ import javafx.scene.input.MouseEvent; import javafx.scene.input.TouchEvent; import javafx.util.Duration; -public class TouchPadViewController implements IPadViewController, EventHandler<Event> { +public class TouchPadViewController extends AbstractPadViewController implements EventHandler<Event> { protected static final String CURRENT_PAGE_BUTTON = "current-page-button"; private static final String DURATION_FORMAT = "%d:%02d"; @@ -70,11 +70,13 @@ public class TouchPadViewController implements IPadViewController, EventHandler< padView.loopLabelVisibleProperty().bind(pad.getPadSettings().loopProperty()); padView.setTriggerLabelActive(pad.getPadSettings().hasTriggerItems()); + updatePlaylistLabelBinding(pad); + // Update Listener padContentListener.setPad(pad); padPositionListener.setPad(pad); - // Pad Content Chnage + // Pad Content Change pad.contentProperty().addListener(padContentListener); // Pad Status Change pad.statusProperty().addListener(padStatusListener); @@ -98,6 +100,9 @@ public class TouchPadViewController implements IPadViewController, EventHandler< padView.clearPreviewContent(); padView.clearTime(); + padView.getPlaylistLabel().textProperty().unbind(); + padView.getPlaylistLabel().setText(""); + padView.setTriggerLabelActive(false); padView.loopLabelVisibleProperty().unbind(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java index 426d058b27de8b181450cc7727dbf0e3c7a0335d..b54079b8e799e072c95b4bbfec191f6a56bdc233 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java @@ -7,9 +7,9 @@ import de.tobias.playpad.audio.AudioRegistry; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.content.play.*; -import de.tobias.playpad.pad.fade.Fade; -import de.tobias.playpad.pad.fade.FadeDelegate; +import de.tobias.playpad.pad.fade.FadeControllerDelegate; import de.tobias.playpad.pad.fade.Fadeable; +import de.tobias.playpad.pad.fade.LogarithmicFadeController; import de.tobias.playpad.pad.mediapath.MediaPath; import de.tobias.playpad.volume.VolumeManager; import javafx.application.Platform; @@ -24,7 +24,7 @@ import java.nio.file.Files; import java.nio.file.Path; public class AudioContent extends PadContent implements Pauseable, Durationable, Fadeable, - Equalizeable, FadeDelegate, Seekable, SpeedAdjustable { + Equalizeable, FadeControllerDelegate, Seekable, SpeedAdjustable { private final String type; @@ -33,15 +33,15 @@ public class AudioContent extends PadContent implements Pauseable, Durationable, private ObjectProperty<Duration> durationProperty = new SimpleObjectProperty<>(); private ObjectProperty<Duration> positionProperty = new SimpleObjectProperty<>(); - private ChangeListener<Number> volumeListener; - private ChangeListener<Number> rateListener; + private final ChangeListener<Number> volumeListener; + private final ChangeListener<Number> rateListener; - private Fade fade; + private final LogarithmicFadeController fade; AudioContent(String type, Pad pad) { super(pad); this.type = type; - fade = new Fade(this); + fade = new LogarithmicFadeController(this); // Pad Volume Listener volumeListener = (a, oldValue, newValue) -> updateVolume(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java index d60a59d949a82adbb94f117600f4d9e6fd95da51..8e5f4339e3e2107bab28ee4ba9c591fcabe1c138 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioPadContentFactory.java @@ -1,16 +1,11 @@ package de.tobias.playpad.pad.content; import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.preview.PadTextPreview; import de.tobias.playpad.pad.view.IPadContentView; import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; import de.tobias.playpad.viewcontroller.option.profile.AudioTabViewController; -import javafx.geometry.Pos; -import javafx.scene.Node; -import javafx.scene.control.Label; import javafx.scene.layout.Pane; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import javafx.scene.text.TextAlignment; public class AudioPadContentFactory extends PadContentFactory { @@ -33,7 +28,7 @@ public class AudioPadContentFactory extends PadContentFactory { @Override public IPadContentView getPadContentPreview(Pad pad, Pane parentNode) { if (pad.getContent() != null) { - return new AudioContentView(pad, parentNode); + return new PadTextPreview(pad, parentNode); } else { return null; } @@ -43,32 +38,4 @@ public class AudioPadContentFactory extends PadContentFactory { public ProfileSettingsTabViewController getSettingsTabViewController(boolean activePlayer) { return new AudioTabViewController(activePlayer); } - - private static class AudioContentView implements IPadContentView { - - private Label nameLabel; - - AudioContentView(Pad pad, Pane parentNode) { - nameLabel = new Label(); - nameLabel.textProperty().bind(pad.nameProperty()); - - nameLabel.setWrapText(true); - nameLabel.setAlignment(Pos.CENTER); - nameLabel.setTextAlignment(TextAlignment.CENTER); - - nameLabel.prefWidthProperty().bind(parentNode.widthProperty()); - nameLabel.setMaxHeight(Double.MAX_VALUE); - VBox.setVgrow(nameLabel, Priority.ALWAYS); - } - - @Override - public Node getNode() { - return nameLabel; - } - - @Override - public void deInit() { - nameLabel.textProperty().unbind(); - } - } } diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/drag/PlaylistDragOption.java b/PlayWall/src/main/java/de/tobias/playpad/pad/drag/PlaylistDragOption.java new file mode 100644 index 0000000000000000000000000000000000000000..69e86ec2c6f8c2b9c437daffec996dc9aea8213a --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/drag/PlaylistDragOption.java @@ -0,0 +1,40 @@ +package de.tobias.playpad.pad.drag; + +import de.thecodelabs.utils.ui.icon.FontAwesomeType; +import de.thecodelabs.utils.ui.icon.FontIcon; +import de.thecodelabs.utils.util.Localization; +import de.tobias.playpad.pad.Pad; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.scene.Node; + +import java.io.File; +import java.util.List; + +public class PlaylistDragOption implements ContentDragOption { + + private final StringProperty displayProperty = new SimpleStringProperty(Localization.getString("DndMode.Playlist")); + + @Override + public void handleDrop(Pad currentPad, List<File> files) { + if (currentPad.isPadVisible()) { + currentPad.getController().getView().showBusyView(true); + } + + for (File file : files) { + currentPad.addPath(file.toPath()); + } + } + + @Override + public StringProperty displayProperty() { + return displayProperty; + } + + @Override + public Node getGraphics() { + final FontIcon fontIcon = new FontIcon(FontAwesomeType.PLUS_CIRCLE); + fontIcon.setSize(30); + return fontIcon; + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java index 0b88a71ca642f337b7c892cf68bc04d3a2efc9ab..20c58f70592345eadb08fc634bcf34a7824951ec 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadContentListener.java @@ -3,16 +3,16 @@ package de.tobias.playpad.pad.listener; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.content.PadContent; import de.tobias.playpad.pad.content.play.Durationable; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; public class PadContentListener implements ChangeListener<PadContent> { private Pad pad; - private IPadViewController controller; + private final AbstractPadViewController controller; - public PadContentListener(IPadViewController controller) { + public PadContentListener(AbstractPadViewController controller) { this.controller = controller; } @@ -49,5 +49,7 @@ public class PadContentListener implements ChangeListener<PadContent> { } else { controller.getView().setPlaybarVisible(false); } + + controller.updatePlaylistLabelBinding(pad); } } diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java index ce208522f99ec464cbe6996109ad0a4b3c9210d5..a364fed1a5f5f6996c4885374d1b8acd70faa936 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadDurationListener.java @@ -1,15 +1,15 @@ package de.tobias.playpad.pad.listener; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.util.Duration; public class PadDurationListener implements ChangeListener<Duration> { - private IPadViewController controller; + private AbstractPadViewController controller; - public PadDurationListener(IPadViewController controller) { + public PadDurationListener(AbstractPadViewController controller) { this.controller = controller; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java index 702951b06dab11e634e5c4aec827a06c98638f4e..e94995dda657050904571c0d88dec486b4d62dfa 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadLockedListener.java @@ -1,14 +1,14 @@ package de.tobias.playpad.pad.listener; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; public class PadLockedListener implements ChangeListener<Boolean> { - private IPadViewController controller; + private AbstractPadViewController controller; - public PadLockedListener(IPadViewController controller) { + public PadLockedListener(AbstractPadViewController controller) { this.controller = controller; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java index 579fe5a9dfb6fbac7a207b2f67b09cfce5c74800..5326b5f914229d7a4e1b9499bb44c01234d00ecf 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadPositionListener.java @@ -13,7 +13,7 @@ import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.content.PadContent; import de.tobias.playpad.pad.content.play.Durationable; import de.tobias.playpad.pad.fade.Fadeable; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.profile.Profile; import javafx.beans.value.ObservableValue; import javafx.util.Duration; @@ -21,9 +21,9 @@ import javafx.util.Duration; public class PadPositionListener implements Runnable, IPadPositionListener { private Pad pad; - private IPadViewController controller; + private AbstractPadViewController controller; - public PadPositionListener(IPadViewController controller) { + public PadPositionListener(AbstractPadViewController controller) { this.controller = controller; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java index bda5270de706c8c4ecfece808faaa2780eb11170..061cc894962680419298d76f8b326c825afb6770 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/pad/listener/PadStatusListener.java @@ -3,16 +3,16 @@ package de.tobias.playpad.pad.listener; import de.thecodelabs.midi.Mapping; import de.tobias.playpad.action.actions.CartAction; import de.tobias.playpad.pad.PadStatus; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.view.PseudoClasses; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; public class PadStatusListener implements ChangeListener<PadStatus> { - private IPadViewController controller; + private AbstractPadViewController controller; - public PadStatusListener(IPadViewController controller) { + public PadStatusListener(AbstractPadViewController controller) { this.controller = controller; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java b/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java index 7920226aec329f3beaa502e701fb055778ceef76..ca60c2c7bd416bf8da2e0b263172e9affec19ea1 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java +++ b/PlayWall/src/main/java/de/tobias/playpad/server/ServerImpl.java @@ -71,9 +71,9 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> { private static final String PROTOCOL = "https"; private static final String WS_PROTOCOL = "wss"; - private String host; + private final String host; private WebSocket websocket; - private ServerSyncListener syncListener; + private final ServerSyncListener syncListener; ServerImpl(String host) { this.host = host; @@ -281,6 +281,7 @@ public class ServerImpl implements Server, ChangeListener<ConnectionState> { public void connect(String key) { try { WebSocketFactory webSocketFactory = new WebSocketFactory(); + webSocketFactory.setConnectionTimeout(5000); if (PlayPadMain.sslContext != null) { webSocketFactory.setSSLContext(PlayPadMain.sslContext); } diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java index 98290adbcd0df99adf16698fe28258999e072a94..e103e69319bbd4457628bb024cc4f812e00d2c66 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java +++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/CartTriggerItemFactory.java @@ -6,6 +6,7 @@ import de.tobias.playpad.Strings; import de.tobias.playpad.tigger.Trigger; import de.tobias.playpad.tigger.TriggerItem; import de.tobias.playpad.tigger.TriggerItemFactory; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.option.pad.trigger.CartTriggerViewController; public class CartTriggerItemFactory extends TriggerItemFactory { @@ -20,8 +21,8 @@ public class CartTriggerItemFactory extends TriggerItemFactory { } @Override - public NVC getSettingsController(TriggerItem item) { - return new CartTriggerViewController((CartTriggerItem) item); + public NVC getSettingsController(TriggerItem item, IMainViewController mainViewController) { + return new CartTriggerViewController((CartTriggerItem) item, mainViewController); } @Override diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java index 434a17a2577ee8aee5a27b1a2850134362e350d0..e6a6a6aa5d3748b2cc348230870c16ac1f5e263b 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java +++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/TriggerDisplayable.java @@ -10,7 +10,7 @@ import javafx.beans.property.StringProperty; public class TriggerDisplayable implements Displayable { - private Trigger trigger; + private final Trigger trigger; public TriggerDisplayable(Trigger trigger) { this.trigger = trigger; @@ -21,7 +21,7 @@ public class TriggerDisplayable implements Displayable { return trigger; } - private StringProperty displayable = new SimpleStringProperty(); + private final StringProperty displayable = new SimpleStringProperty(); @Override public StringProperty displayProperty() { diff --git a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java index 73d2447a29858d8ba7ea630749aa89d8cec357dc..fa908a635f0a02ded7f7e3c4518a21a6c5efef05 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java +++ b/PlayWall/src/main/java/de/tobias/playpad/trigger/VolumeTriggerItemFactory.java @@ -6,6 +6,7 @@ import de.tobias.playpad.Strings; import de.tobias.playpad.tigger.Trigger; import de.tobias.playpad.tigger.TriggerItem; import de.tobias.playpad.tigger.TriggerItemFactory; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.option.pad.trigger.VolumeTriggerViewController; public class VolumeTriggerItemFactory extends TriggerItemFactory { @@ -20,8 +21,8 @@ public class VolumeTriggerItemFactory extends TriggerItemFactory { } @Override - public NVC getSettingsController(TriggerItem item) { - return new VolumeTriggerViewController((VolumeTriggerItem) item); + public NVC getSettingsController(TriggerItem item, IMainViewController mainViewController) { + return new VolumeTriggerViewController((VolumeTriggerItem) item, mainViewController); } @Override diff --git a/PlayWall/src/main/java/de/tobias/playpad/util/ListSerializer.java b/PlayWall/src/main/java/de/tobias/playpad/util/ListSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..155d9bdcf0638bd678fb6dae9ab45799963f68e6 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/util/ListSerializer.java @@ -0,0 +1,35 @@ +package de.tobias.playpad.util; + +import de.thecodelabs.storage.settings.UserDefaults; +import org.dom4j.Element; + +import java.util.ArrayList; +import java.util.List; + +public class ListSerializer implements UserDefaults.Serializer<ArrayList> { + + private static final String LIST_ITEM = "item"; + + @Override + public ArrayList get(Element element) { + ArrayList<Object> list = new ArrayList<>(); + for (Element child : element.elements(LIST_ITEM)) { + final Object o = UserDefaults.loadElement(child); + list.add(o); + } + return list; + } + + @Override + public void set(Object o, Element element) { + if (o instanceof List) { + //noinspection unchecked + final List<Object> list = (List<Object>) o; + + for (Object item : list) { + final Element childElement = element.addElement(LIST_ITEM); + UserDefaults.save(childElement, item, null); + } + } + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/util/NodeWalker.java b/PlayWall/src/main/java/de/tobias/playpad/util/NodeWalker.java new file mode 100644 index 0000000000000000000000000000000000000000..7a2a2b6a86c8a360606310494a7e11737a612020 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/util/NodeWalker.java @@ -0,0 +1,37 @@ +package de.tobias.playpad.util; + +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.control.Labeled; + +import java.util.ArrayList; +import java.util.List; + +public class NodeWalker { + + private NodeWalker() { + } + + public static List<Node> getAllNodes(Parent root) { + List<Node> nodes = new ArrayList<>(); + nodes.add(root); + addAllDescendents(root, nodes); + return nodes; + } + + private static void addAllDescendents(Parent parent, List<Node> nodes) { + for (Node node : parent.getChildrenUnmodifiable()) { + nodes.add(node); + + if (node instanceof Labeled) { + final Node graphic = ((Labeled) node).getGraphic(); + if (graphic != null) { + nodes.add(graphic); + } + } + + if (node instanceof Parent) + addAllDescendents((Parent) node, nodes); + } + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java b/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java index e04e34fbe511be49ef008abbdd6963f1219026db..38270ca6887aaa067025135443761d2215c55706 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java +++ b/PlayWall/src/main/java/de/tobias/playpad/view/FileDragOptionView.java @@ -1,6 +1,7 @@ package de.tobias.playpad.view; import de.tobias.playpad.pad.content.PadContentFactory; +import de.tobias.playpad.pad.drag.ContentDragOption; import javafx.animation.FadeTransition; import javafx.animation.ParallelTransition; import javafx.animation.ScaleTransition; @@ -14,16 +15,16 @@ import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.scene.text.TextAlignment; -import java.util.Set; +import java.util.Collection; import java.util.function.Consumer; -public class FileDragOptionView { +public class FileDragOptionView implements PadContentFactory.PadContentTypeChooser { - private HBox optionPane; - private Pane parent; + private final HBox optionPane; + private final Pane parent; - private Transition inTransition; - private Transition outTransition; + private final Transition inTransition; + private final Transition outTransition; public FileDragOptionView(Pane pane) { parent = pane; @@ -76,9 +77,9 @@ public class FileDragOptionView { return parallelTransition; } - private PadContentFactory selectedConnect; + private ContentDragOption selectedConnect; - public void showDropOptions(Set<PadContentFactory> options) { + public void showOptions(Collection<? extends ContentDragOption> options) { if (!parent.getChildren().contains(optionPane)) { selectedConnect = null; @@ -125,14 +126,16 @@ public class FileDragOptionView { } - public void showDropOptions(Set<PadContentFactory> options, Consumer<PadContentFactory> onFinish) { - showDropOptions(options); + public void showOptions(Collection<PadContentFactory> options, Consumer<PadContentFactory> onFinish) { + showOptions(options); for (Node node : optionPane.getChildren()) { if (node instanceof Label) { Label label = (Label) node; - label.setOnMouseClicked(ev -> - onFinish.accept((PadContentFactory) label.getUserData())); + label.setOnMouseClicked(ev -> { + onFinish.accept((PadContentFactory) label.getUserData()); + hide(); + }); label.setOnMouseEntered(e -> label.pseudoClassStateChanged(PseudoClasses.HOVER_CLASS, true)); label.setOnMouseExited(e -> @@ -141,7 +144,7 @@ public class FileDragOptionView { } } - public PadContentFactory getSelectedConnect() { + public ContentDragOption getSelectedConnect() { return selectedConnect; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java b/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java index 205250172cbe517acfb7cb51d1f052de96eae133..7dac34cde41953601b45c78688458d1418ed47ec 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java +++ b/PlayWall/src/main/java/de/tobias/playpad/view/PadDragOptionView.java @@ -100,7 +100,7 @@ public class PadDragOptionView { parent.getChildren().add(optionPane); optionPane.getChildren().clear(); - for (PadDragMode connect : options.stream().sorted().toArray(value -> new PadDragMode[value])) { + for (PadDragMode connect : options.stream().sorted().toArray(PadDragMode[]::new)) { Label label = new Label(); label.getStyleClass().add("dnd-file-option"); diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadButton.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadButton.java new file mode 100644 index 0000000000000000000000000000000000000000..9cfcd183917cda844a14d0875b669c8aed059e66 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadButton.java @@ -0,0 +1,35 @@ +package de.tobias.playpad.view.pad; + +import de.thecodelabs.utils.ui.icon.FontIcon; +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.Button; + +import static de.tobias.playpad.view.pad.PadStyleClasses.*; + +public class PadButton extends Button implements PadIndexable { + + private final ObjectProperty<PadIndex> indexProperty; + + public PadButton(FontIcon icon, EventHandler<ActionEvent> value) { + super("", icon); + + setFocusTraversable(false); + setOnAction(value); + + indexProperty = new SimpleObjectProperty<>(); + indexProperty.addListener(new StyleIndexListener(this, STYLE_CLASS_PAD_BUTTON, STYLE_CLASS_PAD_BUTTON_INDEX)); + indexProperty.addListener(new StyleIndexListener(getGraphic(), STYLE_CLASS_PAD_ICON, STYLE_CLASS_PAD_ICON_INDEX)); + } + + public PadIndex getIndex() { + return indexProperty.get(); + } + + public void setIndex(PadIndex index) { + indexProperty.set(index); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadHBox.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadHBox.java new file mode 100644 index 0000000000000000000000000000000000000000..3e0c2cdf37be559da5436023d84f375f701aa7e1 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadHBox.java @@ -0,0 +1,57 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.InvalidationListener; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.Node; +import javafx.scene.layout.HBox; + +import java.util.LinkedList; +import java.util.List; + +public class PadHBox extends HBox implements PadIndexable { + + private final ObjectProperty<PadIndex> indexProperty; + private final List<StyleIndexListener> styleListeners = new LinkedList<>(); + + public static PadHBox deepStyled(String... styleClasses) { + PadHBox padHBox = new PadHBox(styleClasses); + + padHBox.getChildren().addListener((InvalidationListener) observable -> { + for (StyleIndexListener listener : padHBox.styleListeners) { + padHBox.indexProperty.removeListener(listener); + } + + padHBox.styleListeners.clear(); + + for (Node child : padHBox.getChildren()) { + StyleIndexListener listener = new StyleIndexListener(child, styleClasses); + padHBox.indexProperty.addListener(listener); + padHBox.styleListeners.add(listener); + + listener.changed(padHBox.indexProperty, null, padHBox.indexProperty.get()); + } + }); + + return padHBox; + } + + public PadHBox(String... styleClasses) { + this(0, styleClasses); + } + + public PadHBox(double spacing, String... styleClasses) { + super(spacing); + indexProperty = new SimpleObjectProperty<>(); + indexProperty.addListener(new StyleIndexListener(this, styleClasses)); + } + + public PadIndex getIndex() { + return indexProperty.get(); + } + + public void setIndex(PadIndex index) { + indexProperty.set(index); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadIndexable.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadIndexable.java new file mode 100644 index 0000000000000000000000000000000000000000..c50a5cc70ee1604eeeb280636e8b3ae561480790 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadIndexable.java @@ -0,0 +1,9 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; + +public interface PadIndexable { + PadIndex getIndex(); + + void setIndex(PadIndex index); +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadLabel.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadLabel.java new file mode 100644 index 0000000000000000000000000000000000000000..f2aabb08af4bb3c2b1d99ee25576442ef2c4fb90 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadLabel.java @@ -0,0 +1,57 @@ +package de.tobias.playpad.view.pad; + +import de.thecodelabs.utils.ui.icon.FontIcon; +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.control.Label; + +import static de.tobias.playpad.view.pad.PadStyleClasses.STYLE_CLASS_PAD_ICON; +import static de.tobias.playpad.view.pad.PadStyleClasses.STYLE_CLASS_PAD_ICON_INDEX; + +public class PadLabel extends Label implements PadIndexable { + + private final ObjectProperty<PadIndex> indexProperty; + private StyleIndexListener graphicsListener; + + public static PadLabel empty(String... styleClasses) { + return new PadLabel("", styleClasses); + } + + public PadLabel(FontIcon icon, String... styleClasses) { + this("", styleClasses); + setGraphic(icon); + } + + public PadLabel(String text, String... styleClasses) { + super(text); + + indexProperty = new SimpleObjectProperty<>(); + indexProperty.addListener(new StyleIndexListener(this, styleClasses)); + initStyleGraphicsListener(); + + graphicProperty().addListener(observable -> { + if (graphicsListener != null) { + indexProperty.removeListener(graphicsListener); + graphicsListener = null; + + } + initStyleGraphicsListener(); + }); + } + + private void initStyleGraphicsListener() { + if (getGraphic() != null) { + graphicsListener = new StyleIndexListener(getGraphic(), STYLE_CLASS_PAD_ICON, STYLE_CLASS_PAD_ICON_INDEX); + indexProperty.addListener(graphicsListener); + } + } + + public PadIndex getIndex() { + return indexProperty.get(); + } + + public void setIndex(PadIndex index) { + indexProperty.set(index); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadProgressBar.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadProgressBar.java new file mode 100644 index 0000000000000000000000000000000000000000..1d366b8cfcf4ab58d695c76e24bbe2ada13b6a54 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadProgressBar.java @@ -0,0 +1,25 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.control.ProgressBar; + +public class PadProgressBar extends ProgressBar implements PadIndexable { + + private final ObjectProperty<PadIndex> indexProperty; + + public PadProgressBar(double progress, String... styleClasses) { + super(progress); + indexProperty = new SimpleObjectProperty<>(); + indexProperty.addListener(new StyleIndexListener(this, styleClasses)); + } + + public PadIndex getIndex() { + return indexProperty.get(); + } + + public void setIndex(PadIndex index) { + indexProperty.set(index); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStackPane.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStackPane.java new file mode 100644 index 0000000000000000000000000000000000000000..94d5670789563c8e01f906399bef0187cfc9a5f8 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStackPane.java @@ -0,0 +1,24 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.layout.StackPane; + +public class PadStackPane extends StackPane implements PadIndexable { + + private final ObjectProperty<PadIndex> indexProperty; + + public PadStackPane(String... styleClasses) { + indexProperty = new SimpleObjectProperty<>(); + indexProperty.addListener(new StyleIndexListener(this, styleClasses)); + } + + public PadIndex getIndex() { + return indexProperty.get(); + } + + public void setIndex(PadIndex index) { + indexProperty.set(index); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStyleClasses.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStyleClasses.java new file mode 100644 index 0000000000000000000000000000000000000000..b610e4391e05d21ea51949856af096c0bd021648 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadStyleClasses.java @@ -0,0 +1,37 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; + +public class PadStyleClasses { + + private PadStyleClasses() { + } + + public static final String STYLE_CLASS_PAD = "pad"; + public static final String STYLE_CLASS_PAD_INDEX = "pad${index}"; + + public static final String STYLE_CLASS_PAD_BUTTON = "pad-button"; + public static final String STYLE_CLASS_PAD_BUTTON_INDEX = "pad${index}-button"; + + public static final String STYLE_CLASS_PAD_ICON = "pad-icon"; + public static final String STYLE_CLASS_PAD_ICON_INDEX = "pad${index}-icon"; + + public static final String STYLE_CLASS_PAD_INFO = "pad-info"; + public static final String STYLE_CLASS_PAD_INFO_INDEX = "pad${index}-info"; + + public static final String STYLE_CLASS_PAD_TITLE = "pad-title"; + public static final String STYLE_CLASS_PAD_TITLE_INDEX = "pad${index}-title"; + + public static final String STYLE_CLASS_PAD_BUTTON_BOX = "pad-button-box"; + public static final String STYLE_CLASS_PAD_BUTTON_ROOT = "pad-root"; + + public static final String STYLE_CLASS_PAD_PLAYBAR = "pad-playbar"; + public static final String STYLE_CLASS_PAD_PLAYBAR_INDEX = "pad${index}-playbar"; + + public static final String STYLE_CLASS_PAD_CUE_IN = "pad-cue-in"; + public static final String STYLE_CLASS_PAD_CUE_IN_INDEX = "pad${index}-cue-in"; + + public static String replaceIndex(String styleClass, PadIndex index) { + return styleClass.replace("${index}", String.valueOf(index)); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadVBox.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadVBox.java new file mode 100644 index 0000000000000000000000000000000000000000..33d999dc7349e03010453853977619ba086e468d --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/PadVBox.java @@ -0,0 +1,29 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.layout.VBox; + +public class PadVBox extends VBox implements PadIndexable { + + private final ObjectProperty<PadIndex> indexProperty; + + public PadVBox(String... styleClasses) { + this(0, styleClasses); + } + + public PadVBox(double spacing, String... styleClasses) { + super(spacing); + indexProperty = new SimpleObjectProperty<>(); + indexProperty.addListener(new StyleIndexListener(this, styleClasses)); + } + + public PadIndex getIndex() { + return indexProperty.get(); + } + + public void setIndex(PadIndex index) { + indexProperty.set(index); + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/pad/StyleIndexListener.java b/PlayWall/src/main/java/de/tobias/playpad/view/pad/StyleIndexListener.java new file mode 100644 index 0000000000000000000000000000000000000000..de3acf0ce609fbed673a2aba820c1aef0cf0ffc7 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/view/pad/StyleIndexListener.java @@ -0,0 +1,32 @@ +package de.tobias.playpad.view.pad; + +import de.tobias.playpad.project.page.PadIndex; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.scene.Node; + +public class StyleIndexListener implements ChangeListener<PadIndex> { + + private final Node node; + private final String[] styleClasses; + + public StyleIndexListener(Node node, String... styleClasses) { + this.node = node; + this.styleClasses = styleClasses; + } + + @Override + public void changed(ObservableValue<? extends PadIndex> observable, PadIndex oldValue, PadIndex newValue) { + if (oldValue != null) { + for (String styleClass : styleClasses) { + node.getStyleClass().remove(PadStyleClasses.replaceIndex(styleClass, oldValue)); + } + } + + if (newValue != null) { + for (String styleClass : styleClasses) { + node.getStyleClass().add(PadStyleClasses.replaceIndex(styleClass, newValue)); + } + } + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java index 7c47592784002e01ae7bf9afed070ee0b959ec4f..4ae03e046bd0f2834543ac709659003d56d92573 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/dialog/AboutDialog.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -// TODO Extract into lang file public class AboutDialog extends NVC { @FXML @@ -40,6 +39,9 @@ public class AboutDialog extends NVC { @FXML private Label versionLabel; + @FXML + private Label platformLabel; + @FXML private Label authorLabel; @@ -52,7 +54,7 @@ public class AboutDialog extends NVC { @FXML private Label graphicsLabel; - private Window owner; + private final Window owner; public AboutDialog(Window owner) { this.owner = owner; @@ -68,7 +70,7 @@ public class AboutDialog extends NVC { AnchorPane.setLeftAnchor(icon, 14.0); AnchorPane.setTopAnchor(icon, 14.0); - icon.setOnMouseClicked((e) -> getStageContainer().ifPresent(NVCStage::close)); + icon.setOnMouseClicked(e -> getStageContainer().ifPresent(NVCStage::close)); ApplicationInfo info = ApplicationUtils.getApplication().getInfo(); versionLabel.setText(info.getVersion()); @@ -76,6 +78,10 @@ public class AboutDialog extends NVC { graphicsLabel.setText(Localization.getString(Strings.UI_DIALOG_ABOUT_GRAPHICS)); libsLabel.setText(Localization.getString(Strings.UI_DIALOG_ABOUT_LIBRARIES)); + platformLabel.setText(String.format("%s (%s) + %s (%s)", System.getProperty("java.version"), + System.getProperty("java.vendor"), System.getProperty("javafx.version"), + System.getProperty("javafx.runtime.version"))); + Hyperlink websiteLink = new Hyperlink(Localization.getString(Strings.UI_DIALOG_ABOUT_WEBSITE)); websiteLink.setPadding(Insets.EMPTY); websiteLink.setFocusTraversable(false); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java index b2bf4ab78fee9e28884c81cd21fb457db7f1f677..ec8f51a3dfc669a93d119794e71e1f9b2d29ee48 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/MainViewController.java @@ -363,6 +363,7 @@ public class MainViewController extends NVC implements IMainViewController, Noti } } } + Platform.exit(); return true; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java index 068ecda32cf6bd2f68391253facbedee24e5f5d1..e29db503f32fbff22d8f33dcf471b8423c9238af 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java @@ -36,9 +36,8 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings @FXML private Button finishButton; - private List<GlobalSettingsTabViewController> tabs = new ArrayList<>(); - - private Runnable onFinish; + private final List<GlobalSettingsTabViewController> tabs = new ArrayList<>(); + private final Runnable onFinish; public GlobalSettingsViewController(Window owner, Runnable onFinish) { load("view/option/global", "GlobalSettingsView", Localization.getBundle()); @@ -53,6 +52,13 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings addTab(new KeysTabViewController()); addTab(new UpdateTabViewController()); + PlayPadPlugin.getInstance().getGlobalSettingsTabs().forEach(supplier -> { + final GlobalSettingsTabViewController globalSettingsTabViewController = supplier.get(); + if (globalSettingsTabViewController != null) { + addTab(globalSettingsTabViewController); + } + }); + // Show Current Settings loadTabs(); } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java index fd2bb3bcd7679c4e777a0b103866730733932f86..604d60b25598cbf48aa1d6d4ade48fa9c854795e 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/UpdateTabViewController.java @@ -24,7 +24,9 @@ import javafx.fxml.FXML; import javafx.scene.control.*; import java.io.IOException; +import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; public class UpdateTabViewController extends GlobalSettingsTabViewController { @@ -56,7 +58,11 @@ public class UpdateTabViewController extends GlobalSettingsTabViewController { GlobalSettings globalSettings = playPad.getGlobalSettings(); updateChannelComboBox.setValue(globalSettings.getUpdateChannel()); - openUpdateList.getItems().setAll(playPad.getUpdateService().getRemoteVersions().values()); + final List<Version> updates = playPad.getUpdateService().getRemoteVersions().values() + .stream() + .filter(Objects::nonNull) + .collect(Collectors.toList()); + openUpdateList.getItems().setAll(updates); updateButton.setDisable(openUpdateList.getItems().isEmpty()); ApplicationInfo info = ApplicationUtils.getApplication().getInfo(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java index cd36d822fa42ae26dac33467de7f3b1434e23e7a..4e40233ca501ef4edc4c8f2a3c1aca28d042dadb 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/GeneralPadTabViewController.java @@ -1,21 +1,36 @@ package de.tobias.playpad.viewcontroller.option.pad; +import de.thecodelabs.utils.application.system.NativeApplication; import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.Strings; +import de.tobias.playpad.layout.desktop.listener.PadNewContentListener; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.PadSettings; import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.TimeMode; +import de.tobias.playpad.pad.content.PadContentFactory; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; import de.tobias.playpad.viewcontroller.cell.EnumCell; +import javafx.beans.binding.Bindings; import javafx.beans.value.ChangeListener; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.*; +import javafx.scene.layout.VBox; import javafx.stage.Stage; +import java.util.Optional; + public class GeneralPadTabViewController extends PadSettingsTabViewController { + @FXML + private VBox mediaRootBox; + @FXML + private Label pathLabel; + @FXML + private Button showPathButton; + @FXML private TextField titleTextField; @FXML @@ -31,12 +46,24 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController { @FXML private Button deleteButton; - private Pad pad; + private final Pad pad; GeneralPadTabViewController(Pad pad) { load("view/option/pad", "GeneralTab", Localization.getBundle()); this.pad = pad; + if (pad.getPath() != null) { + pathLabel.setText(pad.getPath().toString()); + } else { + pathLabel.setText(Localization.getString("padSettings.gen.label.media.empty")); + } + showPathButton.disableProperty().bind(Bindings.isEmpty(pad.getPaths())); + + // Disable media section for playlists + if (pad.getContent() instanceof Playlistable) { + mediaRootBox.setDisable(true); + } + if (pad.getStatus() == PadStatus.PLAY || pad.getStatus() == PadStatus.PAUSE) { deleteButton.setDisable(true); } @@ -44,7 +71,6 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController { @Override public void init() { - // Init Listener ChangeListener<Number> volumeListener = (a, b, c) -> pad.getPadSettings().setVolume(c.doubleValue() / 100.0); volumeSlider.valueProperty().addListener(volumeListener); @@ -71,16 +97,14 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController { @Override public void loadSettings(Pad pad) { - PadSettings padSettings = pad.getPadSettings(); + final PadSettings padSettings = pad.getPadSettings(); - // Bindings titleTextField.textProperty().bindBidirectional(pad.nameProperty()); repeatCheckBox.selectedProperty().bindBidirectional(padSettings.loopProperty()); timeDisplayComboBox.valueProperty().bindBidirectional(padSettings.timeModeProperty()); volumeSlider.setValue(padSettings.getVolume() * 100); - // is Custom TimeMode Actvie customTimeDisplayCheckBox.setSelected(padSettings.isCustomTimeMode()); if (!padSettings.isCustomTimeMode()) { timeDisplayComboBox.setDisable(true); @@ -96,7 +120,21 @@ public class GeneralPadTabViewController extends PadSettingsTabViewController { timeDisplayComboBox.valueProperty().unbindBidirectional(padSettings.timeModeProperty()); } - // Listener + @FXML + private void showPathButtonHandler() { + NativeApplication.sharedInstance().showFileInFileViewer(pad.getPath()); + } + + @FXML + private void chooseButtonHandler(ActionEvent event) { + final PadNewContentListener listener = new PadNewContentListener(pad); + listener.onNew(event, (options, onSelected) -> { + ChoiceDialog<PadContentFactory> dialog = new ChoiceDialog<>(null, options); + final Optional<PadContentFactory> padContentFactory = dialog.showAndWait(); + padContentFactory.ifPresent(onSelected); + }); + } + @FXML private void deleteButtonHandler(ActionEvent event) { pad.clear(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java index 739b65fd2c8591af25fbf2d4eb134ffd7b92332b..d7da00b3990912aaa2c9f0c6c3600408fbed1256 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PadSettingsViewController.java @@ -10,64 +10,63 @@ import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.content.PadContentFactory; import de.tobias.playpad.pad.content.PadContentRegistry; -import de.tobias.playpad.pad.mediapath.MediaPath; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.registry.NoSuchComponentException; import de.tobias.playpad.viewcontroller.IPadSettingsViewController; import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; -import javafx.collections.ObservableList; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import javafx.event.ActionEvent; import javafx.fxml.FXML; -import javafx.scene.Parent; -import javafx.scene.control.*; -import javafx.scene.layout.AnchorPane; +import javafx.scene.control.Button; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; import javafx.stage.Stage; -import javafx.stage.Window; import java.util.ArrayList; import java.util.List; +import java.util.Optional; public class PadSettingsViewController extends NVC implements IPadSettingsViewController { - private Pad pad; + private final Pad pad; @FXML private TabPane tabPane; - private List<PadSettingsTabViewController> tabs = new ArrayList<>(); - - private Control pathLookupButton; + private final List<PadSettingsTabViewController> tabs = new ArrayList<>(); @FXML private Button finishButton; - public PadSettingsViewController(Pad pad, Window owner) { + public PadSettingsViewController(Pad pad, IMainViewController mainViewController) { load("view/option/pad", "PadSettingsView", Localization.getBundle()); this.pad = pad; addTab(new GeneralPadTabViewController(pad)); + if (pad.getContent() instanceof Playlistable) { + addTab(new PlaylistTabViewController(pad)); + } addTab(new DesignPadTabViewController(pad)); addTab(new PlayerPadTabViewController(pad)); - addTab(new TriggerPadTabViewController(pad)); + addTab(new TriggerPadTabViewController(pad, mainViewController)); if (pad.getContent() != null) { try { - // Get Pad Type specific tab - String type = pad.getContent().getType(); - PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents(); + final String type = pad.getContent().getType(); + final PadContentRegistry registry = PlayPadPlugin.getRegistries().getPadContents(); - PadContentFactory padContentFactory = registry.getFactory(type); - PadSettingsTabViewController contentTab = padContentFactory.getSettingsViewController(pad); + final PadContentFactory padContentFactory = registry.getFactory(type); + final PadSettingsTabViewController contentTab = padContentFactory.getSettingsViewController(pad); - if (contentTab != null) + if (contentTab != null) { addTab(contentTab); + } } catch (NoSuchComponentException e) { Logger.error(e); } } - setupPathLookupButton(); - NVCStage nvcStage = applyViewControllerToStage(); - nvcStage.initOwner(owner); + nvcStage.initOwner(mainViewController.getStage()); nvcStage.addCloseHook(this::onFinish); addCloseKeyShortcut(() -> finishButton.fire()); @@ -76,57 +75,23 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo setTitle(pad); } - private void setupPathLookupButton() { - PathLookupListener pathLookupListener = new PathLookupListener(); - - if (pad.getContent() != null) { - final ObservableList<MediaPath> paths = pad.getPaths(); - if (paths.size() == 1) { - Button button = new Button(Localization.getString("padSettings.button.path")); - - MediaPath path = paths.get(0); - button.setUserData(path); - button.setOnAction(pathLookupListener); - - pathLookupButton = button; - } else if (paths.size() > 1) { - MenuButton button = new MenuButton(Localization.getString("padSettings.button.path")); - - for (MediaPath path : paths) { - MenuItem item = new MenuItem(path.getFileName()); - button.getItems().add(item); - - item.setUserData(path); - item.setOnAction(pathLookupListener); - } - - pathLookupButton = button; - } - - Parent parent = getParent(); - if (parent instanceof AnchorPane && pathLookupButton != null) { - AnchorPane anchorPane = (AnchorPane) parent; - anchorPane.getChildren().add(pathLookupButton); - - AnchorPane.setLeftAnchor(pathLookupButton, 14.0); - AnchorPane.setBottomAnchor(pathLookupButton, 14.0); - } - } - } - private void setTitle(Pad pad) { String title; if (pad.getStatus() != PadStatus.EMPTY) { - title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE, pad.getPositionReadable(), pad.getName()); + try { + title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE, pad.getPositionReadable(), pad.getName()); + } catch (IllegalStateException e) { + Logger.error(e); + title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE_EMPTY, pad.getPositionReadable()); + } } else { title = Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_TITLE_EMPTY, pad.getPositionReadable()); } - getStageContainer().ifPresent(nvcStage -> nvcStage.getStage().setTitle(title)); - } - - @Override - public void init() { + final Optional<NVCStage> stageContainer = getStageContainer(); + if (stageContainer.isPresent()) { + stageContainer.get().getStage().setTitle(title); + } } @Override @@ -134,7 +99,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo stage.getIcons().add(PlayPadPlugin.getInstance().getIcon()); stage.setMinWidth(650); - stage.setMinHeight(550); + stage.setMinHeight(600); PlayPadPlugin.styleable().applyStyle(stage); } @@ -162,6 +127,7 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo @FXML private void finishButtonHandler(ActionEvent event) { onFinish(); + getStageContainer().ifPresent(NVCStage::close); } /** @@ -173,7 +139,6 @@ public class PadSettingsViewController extends NVC implements IPadSettingsViewCo for (PadSettingsTabViewController controller : tabs) { controller.saveSettings(pad); } - getStageContainer().ifPresent(NVCStage::close); return true; } } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PathLookupListener.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PathLookupListener.java deleted file mode 100644 index 148f385f1de2c8c9018086a80087c4ef6a8ba314..0000000000000000000000000000000000000000 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PathLookupListener.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.tobias.playpad.viewcontroller.option.pad; - -import de.thecodelabs.utils.application.system.NativeApplication; -import de.tobias.playpad.pad.mediapath.MediaPath; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.control.Button; -import javafx.scene.control.MenuItem; - -import java.nio.file.Path; - -public class PathLookupListener implements EventHandler<ActionEvent> { - - @Override - public void handle(ActionEvent event) { - Object source = event.getSource(); - if (source instanceof Button) { - // single path - Object userData = ((Button) source).getUserData(); - if (userData instanceof MediaPath) { - showPath((MediaPath) userData); - } - } else if (source instanceof MenuItem) { - // multiple path - Object userData = ((MenuItem) source).getUserData(); - if (userData instanceof Path) { - showPath((MediaPath) userData); - } - } - } - - private void showPath(MediaPath path) { - NativeApplication.sharedInstance().showFileInFileViewer(path.getPath()); - } -} \ No newline at end of file diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java index 67d71214c4bd6b72e4eab97da3d926de39f302d5..11d394f681a0bb2f852d0907cffd60e927012d4b 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java @@ -4,10 +4,10 @@ import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.Strings; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.PadSettings; -import de.tobias.playpad.settings.Fade; +import de.tobias.playpad.settings.FadeSettings; import de.tobias.playpad.view.PseudoClasses; import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; -import de.tobias.playpad.viewcontroller.settings.FadeViewController; +import de.tobias.playpad.viewcontroller.settings.FadeSettingsViewController; import de.tobias.playpad.viewcontroller.settings.WarningFeedbackViewController; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; @@ -21,7 +21,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController { private CheckBox customFadeCheckBox; @FXML private VBox fadeContainer; - private FadeViewController fadeViewController; + private FadeSettingsViewController fadeViewController; @FXML private VBox warningFeedbackContainer; @@ -42,7 +42,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController { @Override public void init() { // Embed ViewController - fadeViewController = new FadeViewController(); + fadeViewController = new FadeSettingsViewController(); fadeContainer.getChildren().add(fadeViewController.getParent()); warningFeedbackViewController = WarningFeedbackViewController.newViewControllerForPad(); @@ -54,12 +54,12 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController { PadSettings padSettings = pad.getPadSettings(); if (c && !padSettings.isCustomFade()) - padSettings.setFade(new Fade()); + padSettings.setFade(new FadeSettings()); else if (!c && padSettings.isCustomFade()) padSettings.setFade(null); if (c) - fadeViewController.setFade(padSettings.getFade()); + fadeViewController.setFadeSettings(padSettings.getFade()); }); warningEnableCheckBox.selectedProperty().addListener((a, b, c) -> @@ -104,7 +104,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController { PadSettings padSettings = pad.getPadSettings(); if (padSettings.isCustomFade()) - fadeViewController.setFade(padSettings.getFade()); + fadeViewController.setFadeSettings(padSettings.getFade()); customFadeCheckBox.setSelected(padSettings.isCustomFade()); if (!padSettings.isCustomFade()) { diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlaylistTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlaylistTabViewController.java new file mode 100644 index 0000000000000000000000000000000000000000..0a80e87d3169c61af24b9a8fdaf0f233f6cf2979 --- /dev/null +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlaylistTabViewController.java @@ -0,0 +1,165 @@ +package de.tobias.playpad.viewcontroller.option.pad; + +import de.thecodelabs.utils.application.system.NativeApplication; +import de.thecodelabs.utils.ui.icon.FontAwesomeType; +import de.thecodelabs.utils.ui.icon.FontIcon; +import de.thecodelabs.utils.util.Localization; +import de.tobias.playpad.PlayPadPlugin; +import de.tobias.playpad.Strings; +import de.tobias.playpad.layout.desktop.listener.PadNewContentListener; +import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.content.PadContentFactory; +import de.tobias.playpad.pad.content.PadContentRegistry; +import de.tobias.playpad.pad.content.Playlistable; +import de.tobias.playpad.pad.mediapath.MediaPath; +import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; +import javafx.beans.binding.Bindings; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +public class PlaylistTabViewController extends PadSettingsTabViewController { + + @FXML + private ListView<MediaPath> mediaPathListView; + + @FXML + private Button addButton; + @FXML + private Button upButton; + @FXML + private Button downButton; + + @FXML + private Label pathLabel; + @FXML + private Button deleteButton; + @FXML + private Button showFileButton; + + private final Pad pad; + + public PlaylistTabViewController(Pad pad) { + this.pad = pad; + load("view/option/pad", "PlaylistTab", Localization.getBundle()); + + mediaPathListView.setItems(pad.getPaths()); + initButtons(); + } + + @Override + public void init() { + addButton.setGraphic(new FontIcon(FontAwesomeType.PLUS)); + upButton.setGraphic(new FontIcon(FontAwesomeType.ARROW_UP)); + downButton.setGraphic(new FontIcon(FontAwesomeType.ARROW_DOWN)); + + mediaPathListView.setCellFactory(param -> new ListCell<MediaPath>() { + @Override + protected void updateItem(MediaPath item, boolean empty) { + super.updateItem(item, empty); + if (!empty) { + setText(item.getFileName()); + final Playlistable playlist = (Playlistable) pad.getContent(); + if (!playlist.isLoaded(item)) { + setGraphic(new FontIcon(FontAwesomeType.WARNING)); + } else { + setGraphic(null); + } + } else { + setText(""); + setGraphic(null); + } + } + }); + + pathLabel.setText(Localization.getString("padSettings.gen.label.media.empty")); + mediaPathListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + pathLabel.setText(newValue.getPath().toString()); + } else { + pathLabel.setText(Localization.getString("padSettings.gen.label.media.empty")); + } + }); + } + + private void initButtons() { + upButton.disableProperty() + .bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull() + .or(mediaPathListView.getSelectionModel().selectedIndexProperty().isEqualTo(0))); + downButton.disableProperty() + .bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull() + .or(mediaPathListView.getSelectionModel().selectedIndexProperty().isEqualTo(Bindings.size(mediaPathListView.getItems()).subtract(1)))); + + deleteButton.disableProperty().bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull()); + showFileButton.disableProperty().bind(mediaPathListView.getSelectionModel().selectedItemProperty().isNull()); + } + + @Override + public String getName() { + return Localization.getString(Strings.UI_WINDOW_PAD_SETTINGS_PLAYLIST_TITLE); + } + + @Override + public void loadSettings(Pad pad) { + // Not implemented + } + + @Override + public void saveSettings(Pad pad) { + // Not implemented + } + + @FXML + public void onAddHandler(ActionEvent event) { + final PadContentRegistry padContentRegistry = PlayPadPlugin.getRegistries().getPadContents(); + final PadContentFactory contentFactory = padContentRegistry.getFactory(pad.getContent().getType()); + + final PadNewContentListener padNewContentListener = new PadNewContentListener(pad); + final List<File> files = padNewContentListener.showMediaOpenFileChooser(event, contentFactory.getSupportedTypes(), true); + + if (files != null) { + for (File file : files) { + pad.addPath(file.toPath()); + } + } + } + + @FXML + public void onUpHandler(ActionEvent event) { + final int selectedIndex = mediaPathListView.getSelectionModel().getSelectedIndex(); + Collections.swap(pad.getPaths(), selectedIndex, selectedIndex - 1); + mediaPathListView.getSelectionModel().select(selectedIndex - 1); + pad.getContent().reorderMedia(); + } + + @FXML + public void onDownAction(ActionEvent event) { + final int selectedIndex = mediaPathListView.getSelectionModel().getSelectedIndex(); + Collections.swap(pad.getPaths(), selectedIndex, selectedIndex + 1); + mediaPathListView.getSelectionModel().select(selectedIndex + 1); + pad.getContent().reorderMedia(); + } + + @FXML + public void onShowFileHandler(ActionEvent event) { + MediaPath mediaPath = mediaPathListView.getSelectionModel().getSelectedItem(); + NativeApplication.sharedInstance().showFileInFileViewer(mediaPath.getPath()); + } + + @FXML + public void onDeleteHandler(ActionEvent event) { + MediaPath mediaPath = mediaPathListView.getSelectionModel().getSelectedItem(); + pad.removePath(mediaPath); + + if (pad.getPaths().isEmpty()) { + pad.clear(); + } + } +} diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java index 33fd3432634f564d5718ba8fc85d4fc4725a42b7..d9e1d8fc62dee9745734c99a475b77898a0bf5ea 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/TriggerPadTabViewController.java @@ -8,6 +8,7 @@ import de.tobias.playpad.tigger.TriggerPoint; import de.tobias.playpad.trigger.TriggerDisplayable; import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; import de.tobias.playpad.viewcontroller.cell.DisplayableTreeCell; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.option.pad.trigger.TriggerPointViewController; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; @@ -26,9 +27,11 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im @FXML private VBox contentView; - private Pad pad; + private final Pad pad; + private final IMainViewController mainViewController; - TriggerPadTabViewController(Pad pad) { + TriggerPadTabViewController(Pad pad, IMainViewController mainViewController) { + this.mainViewController = mainViewController; load("view/option/pad", "TriggerTab", Localization.getBundle()); this.pad = pad; } @@ -61,7 +64,7 @@ public class TriggerPadTabViewController extends PadSettingsTabViewController im if (newValue != null) { TriggerDisplayable triggerWrapper = newValue.getValue(); - TriggerPointViewController controller = new TriggerPointViewController(triggerWrapper); + TriggerPointViewController controller = new TriggerPointViewController(mainViewController, triggerWrapper); contentView.getChildren().setAll(controller.getParent()); VBox.setVgrow(controller.getParent(), Priority.ALWAYS); } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java index a5d2f0ea9780c898b90e1ebd98efff2c60d19653..1168ae13aedb828a12ba14ff18c14bad68718a1d 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/CartTriggerViewController.java @@ -8,6 +8,7 @@ import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.project.Project; import de.tobias.playpad.trigger.CartTriggerItem; import de.tobias.playpad.view.main.ProjectPreviewView; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import javafx.beans.InvalidationListener; import javafx.fxml.FXML; import javafx.geometry.Insets; @@ -25,17 +26,17 @@ public class CartTriggerViewController extends NVC { @FXML private CheckBox allCartsCheckbox; - private ProjectPreviewView projectPreviewView; + private final ProjectPreviewView projectPreviewView; - private CartTriggerItem item; + private final CartTriggerItem item; - public CartTriggerViewController(CartTriggerItem item) { + public CartTriggerViewController(CartTriggerItem item, IMainViewController mainViewController) { load("view/option/pad/trigger", "CartTrigger", Localization.getBundle()); this.item = item; Project project = PlayPadMain.getProgramInstance().getCurrentProject(); final List<Pad> pads = item.getCarts().stream().map(project::getPad).collect(Collectors.toList()); - projectPreviewView = new ProjectPreviewView(project, pads); + projectPreviewView = new ProjectPreviewView(project, pads, mainViewController.getPage()); projectPreviewView.setPadding(new Insets(0, 0, 0, 164)); projectPreviewView.selectedProperty().addListener((InvalidationListener) observable -> { item.getCarts().clear(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java index 77d5166b7191a5da2d5f2565bd1221da47e830b4..85793e58329cc0793f8919085cf1059bd01cb500 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/TriggerPointViewController.java @@ -10,6 +10,7 @@ import de.tobias.playpad.registry.NoSuchComponentException; import de.tobias.playpad.tigger.TriggerItem; import de.tobias.playpad.tigger.TriggerItemFactory; import de.tobias.playpad.trigger.TriggerDisplayable; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ContentDisplay; @@ -26,14 +27,17 @@ public class TriggerPointViewController extends NVC { @FXML private HBox buttonBox; - private TriggerDisplayable triggerWrapper; + private final IMainViewController mainViewController; + private final TriggerDisplayable triggerWrapper; - public TriggerPointViewController(TriggerDisplayable triggerWrapper) { + public TriggerPointViewController(IMainViewController mainViewController, TriggerDisplayable triggerWrapper) { + this.mainViewController = mainViewController; load("view/option/pad/trigger", "TriggerPoint", Localization.getBundle()); this.triggerWrapper = triggerWrapper; - for (TriggerItem item : triggerWrapper.getTrigger().getItems()) - showTriggerItem(item); + for (TriggerItem item : triggerWrapper.getTrigger().getItems()) { + showTriggerItem(item, mainViewController); + } } @Override @@ -42,17 +46,17 @@ public class TriggerPointViewController extends NVC { types.stream().sorted().forEach(item -> { try { - TriggerItemFactory conntect = PlayPadPlugin.getRegistries().getTriggerItems().getFactory(item); - Button button = new Button(conntect.toString(), new FontIcon(FontAwesomeType.PLUS_CIRCLE)); + TriggerItemFactory factory = PlayPadPlugin.getRegistries().getTriggerItems().getFactory(item); + Button button = new Button(factory.toString(), new FontIcon(FontAwesomeType.PLUS_CIRCLE)); button.setContentDisplay(ContentDisplay.TOP); button.setPrefWidth(150); button.setOnAction(e -> { - TriggerItem triggerItem = conntect.newInstance(triggerWrapper.getTrigger()); + TriggerItem triggerItem = factory.newInstance(triggerWrapper.getTrigger()); triggerWrapper.addItem(triggerItem); - showTriggerItem(triggerItem); + showTriggerItem(triggerItem, mainViewController); }); buttonBox.getChildren().add(button); } catch (NoSuchComponentException e) { @@ -61,17 +65,19 @@ public class TriggerPointViewController extends NVC { }); } - private void showTriggerItem(TriggerItem item) { + private void showTriggerItem(TriggerItem item, IMainViewController mainViewController) { try { TriggerItemFactory connect = PlayPadPlugin.getRegistries().getTriggerItems().getFactory(item.getType()); VBox itemBox = new VBox(14); - NVC controller = connect.getSettingsController(item); + NVC controller = connect.getSettingsController(item, mainViewController); if (controller != null) { itemBox.getChildren().add(controller.getParent()); - NVC timeViewController = new TriggerTimeViewController(item); - itemBox.getChildren().add(timeViewController.getParent()); + if (triggerWrapper.getTrigger().getTriggerPoint().isTimeAppendable()) { + final NVC timeViewController = new TriggerTimeViewController(item); + itemBox.getChildren().add(timeViewController.getParent()); + } Button deleteButton = new Button("", new FontIcon(FontAwesomeType.TRASH)); HBox hbox = new HBox(itemBox, deleteButton); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java index 10a1a70dfb79ad38c6eedcacaa450384a65cdef9..f48a57341e8a354af30dafc4ead00f256d7955f4 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/trigger/VolumeTriggerViewController.java @@ -8,6 +8,7 @@ import de.tobias.playpad.pad.Pad; import de.tobias.playpad.project.Project; import de.tobias.playpad.trigger.VolumeTriggerItem; import de.tobias.playpad.view.main.ProjectPreviewView; +import de.tobias.playpad.viewcontroller.main.IMainViewController; import javafx.beans.InvalidationListener; import javafx.fxml.FXML; import javafx.geometry.Insets; @@ -30,20 +31,20 @@ public class VolumeTriggerViewController extends NVC { private Slider durationSlider; @FXML private Label durationLabel; - private ProjectPreviewView projectPreviewView; + private final ProjectPreviewView projectPreviewView; - private VolumeTriggerItem item; + private final VolumeTriggerItem item; - public VolumeTriggerViewController(VolumeTriggerItem item) { + public VolumeTriggerViewController(VolumeTriggerItem item, IMainViewController mainViewController) { load("view/option/pad/trigger", "VolumeTrigger", Localization.getBundle()); this.item = item; volumeSlider.setValue(item.getVolume() * 100.0); durationSlider.setValue(item.getDuration().toSeconds()); - Project project = PlayPadMain.getProgramInstance().getCurrentProject(); + final Project project = PlayPadMain.getProgramInstance().getCurrentProject(); final List<Pad> pads = item.getCarts().stream().map(project::getPad).collect(Collectors.toList()); - projectPreviewView = new ProjectPreviewView(project, pads); + projectPreviewView = new ProjectPreviewView(project, pads, mainViewController.getPage()); projectPreviewView.setPadding(new Insets(0, 0, 0, 164)); projectPreviewView.selectedProperty().addListener((InvalidationListener) observable -> { item.getCarts().clear(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java index 384bb2ed2a3fc5a673a82827410e905ca302a45d..7d6e0cb80ec93b40dd5ed01b725a4fe2e49a395b 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java @@ -7,7 +7,7 @@ import de.tobias.playpad.profile.Profile; import de.tobias.playpad.profile.ProfileSettings; import de.tobias.playpad.viewcontroller.cell.EnumCell; import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; -import de.tobias.playpad.viewcontroller.settings.FadeViewController; +import de.tobias.playpad.viewcontroller.settings.FadeSettingsViewController; import de.tobias.playpad.viewcontroller.settings.WarningFeedbackViewController; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; @@ -32,8 +32,8 @@ public class PlayerTabViewController extends ProfileSettingsTabViewController { load("view/option/profile", "PlayerTab", Localization.getBundle()); // Player - FadeViewController fadeViewController = new FadeViewController(); - fadeViewController.setFade(Profile.currentProfile().getProfileSettings().getFade()); + FadeSettingsViewController fadeViewController = new FadeSettingsViewController(); + fadeViewController.setFadeSettings(Profile.currentProfile().getProfileSettings().getFade()); fadeContainer.getChildren().add(fadeViewController.getParent()); setAnchor(fadeViewController.getParent(), 0, 0, 0, 0); } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java index 1c4b3641862810f6d72a8366aad2936365556fc1..4f0ab95348e67855818b1aaf81a63b5a9010a4e7 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java @@ -40,15 +40,15 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin @FXML private Button finishButton; - private List<ProfileSettingsTabViewController> tabs = new ArrayList<>(); + private final List<ProfileSettingsTabViewController> tabs = new ArrayList<>(); - private Runnable onFinish; + private final Runnable onFinish; public ProfileSettingsViewController(Window owner, Project project, Runnable onFinish) { load("view/option/profile", "SettingsView", Localization.getBundle()); this.onFinish = onFinish; - boolean activePlayer = project.hasActivePlayers(); + boolean hasActivePlayers = project.hasActivePlayers(); addTab(new MappingTabViewController()); addTab(new DesignTabViewController()); @@ -58,12 +58,19 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin PadContentRegistry padContents = PlayPadPlugin.getRegistries().getPadContents(); for (String type : padContents.getTypes()) { PadContentFactory component = padContents.getFactory(type); - ProfileSettingsTabViewController controller = component.getSettingsTabViewController(activePlayer); + ProfileSettingsTabViewController controller = component.getSettingsTabViewController(hasActivePlayers); if (controller != null) { addTab(controller); } } + PlayPadPlugin.getInstance().getAdditionalProfileSettingsTabs().forEach(supplier -> { + ProfileSettingsTabViewController controller = supplier.get(); + if (controller != null) { + addTab(controller); + } + }); + NVCStage nvcStage = applyViewControllerToStage(); nvcStage.initOwner(owner); nvcStage.addCloseHook(this::onFinish); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java index dac32ea109085e1fbd079363f87a73ea1a70f18d..33ed71c972ff750b188f775ae9347caea26d2563 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/GeneralTabViewController.java @@ -6,6 +6,8 @@ import de.tobias.playpad.Strings; import de.tobias.playpad.design.ModernDesignSizeHelper; import de.tobias.playpad.project.Project; import de.tobias.playpad.project.ProjectSettings; +import de.tobias.playpad.project.ProjectSettingsValidator; +import de.tobias.playpad.project.ProjectSettingsValidator.ValidationState; import de.tobias.playpad.view.PseudoClasses; import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.option.IProjectReloadTask; @@ -16,25 +18,16 @@ import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.stage.Screen; -public class GeneralTabViewController extends ProjectSettingsTabViewController implements IProjectReloadTask { - - public static final int DISPLAY_OFFSET = 100; +import static de.tobias.playpad.project.ProjectSettingsValidator.Dimension; - private enum ValidationState { - NORMAL, - TOO_MUCH, - TOO_LESS - } - - private enum Dimension { - COLUMNS, - ROWS - } +public class GeneralTabViewController extends ProjectSettingsTabViewController implements IProjectReloadTask { private static final String DIGIT_POSITIVE = "^[1-9]\\d*$"; - private Screen mainWindowScreen; - private Alertable parentController; // Für Benachrichtungen + private final Screen mainWindowScreen; + private final Alertable parentController; // Für Benachrichtungen + + private final ProjectSettingsValidator projectSettingsValidator; @FXML private TextField columnTextField; @@ -52,6 +45,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i this.mainWindowScreen = currentScreen; this.parentController = parentController; + this.projectSettingsValidator = new ProjectSettingsValidator(this.mainWindowScreen); + if (activePlayer) { rowTextField.setDisable(true); columnTextField.setDisable(true); @@ -63,7 +58,7 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i columnTextField.textProperty().addListener((a, b, c) -> { if (c.matches(DIGIT_POSITIVE) && !c.isEmpty()) { - ValidationState validationState = validate(Integer.parseInt(c), Dimension.COLUMNS); + ValidationState validationState = projectSettingsValidator.validate(Integer.parseInt(c), Dimension.COLUMNS); if (validationState == ValidationState.NORMAL) { columnTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false); columnErrorLabel.setText(""); @@ -73,22 +68,22 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i String errorText = ""; // Error Message if (validationState == ValidationState.TOO_MUCH) { - errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, maxValue(Dimension.COLUMNS)); + errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, projectSettingsValidator.maxValue(Dimension.COLUMNS)); } else if (validationState == ValidationState.TOO_LESS) { - errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.COLUMNS)); + errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.COLUMNS)); } columnErrorLabel.setText(errorText); } } else { columnTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true); - columnErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.COLUMNS))); + columnErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.COLUMNS))); } }); rowTextField.textProperty().addListener((a, b, c) -> { if (c.matches(DIGIT_POSITIVE) && !c.isEmpty()) { - ValidationState validationState = validate(Integer.parseInt(c), Dimension.ROWS); + ValidationState validationState = projectSettingsValidator.validate(Integer.parseInt(c), Dimension.ROWS); if (validationState == ValidationState.NORMAL) { rowTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, false); rowErrorLabel.setText(""); @@ -98,49 +93,19 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i String errorText = ""; // Error Message if (validationState == ValidationState.TOO_MUCH) { - errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, maxValue(Dimension.ROWS)); + errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_MUCH, projectSettingsValidator.maxValue(Dimension.ROWS)); } else if (validationState == ValidationState.TOO_LESS) { - errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.ROWS)); + errorText = Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.ROWS)); } rowErrorLabel.setText(errorText); } } else { rowTextField.pseudoClassStateChanged(PseudoClasses.ERROR_CLASS, true); - rowErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, minValue(Dimension.ROWS))); + rowErrorLabel.setText(Localization.getString(Strings.ERROR_SCREEN_TOO_LESS, projectSettingsValidator.minValue(Dimension.ROWS))); } }); } - private ValidationState validate(int input, Dimension dimension) { - if (input < minValue(dimension)) { - return ValidationState.TOO_LESS; - } else if (input > maxValue(dimension)) { - return ValidationState.TOO_MUCH; - } - return ValidationState.NORMAL; - } - - private int minValue(Dimension dimension) { - if (dimension == Dimension.COLUMNS) { - return ProjectSettings.MIN_COLUMNS; - } else if (dimension == Dimension.ROWS) { - return ProjectSettings.MIN_ROWS; - } - return -1; - } - - private int maxValue(Dimension dimension) { - double width = mainWindowScreen.getVisualBounds().getMaxX() - mainWindowScreen.getVisualBounds().getMinX(); - double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY(); - - if (dimension == Dimension.COLUMNS) { - return Math.min((int) (width / ModernDesignSizeHelper.getPadWidth()), ProjectSettings.MAX_COLUMNS); - } else if (dimension == Dimension.ROWS) { - return Math.min((int) ((height - DISPLAY_OFFSET) / ModernDesignSizeHelper.getPadHeight()), ProjectSettings.MAX_ROWS); - } - return -1; - } - private boolean screenValid() { double width = mainWindowScreen.getVisualBounds().getMaxX() - mainWindowScreen.getVisualBounds().getMinX(); double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY(); @@ -200,8 +165,8 @@ public class GeneralTabViewController extends ProjectSettingsTabViewController i @Override public boolean validSettings() { try { - return validate(Integer.parseInt(columnTextField.getText()), Dimension.COLUMNS) == ValidationState.NORMAL && - validate(Integer.parseInt(rowTextField.getText()), Dimension.ROWS) == ValidationState.NORMAL; + return projectSettingsValidator.validate(Integer.parseInt(columnTextField.getText()), Dimension.COLUMNS) == ValidationState.NORMAL && + projectSettingsValidator.validate(Integer.parseInt(rowTextField.getText()), Dimension.ROWS) == ValidationState.NORMAL; } catch (NumberFormatException e) { return false; } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java index 9b2c6957ec97cdbfc6d4050cc662d4330fdbd062..9cab45389cb4dbdc4fa911f4d16fe0c74d5b04c9 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/project/ProjectSettingsViewController.java @@ -35,10 +35,10 @@ public class ProjectSettingsViewController extends NVC implements IProjectSettin @FXML private Button finishButton; - private List<ProjectSettingsTabViewController> tabs = new ArrayList<>(); - private Project project; + private final List<ProjectSettingsTabViewController> tabs = new ArrayList<>(); + private final Project project; - private Runnable onFinish; + private final Runnable onFinish; public ProjectSettingsViewController(Screen currentScreen, Window owner, Project project, Runnable onFinish) { load("view/option/project", "ProjectSettingsView", Localization.getBundle()); diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeSettingsViewController.java similarity index 70% rename from PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java rename to PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeSettingsViewController.java index 14515382904128e4e49c021e0431c02f4a4981fe..ab32efe2dfe4d81fce1b78dd8a21f3475e14a94d 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeSettingsViewController.java @@ -3,14 +3,14 @@ package de.tobias.playpad.viewcontroller.settings; import de.thecodelabs.utils.ui.NVC; import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.Strings; -import de.tobias.playpad.settings.Fade; +import de.tobias.playpad.settings.FadeSettings; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.util.Duration; -public class FadeViewController extends NVC { +public class FadeSettingsViewController extends NVC { @FXML private Slider fadeInSlider; @@ -29,10 +29,12 @@ public class FadeViewController extends NVC { private CheckBox fadeOutPauseCheckBox; @FXML private CheckBox fadeOutStopCheckBox; + @FXML + private CheckBox fadeOutEofCheckBox; - private Fade fade; + private FadeSettings fade; - public FadeViewController() { + public FadeSettingsViewController() { load("view/settings", "FadeView", Localization.getBundle()); } @@ -54,13 +56,14 @@ public class FadeViewController extends NVC { fade.setFadeOut(seconds); }); - fadeInStartCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeInStart(c)); - fadeInPauseCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeInPause(c)); - fadeOutPauseCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeOutPause(c)); - fadeOutStopCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeOutStop(c)); + fadeInStartCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeInStart(newValue)); + fadeInPauseCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeInPause(newValue)); + fadeOutPauseCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutPause(newValue)); + fadeOutStopCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutStop(newValue)); + fadeOutEofCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutEof(newValue)); } - public void setFade(Fade fade) { + public void setFadeSettings(FadeSettings fade) { this.fade = fade; if (fade != null) { @@ -76,6 +79,7 @@ public class FadeViewController extends NVC { fadeInPauseCheckBox.setSelected(fade.isFadeInPause()); fadeOutPauseCheckBox.setSelected(fade.isFadeOutPause()); fadeOutStopCheckBox.setSelected(fade.isFadeOutStop()); + fadeOutEofCheckBox.setSelected(fade.isFadeOutEof()); } } } diff --git a/PlayWall/src/main/resources/lang/_de.properties b/PlayWall/src/main/resources/lang/_de.properties index cfbdf22ed322a5aa4e6fe39868cd2e6956349c89..33029a528b99644493e53bcd9b83e304ae7fd03d 100755 --- a/PlayWall/src/main/resources/lang/_de.properties +++ b/PlayWall/src/main/resources/lang/_de.properties @@ -144,8 +144,8 @@ Error.Plugins.Missing=Es wurden im Projekt Erweiterungen verwendet, welche momen Error.Plugins.Loading=Die Plugins konnten nicht vom geladen werden. Versuchen Sie es sp\u00E4ter erneut. Error.Plugins.Install=Es ist ein Fehler beim installieren des Plugins aufgetreten. Versuche Sie es sp\u00E4ter erneut ({}) # Error - Screen -Error.Screen.TooMuch=Maxiamle Anzahl der Kacheln {} -Error.Screen.TooLess=Minmale Anzahl der Kacheln {} +Error.Screen.TooMuch=Maximale Anzahl der Kacheln {} +Error.Screen.TooLess=Minimale Anzahl der Kacheln {} #Mapper Mapper.Keyboard.Name=Tastatur Mapper.Midi.Name=Midi @@ -158,6 +158,7 @@ Info.Mapper.PressKey=Dr\u00FCcken Sie eine Taste auf dem Ger\u00E4t. UI.Settings.Alert.NewKeyShortcut.Text=Dr\u00FCcken Sie bitte die gew\u00FCnschte Tastenkombination. \nDieses kann aus Buchstaben, Ziffern und/oder den F-Tasten bestehen. # UI - Window - PadSettings UI.Window.PadSettings.General.Title=Allgemein +UI.Window.PadSettings.Playlist.Title=Playlist UI.Window.PadSettings.Player.Title=Player UI.Window.PadSettings.Layout.Title=Layout UI.Window.PadSettings.Trigger.Title=Trigger @@ -208,13 +209,18 @@ UI.Window.Settings.Updates.CurrentVersion={} (Build {}) TriggerPoint.toString={} ({}) Trigger.Cart.Name=Kacheln Trigger.Volume.Name=Lautst\u00E4rke + # TriggerPoint - Enum TriggerPoint.START=Start -TriggerPoint.EOF_STOP=Ende/Stop +TriggerPoint.STOP=Stop +TriggerPoint.EOF=Ende +TriggerPoint.EOF_STATE=Ende (EoF) + # Drag and Drop Mode DnDMode.Replace=Ersetzen DnDMode.Duplicate=Duplizieren DnDMode.Move=Tauschen +DndMode.Playlist=Hinzuf\u00FCgen # Main Layout MainLayout.Desktop=Desktopmodus MainLayout.Touch=Touchmodus diff --git a/PlayWall/src/main/resources/lang/ui_de.properties b/PlayWall/src/main/resources/lang/ui_de.properties index 1876ec12242853a055acb1e74acccedae6ee242f..f3e03f795141542e4f17f58a3af51a51dfca4be3 100755 --- a/PlayWall/src/main/resources/lang/ui_de.properties +++ b/PlayWall/src/main/resources/lang/ui_de.properties @@ -29,6 +29,8 @@ main.menuitem.changelog=Changelog anzeigen... main.menuitem.website=Webseite anzeigen... main.menuitem.fullScreen=Vollbild main.menuitem.searchPad=Kachel suchen... +main.menuitem.addColumn=Spalte rechts hinzuf\u00FCgen +main.menuitem.addRow=Reihe unten hinzuf\u00FCgen main.label.live=Live settings.gen.label.behaviour=Programmstart: settings.gen.checkbox.openLastDocument=Automatisch zuletzt geladenes Projekt \u00F6ffnen. @@ -62,14 +64,16 @@ settings.player.label.modus=Wiedergabemodus: settings.player.checkbox.modus=Mehrere Player gleichzeitig wiedergeben settings.player.label.warning=Warnhinweise: settings.player.label.fade=Ein-/Ausblenden: -settings.player.label.fadeIn=Einblenden (in s): -settings.player.label.fadeOut=Ausblenden (in s): +settings.player.label.fadeIn=Einblenden: +settings.player.label.fadeOut=Ausblenden: settings.player.label.startIn=... nach Start settings.player.label.pauseIn=... bei Pause settings.player.label.pauseOut=... bei Pause -settings.player.label.stopOut=... bei Stop/EoF -settings.player.label.fadeInfo=Wird beim Ein- oder Ausblenden die Dauer auf 0 gesetzt, so findet keine \u00DCberblendung statt. Wenn die Datei zu Ende ist, findet kein Ausblenden statt. +settings.player.label.stopOut=... bei Stop +settings.player.label.eofOut=... bei End of File +settings.player.label.fadeInfo=Wird beim Ein- oder Ausblenden die Dauer auf 0 gesetzt, so findet keine \u00DCberblendung statt. settings.player.label.timeDisplay=Zeitanzeige: +settings.warning.label.time=Warnhinweis ab Restdauer: settings.update.label.current=Installierte Version: settings.update.label.search=Nach Updates suchen: settings.update.label.available=Verf\u00FCgbare Updates: @@ -114,12 +118,15 @@ midi.button.new=\u00C4ndern keyboard.label.key=Taste (Tastatur): keyboard.button.new=\u00C4ndern padSettings.button.delete=L\u00F6schen -padSettings.button.path=Pfad zeigen +padSettings.button.path.show=Im Ordner anzeigen +padSettings.button.path.choose=Pfad w\u00E4hlen +padSettings.gen.label.media=Medien: +padSettings.gen.label.media.empty=<Keine Auswahl> padSettings.gen.label.title=Titel: padSettings.gen.label.volume=Lautst\u00E4rke: padSettings.gen.label.timeDisplay=Zeitanzeige: padSettings.gen.checkbox.customSettings=Eigene Einstellungen -padSettings.checkbox.loop=Wiederholen +padSettings.label.loop=Wiederholen: padSettings.button.finish=Fertig padSettings.player.label.warning=Warnhinweise: padSettings.player.label.cueIn=Intro Dauer (in s): @@ -153,7 +160,7 @@ project.import.label.media=Medien: project.import.label.name=Name: project.import.label.path=Mediendateien: project.import.label.sync= -project.import.checkbox.sync=Cloud-Sychronisation aktivieren +project.import.checkbox.sync=Cloud-Synchronisation aktivieren project.import.checkbox.profile=Profil importieren project.import.checkbox.media=Medien importieren project.import.button.choose=Ordner ausw\u00E4hlen... @@ -178,7 +185,6 @@ profile.button.new=Neu profile.button.delete=L\u00F6schen profile.button.duplicate=Duplizieren profile.button.choose=Profil w\u00E4hlen -warning.label.time=Warnhinweis ab Restdauer: (Sek) print.label.page=Seite: print.button.cancel=Abbrechen print.button.print=Drucken @@ -227,4 +233,14 @@ PathMatchDialog.Table.Column.FileName=Dateiname PathMatchDialog.Table.Column.LocalPath=Lokaler Pfad PathMatchDialog.Table.Column.Action=Aktionen PathMatchDialog.Button.Cancel=Abbrechen -PathMatchDialog.Button.Finish=\u00DCbernehmen \ No newline at end of file +PathMatchDialog.Button.Finish=\u00DCbernehmen + +about.label.headline=\u00DCber PlayWall +about.label.version=Version: +about.label.author=Autor: +about.label.graphics=Grafiken: +about.label.platform=Plattform: +about.label.website=Webseite: +about.label.code=Code: +about.label.libraries=Bibliotheken: +about.label.thanksgiving=Besonderen Dank an die treuen Betatester Stefan und Robert. \ No newline at end of file diff --git a/PlayWall/src/main/resources/view/dialog/About.fxml b/PlayWall/src/main/resources/view/dialog/About.fxml index 45bfe74d2f4dea2fc9760bf608fad319b3e20dc5..952fc777da80ccb8203515f5a4fa3c99fb2cc648 100644 --- a/PlayWall/src/main/resources/view/dialog/About.fxml +++ b/PlayWall/src/main/resources/view/dialog/About.fxml @@ -19,49 +19,56 @@ </ImageView> <VBox alignment="CENTER_LEFT" spacing="7.0"> <children> - <Label styleClass="about-headline" text="Über PlayWall"> + <Label styleClass="about-headline" text="%about.label.headline"> <VBox.margin> <Insets bottom="14.0"/> </VBox.margin> </Label> <HBox spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Version:" textAlignment="RIGHT"/> + <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.version" textAlignment="RIGHT"/> <Label fx:id="versionLabel" text="1.0.0"/> </children> </HBox> <HBox spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Autor:" textAlignment="RIGHT"/> + <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.author" textAlignment="RIGHT"/> <Label fx:id="authorLabel" text="Tobias Ullerich"/> </children> </HBox> <HBox spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Grafiken:" + <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.graphics" textAlignment="RIGHT"/> <Label fx:id="graphicsLabel" text="Robert Goldmann"/> </children> </HBox> + <HBox spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.platform" textAlignment="RIGHT"/> + <Label fx:id="platformLabel" text="controlsfx" wrapText="true"/> + </children> + </HBox> + <HBox fx:id="websiteContainer" spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Webseite" textAlignment="RIGHT"/> + <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.website" textAlignment="RIGHT"/> </children> </HBox> <HBox fx:id="codeContainer" spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="Code:" textAlignment="RIGHT"/> + <Label alignment="CENTER_RIGHT" prefWidth="75.0" text="%about.label.code" textAlignment="RIGHT"/> </children> </HBox> <HBox spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" minWidth="75.0" prefWidth="75.0" text="Libraries:" + <Label alignment="CENTER_RIGHT" minWidth="75.0" prefWidth="75.0" text="%about.label.libraries" textAlignment="RIGHT"/> <Label fx:id="libsLabel" text="controlsfx" wrapText="true"/> </children> </HBox> <Label maxWidth="1.7976931348623157E308" - text="Besonderen Dank an die treuen Betatester Stefan und Robert." wrapText="true"> + text="%about.label.thanksgiving" wrapText="true"> <VBox.margin> <Insets left="89.0"/> </VBox.margin> diff --git a/PlayWall/src/main/resources/view/main/desktop/Header.fxml b/PlayWall/src/main/resources/view/main/desktop/Header.fxml index e18a7a14f0c5dc5fcc12236a2b8e9bd522902747..8383f694f9a847157ff36e78fd1a0264919ff3f3 100644 --- a/PlayWall/src/main/resources/view/main/desktop/Header.fxml +++ b/PlayWall/src/main/resources/view/main/desktop/Header.fxml @@ -126,6 +126,10 @@ </accelerator> </CheckMenuItem> <SeparatorMenuItem mnemonicParsing="false"/> + <MenuItem mnemonicParsing="false" onAction="#addColumnToProject" + text="%main.menuitem.addColumn"/> + <MenuItem mnemonicParsing="false" onAction="#addRowToProject" text="%main.menuitem.addRow"/> + <SeparatorMenuItem mnemonicParsing="false"/> <MenuItem fx:id="searchPadMenuItem" mnemonicParsing="false" onAction="#searchPadHandler" text="%main.menuitem.searchPad"/> <SeparatorMenuItem mnemonicParsing="false"/> diff --git a/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml b/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml index bbbfc204f67a81ad39794136484871888554f9a3..918175e2602fd5ef7166f7392ed40efcbc8838ca 100644 --- a/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml +++ b/PlayWall/src/main/resources/view/option/pad/GeneralTab.fxml @@ -5,44 +5,70 @@ <?import javafx.scene.layout.*?> <VBox spacing="14.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> <children> - <VBox layoutX="14.0" layoutY="14.0" spacing="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" - AnchorPane.topAnchor="14.0"> + <VBox fx:id="mediaRootBox" spacing="14.0"> <children> - <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="14.0" spacing="14.0"> + <HBox alignment="CENTER_LEFT" spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="19.0" prefWidth="150.0" - text="%padSettings.gen.label.title" AnchorPane.leftAnchor="14.0"/> - <TextField fx:id="titleTextField" layoutX="125.0" layoutY="14.0" prefWidth="250.0" - AnchorPane.leftAnchor="127.0"/> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.gen.label.media"/> + <Label fx:id="pathLabel" text="Label" textOverrun="CENTER_ELLIPSIS"/> <VBox HBox.hgrow="ALWAYS"/> - <Button fx:id="deleteButton" mnemonicParsing="false" onAction="#deleteButtonHandler" - text="%padSettings.button.delete"/> - </children> - </HBox> - <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="48.0" spacing="14.0"> - <children> - <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="50.0" prefWidth="150.0" - text="%padSettings.gen.label.volume" AnchorPane.leftAnchor="14.0"/> - <Slider fx:id="volumeSlider" layoutX="122.0" layoutY="54.0" prefWidth="250.0" - showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0" - AnchorPane.leftAnchor="127.0"/> - <VBox HBox.hgrow="ALWAYS"/> - <CheckBox fx:id="repeatCheckBox" mnemonicParsing="false" text="%padSettings.checkbox.loop"/> + <Button fx:id="showPathButton" mnemonicParsing="false" onAction="#showPathButtonHandler" + text="%padSettings.button.path.show"/> </children> </HBox> - <HBox alignment="CENTER_LEFT" layoutX="14.0" layoutY="84.0" spacing="14.0"> + <HBox spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="89.0" prefWidth="150.0" - text="%padSettings.gen.label.timeDisplay" AnchorPane.leftAnchor="14.0"/> - <ComboBox fx:id="timeDisplayComboBox" layoutX="127.0" layoutY="84.0" prefWidth="250.0" - AnchorPane.leftAnchor="127.0"/> - <VBox HBox.hgrow="ALWAYS"/> - <CheckBox fx:id="customTimeDisplayCheckBox" layoutX="406.0" layoutY="88.0" - mnemonicParsing="false" text="%padSettings.gen.checkbox.customSettings"/> + <Button mnemonicParsing="false" onAction="#chooseButtonHandler" + text="%padSettings.button.path.choose"/> + <Button fx:id="deleteButton" mnemonicParsing="false" onAction="#deleteButtonHandler" + text="%padSettings.button.delete"/> </children> + <padding> + <Insets left="164.0"/> + </padding> </HBox> + <Separator prefWidth="200.0"/> </children> </VBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="19.0" prefWidth="150.0" + text="%padSettings.gen.label.title" AnchorPane.leftAnchor="14.0"/> + <TextField fx:id="titleTextField" layoutX="125.0" layoutY="14.0" prefWidth="250.0" + AnchorPane.leftAnchor="127.0"/> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="89.0" prefWidth="150.0" + text="%padSettings.gen.label.timeDisplay" AnchorPane.leftAnchor="14.0"/> + <CheckBox fx:id="customTimeDisplayCheckBox" layoutX="406.0" layoutY="88.0" mnemonicParsing="false" + text="%padSettings.gen.checkbox.customSettings"/> + </children> + </HBox> + <HBox> + <children> + <ComboBox fx:id="timeDisplayComboBox" prefWidth="250.0"/> + </children> + <padding> + <Insets left="164.0"/> + </padding> + </HBox> + <Separator prefWidth="200.0"/> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%padSettings.label.loop"/> + <CheckBox fx:id="repeatCheckBox" mnemonicParsing="false" text="%settings.checkbox.activate"/> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="50.0" prefWidth="150.0" + text="%padSettings.gen.label.volume" AnchorPane.leftAnchor="14.0"/> + <Slider fx:id="volumeSlider" layoutX="122.0" layoutY="54.0" prefWidth="250.0" showTickLabels="true" + showTickMarks="true" snapToTicks="true" value="100.0" AnchorPane.leftAnchor="127.0"/> + </children> + </HBox> </children> <padding> <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/> diff --git a/PlayWall/src/main/resources/view/option/pad/PlaylistTab.fxml b/PlayWall/src/main/resources/view/option/pad/PlaylistTab.fxml new file mode 100644 index 0000000000000000000000000000000000000000..6f25be3e5792c953ce621d4ae05e0ca0db5b8c8f --- /dev/null +++ b/PlayWall/src/main/resources/view/option/pad/PlaylistTab.fxml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.*?> +<?import javafx.scene.layout.*?> +<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="14.0" + xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> + <children> + <VBox spacing="14.0"> + <children> + <ListView fx:id="mediaPathListView" prefWidth="250.0" VBox.vgrow="ALWAYS"/> + <HBox spacing="14.0"> + <children> + <Button fx:id="addButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" + onAction="#onAddHandler" HBox.hgrow="ALWAYS"/> + <Button fx:id="upButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" + onAction="#onUpHandler" HBox.hgrow="ALWAYS"/> + <Button fx:id="downButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" + onAction="#onDownAction" HBox.hgrow="ALWAYS"/> + </children> + </HBox> + </children> + </VBox> + <VBox spacing="14.0"> + <children> + <HBox spacing="14.0"> + <children> + <Label fx:id="pathLabel" textOverrun="CENTER_ELLIPSIS"/> + </children> + </HBox> + <HBox spacing="14.0"> + <children> + <Button fx:id="showFileButton" mnemonicParsing="false" onAction="#onShowFileHandler" + text="%padSettings.button.path.show"/> + <Button fx:id="deleteButton" mnemonicParsing="false" onAction="#onDeleteHandler" + text="%padSettings.button.delete"/> + </children> + </HBox> + </children> + <HBox.margin> + <Insets/> + </HBox.margin> + <padding> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/> + </padding> + </VBox> + </children> + <padding> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/> + </padding> +</HBox> diff --git a/PlayWall/src/main/resources/view/settings/FadeView.fxml b/PlayWall/src/main/resources/view/settings/FadeView.fxml index 41b62886108419caa49806c4e3d2b6b21080ad40..94c88e46b71d49e1d6329457922e436f8c375690 100644 --- a/PlayWall/src/main/resources/view/settings/FadeView.fxml +++ b/PlayWall/src/main/resources/view/settings/FadeView.fxml @@ -51,6 +51,8 @@ text="%settings.player.label.pauseOut"/> <CheckBox fx:id="fadeOutStopCheckBox" mnemonicParsing="false" text="%settings.player.label.stopOut"/> + <CheckBox fx:id="fadeOutEofCheckBox" mnemonicParsing="false" + text="%settings.player.label.eofOut"/> </children> </HBox> </children> diff --git a/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml b/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml index 115ed50e46fbf3987e97541afe8bd1782b246400..27801c98ba344874f9658e81722cee69720e32e0 100644 --- a/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml +++ b/PlayWall/src/main/resources/view/settings/WarningFeedbackSettingsView.fxml @@ -10,7 +10,7 @@ <HBox alignment="CENTER_LEFT" spacing="14.0"> <children> <Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="14.0" prefWidth="150.0" - text="%warning.label.time" textAlignment="RIGHT" wrapText="true" AnchorPane.leftAnchor="14.0"/> + text="%settings.warning.label.time" textAlignment="RIGHT" wrapText="true" AnchorPane.leftAnchor="14.0"/> <Slider fx:id="warningFeedbackTimeSlider" blockIncrement="0.1" majorTickUnit="1.0" max="10.0" minorTickCount="9" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="5.0" HBox.hgrow="ALWAYS"/> diff --git a/PlayWall/src/main/sass/components/dark-list.scss b/PlayWall/src/main/sass/components/dark-list.scss new file mode 100644 index 0000000000000000000000000000000000000000..080f181297955b8f85c6922e539e69705d001645 --- /dev/null +++ b/PlayWall/src/main/sass/components/dark-list.scss @@ -0,0 +1,23 @@ +@import "variables"; + +.dark-list { + -fx-base: rgb(60, 60, 60); + + + .list-cell { + -fx-skin: "com.sun.javafx.scene.control.skin.ListCellSkin"; + -fx-background-color: -fx-base; + -fx-padding: 10px; + -fx-text-fill: #FFFFFF; + -fx-opacity: 1; + + &:filled { + -fx-border-width: 0px 0px 1px 0px; + -fx-border-color: #00000044; + } + + &:odd { + -fx-background-color: -fx-base; + } + } +} \ No newline at end of file diff --git a/PlayWall/src/main/sass/components/list.scss b/PlayWall/src/main/sass/components/list.scss index 1ea1f4bc53dc52ac2bfb04568b503e2d64412451..45bcf857eb7c9f26a7ae5cf1a91c174cf92f75df 100644 --- a/PlayWall/src/main/sass/components/list.scss +++ b/PlayWall/src/main/sass/components/list.scss @@ -1,19 +1,22 @@ @import "variables"; -.dark-list { +.list-view { -fx-base: rgb(60, 60, 60); .list-cell { -fx-skin: "com.sun.javafx.scene.control.skin.ListCellSkin"; -fx-background-color: -fx-base; - -fx-padding: 10px; + -fx-padding: 4px; -fx-text-fill: #FFFFFF; -fx-opacity: 1; &:filled { -fx-border-width: 0px 0px 1px 0px; - -fx-border-color: #00000044; + } + + &:odd:filled { + -fx-background-color: derive(-fx-hover-base, -10%); } } diff --git a/PlayWall/src/main/sass/modern.scss b/PlayWall/src/main/sass/modern.scss index 7046c6af039f7e778946349465614c6b1a8e9f6b..bb353f6186cc4e1be629a85988ceb1745bdb2908 100644 --- a/PlayWall/src/main/sass/modern.scss +++ b/PlayWall/src/main/sass/modern.scss @@ -12,6 +12,7 @@ @import "components/menu"; @import "components/toggle-button"; @import "components/list"; +@import "components/dark-list"; @import "components/progress-bar"; @import "components/dialog"; @import "components/treeview"; diff --git a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala index aec4ccf9145de83e3b41e86038504f1dbf585ea9..b639f9099419bd956a0b420216f9c01568b2c679 100644 --- a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala +++ b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernCartDesignHandlerImpl.scala @@ -4,7 +4,7 @@ import de.thecodelabs.utils.application.ApplicationUtils import de.tobias.playpad.design.modern.model.{ModernCartDesign, ModernGlobalDesign} import de.tobias.playpad.design.modern.{ModernCartDesignHandler, ModernColor} import de.tobias.playpad.pad.content.play.Durationable -import de.tobias.playpad.pad.viewcontroller.IPadViewController +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController import de.tobias.playpad.util.Minifier import de.tobias.playpad.view.PseudoClasses import javafx.util.Duration @@ -47,7 +47,7 @@ class ModernCartDesignHandlerImpl extends ModernCartDesignHandler { expressionParser.parseExpression(string, new TemplateParserContext("${", "}")).getValue(context, classOf[String]) } - override def handleWarning(design: ModernCartDesign, controller: IPadViewController, warning: Duration, globalDesign: ModernGlobalDesign): Unit = { + override def handleWarning(design: ModernCartDesign, controller: AbstractPadViewController, warning: Duration, globalDesign: ModernGlobalDesign): Unit = { if (globalDesign.isWarnAnimation) { val playColor = design.getPlayColor val backgroundColor = design.getBackgroundColor @@ -71,5 +71,5 @@ class ModernCartDesignHandlerImpl extends ModernCartDesignHandler { } } - override def stopWarning(design: ModernCartDesign, controller: IPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller) + override def stopWarning(design: ModernCartDesign, controller: AbstractPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller) } diff --git a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala index ca1ade7277a8ba8e726e3d3b1844575ea2b47f0b..3eea45b74878a931b801b72ea341ce13375be7d2 100644 --- a/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala +++ b/PlayWall/src/main/scala/de/tobias/playpad/design/ModernGlobalDesignHandlerImpl.scala @@ -1,14 +1,11 @@ package de.tobias.playpad.design -import java.nio.file.Files -import java.util.function.Consumer - import de.thecodelabs.utils.application.ApplicationUtils import de.thecodelabs.utils.application.container.PathType import de.tobias.playpad.design.modern.model.{ModernCartDesign, ModernGlobalDesign} import de.tobias.playpad.design.modern.{ModernColor, ModernGlobalDesignHandler} import de.tobias.playpad.pad.content.play.Durationable -import de.tobias.playpad.pad.viewcontroller.IPadViewController +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController import de.tobias.playpad.project.Project import de.tobias.playpad.util.Minifier import de.tobias.playpad.view.{ColorPickerView, PseudoClasses} @@ -22,6 +19,8 @@ import org.springframework.expression.common.TemplateParserContext import org.springframework.expression.spel.standard.SpelExpressionParser import org.springframework.expression.spel.support.StandardEvaluationContext +import java.nio.file.Files +import java.util.function.Consumer import scala.jdk.CollectionConverters._ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with ColorModeHandler { @@ -93,7 +92,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color expressionParser.parseExpression(string, new TemplateParserContext("${", "}")).getValue(context, classOf[String]) } - override def handleWarning(design: ModernGlobalDesign, controller: IPadViewController, warning: Duration): Unit = { + override def handleWarning(design: ModernGlobalDesign, controller: AbstractPadViewController, warning: Duration): Unit = { if (design.isWarnAnimation) { warnAnimation(design, controller, warning) } else { @@ -101,7 +100,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color } } - private def warnAnimation(design: ModernGlobalDesign, controller: IPadViewController, warning: Duration): Unit = { + private def warnAnimation(design: ModernGlobalDesign, controller: AbstractPadViewController, warning: Duration): Unit = { val stopColor = if (design.isFlatDesign) design.getBackgroundColor.toFlatFadeableColor else design.getBackgroundColor.toFadeableColor val playColor = if (design.isFlatDesign) design.getPlayColor.toFlatFadeableColor else design.getPlayColor.toFadeableColor @@ -118,7 +117,7 @@ class ModernGlobalDesignHandlerImpl extends ModernGlobalDesignHandler with Color ModernDesignAnimator.animateWarn(controller, playColor, stopColor, duration) } - override def stopWarning(design: ModernGlobalDesign, controller: IPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller) + override def stopWarning(design: ModernGlobalDesign, controller: AbstractPadViewController): Unit = ModernDesignAnimator.stopAnimation(controller) override def getColorInterface(onSelection: Consumer[DisplayableColor]) = new ColorPickerView(null, ModernColor.values.asInstanceOf[Array[DisplayableColor]], onSelection) diff --git a/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala b/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala index 0d415d80d9cd6c21276953546d84d47c187b770e..7b4d7bacf7a75ff8a6ee3ad8e67cd9a523ed6ffc 100644 --- a/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala +++ b/PlayWall/src/main/scala/de/tobias/playpad/initialize/PluginLoadingTask.scala @@ -1,4 +1,5 @@ package de.tobias.playpad.initialize + import java.io.IOException import java.nio.file.{Path, Paths} @@ -8,6 +9,8 @@ import de.thecodelabs.utils.application.ApplicationUtils import de.thecodelabs.utils.application.container.PathType import de.tobias.playpad.PlayPadImpl import de.tobias.playpad.plugin.ModernPluginManager +import javafx.application.Platform +import org.controlsfx.dialog.ExceptionDialog class PluginLoadingTask extends PlayPadInitializeTask { override def name(): String = "Plugins" @@ -34,6 +37,11 @@ class PluginLoadingTask extends PlayPadInitializeTask { case e: Exception => Logger.error("Unable to load plugins") Logger.error(e) + + Platform.runLater(() => { + val dialog = new ExceptionDialog(e) + dialog.showAndWait() + }) } } diff --git a/PlayWallComponents/pom.xml b/PlayWallComponents/pom.xml index e43eab12219cb2353d7a74809fcba74d74097769..014e6b86de1ac4bfcd3f2e4f69af6c276f1567f9 100644 --- a/PlayWallComponents/pom.xml +++ b/PlayWallComponents/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallDesktop</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWallComponents</artifactId> diff --git a/PlayWallCore/pom.xml b/PlayWallCore/pom.xml index e2f7f2d2f67a8ed6af95a543b09d75d003aaec2c..e88205b628d36d178dd5d0938e379c960fd4d7ea 100644 --- a/PlayWallCore/pom.xml +++ b/PlayWallCore/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallDesktop</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWallCore</artifactId> @@ -29,10 +29,38 @@ <dependency> <groupId>de.thecodelabs</groupId> <artifactId>libPlugins-core</artifactId> + <version>${libPlugins.version}</version> + <classifier>java8</classifier> + <exclusions> + <exclusion> + <groupId>de.thecodelabs</groupId> + <artifactId>libUtils</artifactId> + </exclusion> + <exclusion> + <groupId>de.thecodelabs</groupId> + <artifactId>libStorage</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>de.thecodelabs</groupId> <artifactId>libPlugins-versionizer</artifactId> + <version>${libPlugins.version}</version> + <classifier>java8</classifier> + <exclusions> + <exclusion> + <groupId>de.thecodelabs</groupId> + <artifactId>libUtils</artifactId> + </exclusion> + <exclusion> + <groupId>de.thecodelabs</groupId> + <artifactId>libStorage</artifactId> + </exclusion> + <exclusion> + <groupId>de.thecodelabs.versionizer</groupId> + <artifactId>api</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>de.thecodelabs.versionizer</groupId> diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java index 14d50ffae9ec046ee3cdb1b70fa00542ec112b81..c480828c5d48c0712eab670dbd4a3d2ed05ede89 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java @@ -14,12 +14,15 @@ import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbor import de.tobias.playpad.project.ref.ProjectReference; import de.tobias.playpad.settings.GlobalSettings; import de.tobias.playpad.viewcontroller.main.IMainViewController; +import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController; +import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; import javafx.scene.image.Image; import org.dom4j.DocumentException; import java.io.IOException; import java.util.List; import java.util.function.Consumer; +import java.util.function.Supplier; /** * Hauptfunktionen für Listener und zur Programmsteuerung für Plugins. @@ -138,4 +141,15 @@ public interface PlayPad { UpdateService getUpdateService(); + /* + Settings Views + */ + + void addAdditionalProfileSettingsTab(Supplier<ProfileSettingsTabViewController> tab); + + List<Supplier<ProfileSettingsTabViewController>> getAdditionalProfileSettingsTabs(); + + void addGlobalSettingsTab(Supplier<GlobalSettingsTabViewController> tab); + + List<Supplier<GlobalSettingsTabViewController>> getGlobalSettingsTabs(); } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java b/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java index c8db038e85e1b12b53a665a4fd4995b5c97d30fe..5fb29e5373d451e77f55ec95885e075859ce859e 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/audio/AudioCapability.java @@ -11,10 +11,10 @@ public class AudioCapability { public static final AudioCapability EQUALIZER = new AudioCapability("EQUALIZER", Equalizeable.class); public static final AudioCapability SOUNDCARD = new AudioCapability("SOUNDCARD", Soundcardable.class); - private String nameKey; - private Class<? extends AudioFeature> clazz; + private final String nameKey; + private final Class<? extends AudioFeature> clazz; - private static List<AudioCapability> audioCapabilityList; + private static final List<AudioCapability> audioCapabilityList; static { audioCapabilityList = new ArrayList<>(); diff --git a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java similarity index 90% rename from PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java rename to PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java index d06dbc7a7c6619d5dedb9389c9124e680fe0bb53..91939942841248f3799c5dcf7b6b9e738b5b9831 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/ModernDesignSizeHelper.java @@ -2,7 +2,7 @@ package de.tobias.playpad.design; public class ModernDesignSizeHelper { - private static final double MIN_WIDTH = 165; + private static final double MIN_WIDTH = 140; private static final double MIN_HEIGHT = 115; private ModernDesignSizeHelper() { diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java index 0f34344711461d7ef8a26a175053fc2be731f27b..200ead1fd6e412137370b6393167bb1092adc90d 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernCartDesignHandler.java @@ -2,7 +2,7 @@ package de.tobias.playpad.design.modern; import de.tobias.playpad.design.modern.model.ModernCartDesign; import de.tobias.playpad.design.modern.model.ModernGlobalDesign; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import javafx.util.Duration; public interface ModernCartDesignHandler { @@ -12,9 +12,9 @@ public interface ModernCartDesignHandler { /* * Wird in einem neuen Thread aufgerufen */ - void handleWarning(ModernCartDesign design, IPadViewController controller, Duration warning, ModernGlobalDesign globalDesign); + void handleWarning(ModernCartDesign design, AbstractPadViewController controller, Duration warning, ModernGlobalDesign globalDesign); - default void stopWarning(ModernCartDesign design, IPadViewController controller) { + default void stopWarning(ModernCartDesign design, AbstractPadViewController controller) { } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java index 1c6930dd44d0737bfce2454d18f96ba131652aff..bca1e4aa9cee672852326f41dffe582e115f10e4 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/design/modern/ModernGlobalDesignHandler.java @@ -1,7 +1,7 @@ package de.tobias.playpad.design.modern; import de.tobias.playpad.design.modern.model.ModernGlobalDesign; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.project.Project; import de.tobias.playpad.viewcontroller.main.IMainViewController; import javafx.stage.Stage; @@ -16,8 +16,8 @@ public interface ModernGlobalDesignHandler { /* * Wird in einem neuen Thread aufgerufen */ - void handleWarning(ModernGlobalDesign design, IPadViewController controller, Duration warning); + void handleWarning(ModernGlobalDesign design, AbstractPadViewController controller, Duration warning); - default void stopWarning(ModernGlobalDesign design, IPadViewController controller) { + default void stopWarning(ModernGlobalDesign design, AbstractPadViewController controller) { } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java index 2a0fd4c28cda491ab99634c36b4f2ac2ac967598..cbefe4d2a0c9c95ce5607e7bcd510b7311212ea9 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java @@ -13,7 +13,7 @@ import de.tobias.playpad.pad.listener.trigger.PadTriggerContentListener; import de.tobias.playpad.pad.listener.trigger.PadTriggerDurationListener; import de.tobias.playpad.pad.listener.trigger.PadTriggerStatusListener; import de.tobias.playpad.pad.mediapath.MediaPath; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.project.Project; import de.tobias.playpad.project.ProjectSettings; import de.tobias.playpad.project.page.PadIndex; @@ -78,7 +78,7 @@ public class Pad { // Utils private transient boolean eof; - private transient IPadViewController controller; + private transient AbstractPadViewController controller; private transient Project project; private transient PadUpdateListener padListener; @@ -323,6 +323,10 @@ public class Pad { createMediaPath(path); } else { setPath(path, 0); + + while (mediaPaths.size() > 1) { + mediaPaths.remove(mediaPaths.size() - 1); + } } } @@ -350,6 +354,13 @@ public class Pad { addPath(mediaPath); } + public void addPath(Path path) { + if (mediaPaths.isEmpty()) { + setName(PathUtils.getFilenameWithoutExtension(path.getFileName())); + } + createMediaPath(path); + } + public void addPath(MediaPath mediaPath) { mediaPaths.add(mediaPath); @@ -364,6 +375,7 @@ public class Pad { } public void removePath(MediaPath path) { + getContent().unloadMedia(path); mediaPaths.remove(path); } @@ -374,6 +386,12 @@ public class Pad { } } + public void clearPaths() { + while (!mediaPaths.isEmpty()) { + removePath(mediaPaths.get(0)); + } + } + /** * Get the status of the pad. * @@ -556,11 +574,11 @@ public class Pad { return controller != null; } - public IPadViewController getController() { + public AbstractPadViewController getController() { return controller; } - public void setController(IPadViewController controller) { + public void setController(AbstractPadViewController controller) { this.controller = controller; } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java index f85ef7e4c280e323aebcc5ea805e94a0cd5e5dd2..a935edd4808ae2d9f1c92c99286591e429334cd8 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java @@ -7,7 +7,7 @@ import de.tobias.playpad.project.ref.ProjectReference; import de.tobias.playpad.server.sync.command.CommandManager; import de.tobias.playpad.server.sync.command.Commands; import de.tobias.playpad.server.sync.listener.upstream.PadSettingsUpdateListener; -import de.tobias.playpad.settings.Fade; +import de.tobias.playpad.settings.FadeSettings; import de.tobias.playpad.tigger.Trigger; import de.tobias.playpad.tigger.TriggerPoint; import javafx.beans.binding.BooleanBinding; @@ -31,7 +31,7 @@ public class PadSettings { private DoubleProperty speedProperty = new SimpleDoubleProperty(1.0); private BooleanProperty loopProperty = new SimpleBooleanProperty(false); private ObjectProperty<TimeMode> timeModeProperty = new SimpleObjectProperty<>(); - private ObjectProperty<Fade> fadeProperty = new SimpleObjectProperty<>(); + private ObjectProperty<FadeSettings> fadeProperty = new SimpleObjectProperty<>(); private ObjectProperty<Duration> warningProperty = new SimpleObjectProperty<>(); private ObjectProperty<Duration> cueInProperty = new SimpleObjectProperty<>(); @@ -137,18 +137,18 @@ public class PadSettings { * * @return Fade */ - public Fade getFade() { + public FadeSettings getFade() { if (fadeProperty.isNull().get() && Profile.currentProfile() != null) { return Profile.currentProfile().getProfileSettings().getFade(); } return fadeProperty.get(); } - public void setFade(Fade fade) { + public void setFade(FadeSettings fade) { this.fadeProperty.set(fade); } - public ObjectProperty<Fade> fadeProperty() { + public ObjectProperty<FadeSettings> fadeProperty() { return fadeProperty; } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java index c4a44e1d72c09c8ae1ae8bdd3103f4f68447045f..82e70e61fcdcf7c06ccc037ad6296898528be82b 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java @@ -1,9 +1,10 @@ package de.tobias.playpad.pad; +import de.thecodelabs.logger.Logger; import de.thecodelabs.storage.settings.UserDefaults; import de.tobias.playpad.design.modern.model.ModernCartDesign; import de.tobias.playpad.design.modern.serializer.ModernCartDesignSerializer; -import de.tobias.playpad.settings.Fade; +import de.tobias.playpad.settings.FadeSettings; import de.tobias.playpad.tigger.Trigger; import de.tobias.playpad.tigger.TriggerPoint; import javafx.util.Duration; @@ -50,7 +51,7 @@ public class PadSettingsSerializer { if (settingsElement.element(TIME_MODE_ELEMENT) != null) padSettings.setTimeMode(TimeMode.valueOf(settingsElement.element(TIME_MODE_ELEMENT).getStringValue())); if (settingsElement.element(FADE_ELEMENT) != null) - padSettings.setFade(Fade.load(settingsElement.element(FADE_ELEMENT))); + padSettings.setFade(FadeSettings.load(settingsElement.element(FADE_ELEMENT))); if (settingsElement.element(WARNING_ELEMENT) != null) { try { Duration duration = Duration.valueOf(settingsElement.element(WARNING_ELEMENT).getStringValue().replace(" ", "")); @@ -92,9 +93,13 @@ public class PadSettingsSerializer { Element triggersElement = settingsElement.element(TRIGGERS_ELEMENT); if (triggersElement != null) { for (Element triggerElement : triggersElement.elements(TRIGGER_ELEMENT)) { - Trigger trigger = new Trigger(); - trigger.load(triggerElement); - padSettings.getTriggers().put(trigger.getTriggerPoint(), trigger); + try { + Trigger trigger = new Trigger(); + trigger.load(triggerElement); + padSettings.getTriggers().put(trigger.getTriggerPoint(), trigger); + } catch (IllegalArgumentException e) { + Logger.error(e); + } } } padSettings.updateTrigger(); // Add missing trigger points diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java index bf50a0b447c04de9dd77eadb9a9ee6834ca224bc..6c6d943e9f88741e9891794bf5a68fa3d712a7df 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContent.java @@ -40,6 +40,10 @@ public abstract class PadContent { public abstract boolean isPadLoaded(); + public boolean isPadLoading() { + return false; + } + /** * Load media files. */ @@ -64,6 +68,9 @@ public abstract class PadContent { */ public abstract void unloadMedia(MediaPath mediaPath); + public void reorderMedia() { + } + public abstract void updateVolume(); @Override diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java index 5b34c1653f0bd0836507fc4a7af1a4082c48dbd2..611654dc50e21a013911b95a49e9024936c9b14b 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentFactory.java @@ -2,16 +2,24 @@ package de.tobias.playpad.pad.content; import de.thecodelabs.utils.io.PathUtils; import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.drag.ContentDragOption; import de.tobias.playpad.pad.view.IPadContentView; import de.tobias.playpad.registry.Component; import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; import javafx.scene.layout.Pane; +import java.io.File; import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; -// COMMENT PadContentFactory -public abstract class PadContentFactory extends Component implements Comparable<PadContentFactory> { +public abstract class PadContentFactory extends Component implements ContentDragOption { + + public interface PadContentTypeChooser { + void showOptions(Collection<PadContentFactory> options, Consumer<PadContentFactory> onSelected); + } public PadContentFactory(String type) { super(type); @@ -31,11 +39,6 @@ public abstract class PadContentFactory extends Component implements Comparable< public abstract String[] getSupportedTypes(); - @Override - public int compareTo(PadContentFactory o) { - return getType().compareTo(o.getType()); - } - public static boolean isFileTypeSupported(Path path, PadContentFactory connect) { String extension = PathUtils.getFileExtension(path); for (String ex : connect.getSupportedTypes()) { @@ -45,4 +48,26 @@ public abstract class PadContentFactory extends Component implements Comparable< } return false; } + + // Generic Drag Option for all content types + + @Override + public void handleDrop(Pad currentPad, List<File> files) { + if (currentPad.getContent() == null || !currentPad.getContent().getType().equals(getType())) { + currentPad.setContentType(getType()); + } + + if (currentPad.isPadVisible()) { + currentPad.getController().getView().showBusyView(true); + } + + if (currentPad.getContent() instanceof Playlistable) { + currentPad.clearPaths(); + for (File file : files) { + currentPad.addPath(file.toPath()); + } + } else { + currentPad.setPath(files.get(0).toPath()); + } + } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java index 20e7f45d2ef3f798555acda8d0062c9cad47c5f5..a2614a95f34e7f86294ff57beb87777c818e8bcb 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PadContentRegistry.java @@ -12,17 +12,30 @@ public class PadContentRegistry extends ComponentRegistry<PadContentFactory> { super(name); } - public Set<PadContentFactory> getPadContentConnectsForFile(Path path) throws NoSuchComponentException { - Set<PadContentFactory> connects = new HashSet<>(); + public List<PadContentFactory> getPadContentConnectsForFile(Path paths) throws NoSuchComponentException { + return getPadContentConnectsForFiles(Collections.singletonList(paths)); + } + + public List<PadContentFactory> getPadContentConnectsForFiles(List<Path> paths) throws NoSuchComponentException { + final Set<PadContentFactory> connects = new HashSet<>(); for (String type : getTypes()) { PadContentFactory connect = getFactory(type); for (String extension : connect.getSupportedTypes()) { - if (path.getFileName().toString().toLowerCase().matches("." + extension)) { + if (isExtensionMatchingAllFiles(extension, paths)) { connects.add(connect); } } } - return connects; + return new ArrayList<>(connects); + } + + private boolean isExtensionMatchingAllFiles(String extension, List<Path> paths) { + for (Path path : paths) { + if (!path.getFileName().toString().toLowerCase().matches("." + extension)) { + return false; + } + } + return true; } public String[] getSupportedFileTypes() throws NoSuchComponentException { diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java new file mode 100644 index 0000000000000000000000000000000000000000..1d15d9ad02184a18dc076b6cce7d739f8eba9552 --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java @@ -0,0 +1,16 @@ +package de.tobias.playpad.pad.content; + +import de.tobias.playpad.pad.mediapath.MediaPath; +import javafx.beans.property.IntegerProperty; + +public interface Playlistable { + int getCurrentPlayingMediaIndex(); + + IntegerProperty currentPlayingMediaIndexProperty(); + + boolean hasNext(); + + void next(); + + boolean isLoaded(MediaPath mediaPath); +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/drag/ContentDragOption.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/drag/ContentDragOption.java new file mode 100644 index 0000000000000000000000000000000000000000..8af2e6d82227376781157fc2f9bd46b9073ce53f --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/drag/ContentDragOption.java @@ -0,0 +1,17 @@ +package de.tobias.playpad.pad.drag; + +import de.tobias.playpad.Displayable; +import de.tobias.playpad.pad.Pad; + +import java.io.File; +import java.util.List; + +public interface ContentDragOption extends Displayable, Comparable<ContentDragOption> { + + void handleDrop(Pad currentPad, List<File> files); + + @Override + default int compareTo(ContentDragOption o) { + return displayProperty().get().compareTo(o.displayProperty().get()); + } +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java similarity index 59% rename from PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java rename to PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java index de3828da7264143b30c1c0a49f94b58407d4919a..3923a9e07e8f171ce6b4c2ea714d6ed273136694 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/AbstractFadeController.java @@ -4,19 +4,14 @@ import javafx.animation.Transition; import javafx.util.Duration; /** - * Fade utils. - * - * @author tobias - * @since 6.0.0 + * @since 7.1.0 */ -public class Fade { +public abstract class AbstractFadeController { - private FadeDelegate fadeDelegate; private Transition currentFadeTransition; + protected final FadeControllerDelegate fadeDelegate; - private double velocity = 1; - - public Fade(FadeDelegate fadeDelegate) { + public AbstractFadeController(FadeControllerDelegate fadeDelegate) { this.fadeDelegate = fadeDelegate; } @@ -58,15 +53,7 @@ public class Fade { @Override protected void interpolate(double frac) { - double diff = Math.abs(to - from); - if (from < to) { // Fade In - double fade = fadeInVolumeMultiplier(frac, velocity); - fadeDelegate.onFadeLevelChange(from + fade * diff); - } else { // Fade Out - double fade = fadeOutVolumeMultiplier(frac, velocity); - double newValue = to + fade * diff; - fadeDelegate.onFadeLevelChange(newValue); - } + AbstractFadeController.this.interpolate(this, frac, from, to); } }; currentFadeTransition.setOnFinished(e -> @@ -79,12 +66,5 @@ public class Fade { currentFadeTransition.play(); } - private double fadeInVolumeMultiplier(double time, double velocity) { - return Math.pow(Math.E, velocity * (time - 1)) * time; - } - - private double fadeOutVolumeMultiplier(double time, double velocity) { - return Math.pow(Math.E, -velocity * time) * (1 - time); - } - + protected abstract void interpolate(Transition transition, double frac, double from, double to); } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeDelegate.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeControllerDelegate.java similarity index 87% rename from PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeDelegate.java rename to PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeControllerDelegate.java index 3c7e49855c636f54ebf577814245059aa478524d..b86b6751aa985583cbb1a7c6a38642cff624df06 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeDelegate.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/FadeControllerDelegate.java @@ -6,7 +6,7 @@ package de.tobias.playpad.pad.fade; * @author tobias * @since 6.0.0 */ -public interface FadeDelegate { +public interface FadeControllerDelegate { /** * If the fade level is changed, the delegate performs this method. The faded object should update. diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java index a0f5444cd47f4548471c82f34bad43b006f693dc..7e343f61b3d67bcd1b92703ec14cc2837c259835 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java @@ -7,6 +7,10 @@ public interface Fadeable { void fadeIn(); + default void fadeOut() { + fadeOut(null); + } + void fadeOut(Runnable runnable); boolean isFadeActive(); diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LinearFadeController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LinearFadeController.java new file mode 100644 index 0000000000000000000000000000000000000000..3287ca97157df9df9aac614b43ccd21baa49e94a --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LinearFadeController.java @@ -0,0 +1,26 @@ +package de.tobias.playpad.pad.fade; + +import javafx.animation.Transition; + +/** + * A fade controller implementation, that handles fade scala linear. + * + * @author tobias + * @since 7.1.0 + */ +public class LinearFadeController extends AbstractFadeController { + + public LinearFadeController(FadeControllerDelegate fadeDelegate) { + super(fadeDelegate); + } + + @Override + protected void interpolate(Transition transition, double frac, double from, double to) { + double diff = Math.abs(to - from); + if (from < to) { // Fade In + fadeDelegate.onFadeLevelChange(diff * frac); + } else { // Fade Out + fadeDelegate.onFadeLevelChange(from - (diff * frac)); + } + } +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LogarithmicFadeController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LogarithmicFadeController.java new file mode 100644 index 0000000000000000000000000000000000000000..effbc279899291ec7edb57cea9b6c2b018a686ea --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/LogarithmicFadeController.java @@ -0,0 +1,40 @@ +package de.tobias.playpad.pad.fade; + +import javafx.animation.Transition; + +/** + * A fade controller implementation, that handles fade scala logarithmic for dB. + * + * @author tobias + * @since 6.0.0 + */ +public class LogarithmicFadeController extends AbstractFadeController { + + private static final double VELOCITY = 1; + + public LogarithmicFadeController(FadeControllerDelegate fadeDelegate) { + super(fadeDelegate); + } + + @Override + protected void interpolate(Transition transition, double frac, double from, double to) { + double diff = Math.abs(to - from); + if (from < to) { // Fade In + double fade = computeFadeInMultiplier(frac); + fadeDelegate.onFadeLevelChange(from + fade * diff); + } else { // Fade Out + double fade = computeFadeOutMultiplier(frac); + double newValue = to + fade * diff; + fadeDelegate.onFadeLevelChange(newValue); + } + } + + protected double computeFadeInMultiplier(double frac) { + return Math.pow(Math.E, VELOCITY * (frac - 1)) * frac; + } + + protected double computeFadeOutMultiplier(double frac) { + return Math.pow(Math.E, -VELOCITY * frac) * (1 - frac); + } + +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java index ad414c8d8250053b5a3ec2f279c3b3bfd676e57c..0d7436b3405d2f89be63feebeaf36f55fe213889 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeContentListener.java @@ -7,9 +7,12 @@ import de.tobias.playpad.pad.fade.Fadeable; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; +/** + * Remove end of file fade listener on old pad content and register on new pad content + */ public class PadFadeContentListener implements ChangeListener<PadContent> { - private Pad pad; + private final Pad pad; public PadFadeContentListener(Pad pad) { this.pad = pad; diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java index d9eee37384b5f462200ec2e45f18b1e9b630e56e..214f832d81b61a8449170e5443a83a1fa32c57de 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java @@ -1,6 +1,7 @@ package de.tobias.playpad.pad.fade.listener; import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.pad.content.play.Durationable; import de.tobias.playpad.pad.fade.Fadeable; import javafx.beans.value.ChangeListener; @@ -9,7 +10,7 @@ import javafx.util.Duration; public class PadFadeDurationListener implements ChangeListener<Duration> { - private Pad pad; + private final Pad pad; public PadFadeDurationListener(Pad pad) { this.pad = pad; @@ -17,15 +18,27 @@ public class PadFadeDurationListener implements ChangeListener<Duration> { @Override public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) { - if (pad.getPadSettings().getFade().isFadeOutStop()) { + if (pad.getPadSettings().getFade().isFadeOutEof()) { final Duration fadeDuration = pad.getPadSettings().getFade().getFadeOut(); + // Do not fade out if looping is enabled + if (pad.getPadSettings().isLoop()) { + return; + } + + // Do not fade out if the playlist has a next entry + if (pad.getContent() instanceof Playlistable && ((Playlistable) pad.getContent()).hasNext()) { + return; + } + if (pad.getContent() instanceof Durationable) { - Durationable durationable = (Durationable) pad.getContent(); - if (durationable.getPosition() != null && durationable.getDuration() != null) { - if (durationable.getPosition().add(fadeDuration).greaterThan(durationable.getDuration())) { - fadeOut(); - } + final Durationable durationable = (Durationable) pad.getContent(); + + final Duration position = durationable.getPosition(); + final Duration duration = durationable.getDuration(); + + if (position != null && duration != null && position.add(fadeDuration).greaterThan(duration)) { + fadeOut(); } } } @@ -33,11 +46,10 @@ public class PadFadeDurationListener implements ChangeListener<Duration> { private void fadeOut() { if (pad.getContent() instanceof Fadeable) { - Fadeable fadeable = (Fadeable) pad.getContent(); + final Fadeable fadeable = (Fadeable) pad.getContent(); if (!fadeable.isFadeActive()) { - fadeable.fadeOut(null); + fadeable.fadeOut(); } - } } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java index f0ea7b10a3a826fcc3c1fa104c978859abd93270..5067bad2fd287937bc336e5362a57ad854d7b609 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java @@ -51,7 +51,7 @@ public class PadStatusControlListener implements ChangeListener<PadStatus> { } if (pad.getContent() instanceof Fadeable) { - if (padSettings.getFade().isFadeInStart() || (oldValue == PadStatus.PAUSE && padSettings.getFade().isFadeInPause())) { + if ((oldValue != PadStatus.PAUSE && padSettings.getFade().isFadeInStart()) || (oldValue == PadStatus.PAUSE && padSettings.getFade().isFadeInPause())) { ((Fadeable) pad.getContent()).fadeIn(); } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java index 56eb71c98416217a5bd385a176f4690b084aa86d..834121676c93bc610e53b4ed255d8c06536991ae 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerDurationListener.java @@ -15,29 +15,29 @@ import javafx.util.Duration; public class PadTriggerDurationListener implements ChangeListener<Duration> { - private Pad pad; + private final Pad pad; public PadTriggerDurationListener(Pad pad) { this.pad = pad; } @Override - public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) { + public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration currentTime) { PadContent content = pad.getContent(); if (content instanceof Durationable) { Duration totalDuration = ((Durationable) content).getDuration(); if (totalDuration != null) { - Duration leftTime = totalDuration.subtract(newValue); - IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController(); Profile currentProfile = Profile.currentProfile(); PadSettings padSettings = pad.getPadSettings(); - // Execute Triggers - Trigger startTrigger = padSettings.getTrigger(TriggerPoint.START); - startTrigger.handle(pad, newValue, pad.getProject(), mainViewController, currentProfile); + // Execute Start Triggers + final Trigger startTrigger = padSettings.getTrigger(TriggerPoint.START); + startTrigger.handle(pad, currentTime, pad.getProject(), mainViewController, currentProfile); - Trigger endTrigger = padSettings.getTrigger(TriggerPoint.EOF_STOP); + // Execute End Trigger + final Duration leftTime = totalDuration.subtract(currentTime); + final Trigger endTrigger = padSettings.getTrigger(TriggerPoint.EOF); endTrigger.handle(pad, leftTime, pad.getProject(), mainViewController, currentProfile); } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java index 4517436191751b721ca5cc1ee98b18254fc2a196..94459f05e67e68795cc885c73be904a798fced97 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerStatusListener.java @@ -14,7 +14,7 @@ import javafx.util.Duration; public class PadTriggerStatusListener implements ChangeListener<PadStatus> { - private Pad pad; + private final Pad pad; public PadTriggerStatusListener(Pad pad) { this.pad = pad; @@ -26,12 +26,12 @@ public class PadTriggerStatusListener implements ChangeListener<PadStatus> { PadSettings padSettings = pad.getPadSettings(); // Execute Trigger - if (newValue == PadStatus.PLAY) { // TRIGGER FÜR START + if (newValue == PadStatus.PLAY) { executeTrigger(padSettings.getTriggers().get(TriggerPoint.START)); - } else if (newValue == PadStatus.STOP || (oldValue == PadStatus.PLAY && newValue == PadStatus.READY)) { // TRIGGER FÜR STOP - executeTrigger(padSettings.getTriggers().get(TriggerPoint.EOF_STOP)); - } else if (oldValue == PadStatus.PLAY && newValue == PadStatus.READY && pad.isEof()) { // TRIGGER FÜR EOF - executeTrigger(padSettings.getTriggers().get(TriggerPoint.EOF_STOP)); + } else if (newValue == PadStatus.STOP) { + executeTrigger(padSettings.getTriggers().get(TriggerPoint.STOP)); + } else if (oldValue == PadStatus.PLAY && newValue == PadStatus.READY && pad.isEof()) { + executeTrigger(padSettings.getTriggers().get(TriggerPoint.EOF_STATE)); } } else { pad.setIgnoreTrigger(false); diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java index 2287d7e5ac335b679cbf05975645bbd2e0737b97..64b1eb68e81f22260754f63fd089efdc97fcc12b 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/mediapath/MediaPath.java @@ -19,8 +19,8 @@ import java.util.UUID; */ public class MediaPath { - private UUID id; - private StringProperty fileName; + private final UUID id; + private final StringProperty fileName; private Pad pad; public MediaPath(UUID id, Path path, Pad pad) { diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/preview/PadTextPreview.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/preview/PadTextPreview.java new file mode 100644 index 0000000000000000000000000000000000000000..714792cb845c075ea42c739964af5f1b44ef8fa7 --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/preview/PadTextPreview.java @@ -0,0 +1,40 @@ +package de.tobias.playpad.pad.preview; + +import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.view.IPadContentView; +import javafx.geometry.Pos; +import javafx.scene.Parent; +import javafx.scene.control.Label; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.text.TextAlignment; + +public class PadTextPreview implements IPadContentView { + + private final Label nameLabel; + + public PadTextPreview(Pad pad, Pane parentNode) { + this.nameLabel = new Label(); + this.nameLabel.textProperty().bind(pad.nameProperty()); + + this.nameLabel.setWrapText(true); + this.nameLabel.setAlignment(Pos.CENTER); + this.nameLabel.setTextAlignment(TextAlignment.CENTER); + + this.nameLabel.prefWidthProperty().bind(parentNode.widthProperty()); + this.nameLabel.setMaxHeight(Double.MAX_VALUE); + + VBox.setVgrow(nameLabel, Priority.ALWAYS); + } + + @Override + public Parent getNode() { + return nameLabel; + } + + @Override + public void deInit() { + nameLabel.textProperty().unbind(); + } +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java index c91aa9c7651afdc804ed1e961bf8cf80a1744338..62c5c08f19d5f9dfae5feddd12b5020c1a0e4be6 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadContentView.java @@ -1,6 +1,6 @@ package de.tobias.playpad.pad.view; -import javafx.scene.Node; +import javafx.scene.Parent; // TODO Rename to ContentView @@ -17,7 +17,7 @@ public interface IPadContentView { * * @return GUI Element */ - Node getNode(); + Parent getNode(); /** * Deinitialisiert die View. Hier können mögliche Bindings und Listener entfernt werden. diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java index 51c6ae1b2d7450bf0cd0c191d822bc7f43be7beb..fd2be672d536176e22eb2a1097acca69a666be8e 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/view/IPadView.java @@ -1,9 +1,10 @@ package de.tobias.playpad.pad.view; import de.tobias.playpad.pad.Pad; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.project.page.PadIndex; import javafx.css.PseudoClass; +import javafx.scene.control.Label; import javafx.scene.layout.Pane; /** @@ -33,7 +34,7 @@ public interface IPadView { * * @return ViewController des Pad */ - IPadViewController getViewController(); + AbstractPadViewController getViewController(); /** * Gibt das oberste GUI Element des Pads zurück, welche im MainView verwendet wird. @@ -106,6 +107,8 @@ public interface IPadView { */ void setPlaybarVisible(boolean visible); + Label getPlaylistLabel(); + /** * Fügt die Standart Elemente der PadView hinzu. Die GUI Element sind Abhängig vom Pad, und welchen Content es hat. * diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/AbstractPadViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/AbstractPadViewController.java new file mode 100644 index 0000000000000000000000000000000000000000..e1cbb5372b4768424ceae0a0f1cee17adf0a6527 --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/AbstractPadViewController.java @@ -0,0 +1,71 @@ +package de.tobias.playpad.pad.viewcontroller; + +import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.content.Playlistable; +import de.tobias.playpad.pad.listener.IPadPositionListener; +import de.tobias.playpad.pad.view.IPadView; +import javafx.beans.binding.Bindings; +import javafx.beans.value.ChangeListener; +import javafx.util.Duration; + +/** + * Schnittstellen um mit einem PadViewController zu kommunizieren. + * + * @author tobias + * @since 5.1.0 + */ +public abstract class AbstractPadViewController { + + /** + * Gibt das Pad zurück, welches er verwaltet. (Das Datenmodel) + * + * @return Pad + */ + public abstract Pad getPad(); + + /** + * Gibt die View des Controllers zurück. + * + * @return View + */ + public abstract IPadView getView(); + + /** + * Setzt ein Pad für ein View. Hier werden die Datein mittels ViewController der View bekannt gemacht. + * + * @param pad Neues Pad + */ + public abstract void setupPad(Pad pad); + + /** + * Entfertn des Verbundene Pad von der View. + */ + public abstract void removePad(); + + public abstract void updateTimeLabel(); + + public abstract void updateButtonDisable(); + + public abstract IPadPositionListener getPadPositionListener(); + + public abstract ChangeListener<Duration> getPadDurationListener(); + + public void updatePlaylistLabelBinding(Pad pad) { + if (pad.getContent() instanceof Playlistable) { + final Playlistable content = (Playlistable) pad.getContent(); + getView().getPlaylistLabel().textProperty().bind(Bindings.createStringBinding(() -> { + final int currentPlayingMediaIndex = content.getCurrentPlayingMediaIndex(); + final int totalCount = pad.getPaths().size(); + + if (currentPlayingMediaIndex < 0) { + return "- / " + totalCount; + } else { + return (currentPlayingMediaIndex + 1) + " / " + totalCount; + } + }, content.currentPlayingMediaIndexProperty(), pad.getPaths())); + } else { + getView().getPlaylistLabel().textProperty().unbind(); + getView().getPlaylistLabel().setText(""); + } + } +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/IPadViewController.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/IPadViewController.java deleted file mode 100644 index 6c010518809856910286625e81179040dfcb5c13..0000000000000000000000000000000000000000 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/viewcontroller/IPadViewController.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.tobias.playpad.pad.viewcontroller; - -import de.tobias.playpad.pad.Pad; -import de.tobias.playpad.pad.listener.IPadPositionListener; -import de.tobias.playpad.pad.view.IPadView; -import javafx.beans.value.ChangeListener; -import javafx.util.Duration; - -/** - * Schnittstellen um mit einem PadViewController zu kommunizieren. - * - * @author tobias - * @since 5.1.0 - */ -public interface IPadViewController { - - /** - * Gibt das Pad zurück, welches er verwaltet. (Das Datenmodel) - * - * @return Pad - */ - Pad getPad(); - - /** - * Gibt die View des Controllers zurück. - * - * @return View - */ - IPadView getView(); - - /** - * Setzt ein Pad für ein View. Hier werden die Datein mittels ViewController der View bekannt gemacht. - * - * @param pad Neues Pad - */ - void setupPad(Pad pad); - - /** - * Entfertn des Verbundene Pad von der View. - */ - void removePad(); - - void updateTimeLabel(); - - void updateButtonDisable(); - - IPadPositionListener getPadPositionListener(); - - ChangeListener<Duration> getPadDurationListener(); -} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java index 6a7710569a56500cac8e246091f31523071c9190..40505787027f23d67c65d616d4ab9b889c0b347b 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/plugin/ModernPluginManager.java @@ -2,8 +2,8 @@ package de.tobias.playpad.plugin; import de.thecodelabs.logger.Logger; import de.thecodelabs.plugins.Plugin; -import de.thecodelabs.plugins.PluginArtifact; import de.thecodelabs.plugins.PluginManager; +import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.thecodelabs.utils.application.ApplicationUtils; import de.thecodelabs.utils.application.container.PathType; import de.tobias.playpad.PlayPadPlugin; @@ -25,10 +25,10 @@ public class ModernPluginManager { private static final String PLUGIN_INFO_TXT = "pluginInfo.txt"; - private PluginManager pluginManager; - private Set<Path> deletedPlugins; + private final PluginManager pluginManager; + private final Set<Path> deletedPlugins; - private Set<Module> modules; + private final Set<Module> modules; private static ModernPluginManager instance; @@ -59,14 +59,14 @@ public class ModernPluginManager { public void loadFile(Path path) { if (path.endsWith("classes")) { - pluginManager.addFile(path); + pluginManager.addPluginFile(path); } else { - pluginManager.addFolder(path); + pluginManager.addPluginsOfDirectory(path); } pluginManager.loadPlugins(); // Registriert Funktionen aus Plugin (Module) - for (Plugin p : pluginManager.getPlugins()) { + for (Plugin p : pluginManager.getLoadedPlugins()) { if (p instanceof PlayPadPluginStub) { modules.add(((PlayPadPluginStub) p).getModule()); } 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 4900d036b2a09c0e936c85cbc6e5b52bebea9964..7e50c4dc4866467c22a06cc7372e830b28cd36e7 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/Profile.java @@ -17,9 +17,7 @@ import org.dom4j.DocumentException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; public class Profile { @@ -30,11 +28,13 @@ public class Profile { private static Profile currentProfile; // Settings - private ProfileReference ref; + private final ProfileReference ref; private ProfileSettings profileSettings; private MappingCollection mappings; + private Map<String, Object> customSettings; + /** * Use {@link ProfileReferenceManager#addProfile(ProfileReference)} instead * @@ -44,6 +44,7 @@ public class Profile { this.ref = ref; this.profileSettings = new ProfileSettings(); this.mappings = new MappingCollection(); + this.customSettings = new HashMap<>(); } public static Mapping createMappingWithDefaultActions() { @@ -84,6 +85,14 @@ public class Profile { return profileSettings; } + public Object getCustomSettings(String name) { + return customSettings.get(name); + } + + public void addCustomSettings(String name, Object settings) { + customSettings.put(name, settings); + } + public static Profile load(ProfileReference ref) throws DocumentException, IOException, ProfileNotFoundException { if (ref == null) { throw new IllegalArgumentException("Profile is null"); diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java index a2039d5c3d0b27febb982aff03ae0d02e0bcd698..0b20a03f7e516161a6507e746031236a4c02c80e 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java @@ -8,7 +8,7 @@ import de.tobias.playpad.action.feedback.LightMode; import de.tobias.playpad.design.modern.model.ModernGlobalDesign; import de.tobias.playpad.design.modern.serializer.ModernGlobalDesignSerializer; import de.tobias.playpad.pad.TimeMode; -import de.tobias.playpad.settings.Fade; +import de.tobias.playpad.settings.FadeSettings; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleBooleanProperty; @@ -66,7 +66,7 @@ public class ProfileSettings { private boolean windowAlwaysOnTop = false; @Key - private Fade fade = new Fade(); + private FadeSettings fade = new FadeSettings(); @Key private TimeMode playerTimeDisplayMode = TimeMode.REST; @@ -115,7 +115,7 @@ public class ProfileSettings { return windowAlwaysOnTop; } - public Fade getFade() { + public FadeSettings getFade() { return fade; } @@ -168,7 +168,7 @@ public class ProfileSettings { this.windowAlwaysOnTop = windowAlwaysOnTop; } - public void setFade(Fade fade) { + public void setFade(FadeSettings fade) { this.fade = fade; } @@ -247,7 +247,7 @@ public class ProfileSettings { } if (root.element(FADE_ELEMENT) != null) { - Fade fade = Fade.load(root.element(FADE_ELEMENT)); + FadeSettings fade = FadeSettings.load(root.element(FADE_ELEMENT)); profileSettings.setFade(fade); } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java index bd70c1dfa78b1a6c1b50f3216ef46d1fdc0fb8b2..eedc4bcac8b6176a772fb4b133d1ac2a7d3682f6 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/Project.java @@ -199,7 +199,6 @@ public class Project { notFoundMediaProperty.set(getPads(p -> p.getStatus() == PadStatus.NOT_FOUND).size()); } - @Override public String toString() { return projectReference.getName() + " (" + projectReference.getUuid() + ")"; @@ -281,4 +280,14 @@ public class Project { } return null; } + + public void addColumn() { + settings.setColumns(settings.getColumns() + 1); + pages.forEach(Page::addColumn); + } + + public void addRow() { + settings.setRows(settings.getRows() + 1); + pages.forEach(Page::addRow); + } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsValidator.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..c750722448fe4573b004fead310a1634075d4b83 --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/ProjectSettingsValidator.java @@ -0,0 +1,55 @@ +package de.tobias.playpad.project; + +import de.tobias.playpad.design.ModernDesignSizeHelper; +import javafx.stage.Screen; + +public class ProjectSettingsValidator { + public static final int DISPLAY_OFFSET = 100; + + public enum ValidationState { + NORMAL, + TOO_MUCH, + TOO_LESS + } + + public enum Dimension { + COLUMNS, + ROWS + } + + public ProjectSettingsValidator(Screen mainWindowScreen) { + this.mainWindowScreen = mainWindowScreen; + } + + private final Screen mainWindowScreen; + + public ValidationState validate(int input, Dimension dimension) { + if (input < minValue(dimension)) { + return ValidationState.TOO_LESS; + } else if (input > maxValue(dimension)) { + return ValidationState.TOO_MUCH; + } + return ValidationState.NORMAL; + } + + public int minValue(Dimension dimension) { + if (dimension == Dimension.COLUMNS) { + return ProjectSettings.MIN_COLUMNS; + } else if (dimension == Dimension.ROWS) { + return ProjectSettings.MIN_ROWS; + } + return -1; + } + + public int maxValue(Dimension dimension) { + double width = mainWindowScreen.getVisualBounds().getMaxX() - mainWindowScreen.getVisualBounds().getMinX(); + double height = mainWindowScreen.getVisualBounds().getMaxY() - mainWindowScreen.getVisualBounds().getMinY(); + + if (dimension == Dimension.COLUMNS) { + return Math.min((int) (width / ModernDesignSizeHelper.getPadWidth()), ProjectSettings.MAX_COLUMNS); + } else if (dimension == Dimension.ROWS) { + return Math.min((int) ((height - DISPLAY_OFFSET) / ModernDesignSizeHelper.getPadHeight()), ProjectSettings.MAX_ROWS); + } + return -1; + } +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java index 36d9b1d04b488322ad2d1449ca2025ea244e268b..24f207894be9dc118cf8c20439094e3ab46ce851 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/project/page/Page.java @@ -192,12 +192,17 @@ public class Page { public Pad getPad(int x, int y) { ProjectSettings settings = projectReference.getSettings(); if (x < settings.getColumns() && y < settings.getRows()) { - int id = y * settings.getColumns() + x; - return getPad(id); + int position = getPadPosition(x, y); + return getPad(position); } return null; } + private int getPadPosition(int x, int y) { + ProjectSettings settings = projectReference.getSettings(); + return y * settings.getColumns() + x; + } + /** * Set a pad to a new id. It overwrites the old pad. If the pad argument is null, it only removes the old pad. * @@ -244,6 +249,40 @@ public class Page { pads.removeIf(p -> p.getUuid().equals(uuid)); } + public void addColumn() { + final int columns = getProject().getSettings().getColumns() - 1; + final int rows = getProject().getSettings().getRows(); + + for (int i = 0; i < rows; i++) { + insertPadAndShiftSuccessor(columns, i, rows * columns); + } + } + + public void addRow() { + final int columns = getProject().getSettings().getColumns(); + final int rows = getProject().getSettings().getRows() - 1; + + for (int i = 0; i < columns; i++) { + insertPadAndShiftSuccessor(columns, i, rows * columns); + } + } + + /** + * Insert a pad into given (x, y). Moves all other pads one position ahead. + * + * @param x x + * @param y y + * @param lastPadIndex index of the last pad on the page + */ + private void insertPadAndShiftSuccessor(int x, int y, int lastPadIndex) { + int position = getPadPosition(x, y); + // Going backwards to avoid overwriting the next pad when updating the position of the current one. + for (int i = lastPadIndex - 1; i >= position; i--) { + getPad(i).setPosition(i + 1); + } + getPad(position); + } + @Override public String toString() { return "Page [positionProperty=" + positionProperty + "]"; diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java b/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java index 8c645af1e6e2119ed09f38d44926e05531039ba0..6f42120f2074321041352844c3e100bbb0271ff4 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/registry/Component.java @@ -12,8 +12,8 @@ import javafx.scene.Node; */ public class Component implements Displayable { - private String type; - private StringProperty displayProperty; + private final String type; + private final StringProperty displayProperty; private FontIcon graphics; public Component(String type) { diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java similarity index 80% rename from PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java rename to PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java index 4b30a96f2101acc9136fb218a92918d1edea5a69..d545281b29f8fc47aa42e0619e001a5d69b6073c 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java @@ -14,7 +14,7 @@ import org.dom4j.Element; * @see PadSettings#getFade() * @since 6.0.0 */ -public class Fade { +public class FadeSettings { private Duration fadeIn; private Duration fadeOut; @@ -23,11 +23,12 @@ public class Fade { private boolean fadeInPause; private boolean fadeOutPause; private boolean fadeOutStop; + private boolean fadeOutEof; /** * Erstellt ein neues Fade mit den Default Werten. (Fade Dauer: 0 sec) */ - public Fade() { + public FadeSettings() { this(Duration.ONE, Duration.ONE); } @@ -37,8 +38,8 @@ public class Fade { * @param fadeIn Fade In Dauer * @param fadeOut Fade Out Dauer */ - public Fade(Duration fadeIn, Duration fadeOut) { - this(fadeIn, fadeOut, false, true, true, true); + public FadeSettings(Duration fadeIn, Duration fadeOut) { + this(fadeIn, fadeOut, false, true, true, true, false); } /** @@ -51,13 +52,14 @@ public class Fade { * @param fadeOutPause Fade vor Pause * @param fadeOutStop Fade vor Stop */ - public Fade(Duration fadeIn, Duration fadeOut, boolean fadeInStart, boolean fadeInPause, boolean fadeOutPause, boolean fadeOutStop) { + public FadeSettings(Duration fadeIn, Duration fadeOut, boolean fadeInStart, boolean fadeInPause, boolean fadeOutPause, boolean fadeOutStop, boolean fadeOutEof) { this.fadeIn = fadeIn; this.fadeOut = fadeOut; this.fadeInStart = fadeInStart; this.fadeInPause = fadeInPause; this.fadeOutPause = fadeOutPause; this.fadeOutStop = fadeOutStop; + this.fadeOutEof = fadeOutEof; } public Duration getFadeIn() { @@ -108,6 +110,14 @@ public class Fade { this.fadeOutStop = fadeOutStop; } + public boolean isFadeOutEof() { + return fadeOutEof; + } + + public void setFadeOutEof(boolean fadeOutEof) { + this.fadeOutEof = fadeOutEof; + } + /* * Serialize */ @@ -116,6 +126,7 @@ public class Fade { private static final String FADE_IN = "FadeIn"; private static final String ON_STOP_ATTR = "onStop"; + private static final String ON_EOF_ATTR = "onEof"; private static final String ON_PAUSE_ATTR = "onPause"; private static final String ON_START_ATTR = "onStart"; @@ -129,16 +140,17 @@ public class Fade { fadeOutElement.addText(fadeOut.toString()); fadeOutElement.addAttribute(ON_PAUSE_ATTR, String.valueOf(fadeOutPause)); fadeOutElement.addAttribute(ON_STOP_ATTR, String.valueOf(fadeOutStop)); + fadeOutElement.addAttribute(ON_EOF_ATTR, String.valueOf(fadeOutEof)); } - public static Fade load(Element container) { + public static FadeSettings load(Element container) { try { - Fade fade = new Fade(); + FadeSettings fade = new FadeSettings(); Element fadeInElement = container.element(FADE_IN); - if (fadeInElement.attributeValue(ON_PAUSE_ATTR) != null) + if (fadeInElement.attributeValue(ON_START_ATTR) != null) fade.setFadeInStart(Boolean.parseBoolean(fadeInElement.attributeValue(ON_START_ATTR))); - if (fadeInElement.attributeValue(ON_STOP_ATTR) != null) + if (fadeInElement.attributeValue(ON_PAUSE_ATTR) != null) fade.setFadeInPause(Boolean.parseBoolean(fadeInElement.attributeValue(ON_PAUSE_ATTR))); fade.setFadeIn(Duration.valueOf(fadeInElement.getStringValue().replace(" ", ""))); @@ -147,6 +159,8 @@ public class Fade { fade.setFadeOutPause(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_PAUSE_ATTR))); if (fadeOutElement.attributeValue(ON_STOP_ATTR) != null) fade.setFadeOutStop(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_STOP_ATTR))); + if (fadeOutElement.attributeValue(ON_EOF_ATTR) != null) + fade.setFadeOutEof(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_EOF_ATTR))); fade.setFadeOut(Duration.valueOf(fadeOutElement.getStringValue().replace(" ", ""))); return fade; } catch (Exception e) { diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java index 2f65d793a5a5e39a17060ed14d72f6d2b0cfe773..ba284a16cccbe20166ac9c86c41fbb9a822dc5e5 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java @@ -71,7 +71,7 @@ public class Trigger { try { triggerPoint = TriggerPoint.valueOf(element.attributeValue(POINT_ATTR)); } catch (Exception e) { - Logger.error(e); + throw new IllegalArgumentException("Trigger Point " + element.attributeValue(POINT_ATTR) + " not exists"); } for (Element itemElement : element.elements(ITEM_ELEMENT)) { @@ -104,18 +104,22 @@ public class Trigger { return triggerPoint.name() + " (" + items.size() + ")"; } - public void handle(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile) { + public void handle(Pad pad, Duration currentDuration, Project project, IMainViewController mainViewController, Profile currentProfile) { for (TriggerItem item : items) { if (triggerPoint == TriggerPoint.START) { - handleStartPoint(pad, duration, project, mainViewController, currentProfile, item); - } else if ((triggerPoint == TriggerPoint.EOF_STOP)) { - handleEndPoint(pad, duration, project, mainViewController, currentProfile, item); + handleStartPoint(pad, currentDuration, project, mainViewController, currentProfile, item); + } else if (triggerPoint == TriggerPoint.STOP) { + handleEndPoint(pad, currentDuration, project, mainViewController, currentProfile, item); + } else if (triggerPoint == TriggerPoint.EOF) { + handleEndPoint(pad, currentDuration, project, mainViewController, currentProfile, item); + } else if (triggerPoint == TriggerPoint.EOF_STATE) { + item.performAction(pad, project, mainViewController, currentProfile); } } } private void handleEndPoint(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile, TriggerItem item) { - // Wenn Trigger noch nicht gespiel wurde (null) und Zeit größer ist als gesetzte Zeit (oder 0) + // Wenn Trigger noch nicht gespielt wurde (null) und Zeit größer ist als gesetzte Zeit (oder 0) if (item.getPerformedAt() == null && (item.getDurationFromPoint().greaterThan(duration) || duration.equals(Duration.ZERO))) { item.performAction(pad, project, mainViewController, currentProfile); item.setPerformedAt(duration); @@ -126,7 +130,7 @@ public class Trigger { private void handleStartPoint(Pad pad, Duration duration, Project project, IMainViewController mainViewController, Profile currentProfile, TriggerItem item) { if (pad.getStatus() == PadStatus.PLAY) { - // Mitten drin, wenn die Zeit die gepsiel wurde größer ist als die gesetzte und noch der Trigger noch nicht ausgeführt + // Mitten drin, wenn die Zeit die gespielt wurde größer ist als die gesetzte und noch der Trigger noch nicht ausgeführt // wurde (null) if ((item.getPerformedAt() == null && item.getDurationFromPoint().lessThan(duration)) // Wenn der Trigger am Anfang ist diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java index 9590d921a24a86a84453ff83acbcce147cb69c91..118dc56017638413688062a0bd742f59ffc05dec 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerItemFactory.java @@ -2,6 +2,7 @@ package de.tobias.playpad.tigger; import de.thecodelabs.utils.ui.NVC; import de.tobias.playpad.registry.Component; +import de.tobias.playpad.viewcontroller.main.IMainViewController; public abstract class TriggerItemFactory extends Component { @@ -11,6 +12,6 @@ public abstract class TriggerItemFactory extends Component { public abstract TriggerItem newInstance(Trigger trigger); - public abstract NVC getSettingsController(TriggerItem item); + public abstract NVC getSettingsController(TriggerItem item, IMainViewController mainViewController); } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java index 30730e5b61922655bbd49ab38a8b6f735967738a..4f1390d9e6ebda63f92fe7647d00ae0fe759df2c 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java @@ -2,7 +2,21 @@ package de.tobias.playpad.tigger; public enum TriggerPoint { - START, - EOF_STOP + START(true), + STOP(false), + EOF(true), + EOF_STATE(false); + /** + * Defines if a trigger can be run after, before a certain event. + */ + private final boolean timeAppendable; + + TriggerPoint(boolean timeAppendable) { + this.timeAppendable = timeAppendable; + } + + public boolean isTimeAppendable() { + return timeAppendable; + } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java index f7cf7399636ec98235da323c9e75f1c23a0631f1..88039dcb374505f9f913fc81b4d72d5c20fdfd63 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/MainLayoutFactory.java @@ -1,7 +1,7 @@ package de.tobias.playpad.view.main; import de.tobias.playpad.pad.view.IPadView; -import de.tobias.playpad.pad.viewcontroller.IPadViewController; +import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; import de.tobias.playpad.registry.Component; import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.main.MenuToolbarViewController; @@ -31,7 +31,7 @@ public abstract class MainLayoutFactory extends Component { * * @return Pad * @see IPadView notwendige Methoden für ein Pad - * @see IPadViewController ViewController zum Pad + * @see AbstractPadViewController ViewController zum Pad */ public abstract IPadView createPadView(); diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java index 10bba54fef944f0b3dd71fe6a651bf867b4a54f7..2e16c3cb79abe3471b9e6c0c185852f9efb87816 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/view/main/ProjectPreviewView.java @@ -6,6 +6,9 @@ import de.tobias.playpad.project.Project; import de.tobias.playpad.project.page.Page; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Node; import javafx.scene.control.Pagination; import javafx.scene.control.ToggleButton; import javafx.scene.control.Tooltip; @@ -15,31 +18,36 @@ import java.util.List; public class ProjectPreviewView extends Pagination { - private Project project; + private final Project project; + private final ObservableList<Pad> selected; - private ObservableList<Pad> selected; - - public ProjectPreviewView(Project project, List<Pad> preSelect) { + public ProjectPreviewView(Project project, List<Pad> preSelect, int initialPage) { super(project.getPages().size()); this.project = project; this.selected = FXCollections.observableArrayList(preSelect); - setPageFactory(index -> { - GridPane gridPane = new GridPane(); - gridPane.setHgap(7); - gridPane.setVgap(7); + setCurrentPageIndex(initialPage); + setPageFactory(this::getPageNode); + } + + private Node getPageNode(int index) { + GridPane gridPane = new GridPane(); + gridPane.setHgap(7); + gridPane.setVgap(7); + gridPane.setAlignment(Pos.CENTER); - Page page = project.getPage(index); - for (int x = 0; x < project.getSettings().getColumns(); x++) { - for (int y = 0; y < project.getSettings().getRows(); y++) { - final Pad pad = page.getPad(x, y); - ToggleButton toggleButton = getToggleButton(preSelect, pad); + gridPane.setPadding(new Insets(0, 0, 7, 0)); - gridPane.add(toggleButton, x, y); - } + final Page page = project.getPage(index); + for (int x = 0; x < project.getSettings().getColumns(); x++) { + for (int y = 0; y < project.getSettings().getRows(); y++) { + final Pad pad = page.getPad(x, y); + ToggleButton toggleButton = getToggleButton(selected, pad); + + gridPane.add(toggleButton, x, y); } - return gridPane; - }); + } + return gridPane; } private ToggleButton getToggleButton(List<Pad> preSelect, Pad pad) { diff --git a/PlayWallPlugins/PlayWallPluginAwake/pom.xml b/PlayWallPlugins/PlayWallPluginAwake/pom.xml index e8e455aa952bf3696847c5cb239d45bd1817ecc4..ab7412fa66fc468da72597b261d0699a109f60ce 100644 --- a/PlayWallPlugins/PlayWallPluginAwake/pom.xml +++ b/PlayWallPlugins/PlayWallPluginAwake/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallPlugins</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWallPluginAwake</artifactId> diff --git a/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java index aa546a3218fa87200ddeb5090f9b0e7328200391..4c47a3b672cc4a81d24a34c3aa47bb684d19961b 100644 --- a/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java +++ b/PlayWallPlugins/PlayWallPluginAwake/src/main/java/de/tobias/playpad/awakeplugin/AwakePluginImpl.java @@ -1,8 +1,8 @@ package de.tobias.playpad.awakeplugin; import de.thecodelabs.logger.Logger; -import de.thecodelabs.plugins.PluginArtifact; import de.thecodelabs.plugins.PluginDescriptor; +import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.thecodelabs.utils.application.system.NativeApplication; import de.thecodelabs.utils.ui.icon.FontAwesomeType; import de.thecodelabs.utils.ui.icon.FontIcon; diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/pom.xml b/PlayWallPlugins/PlayWallPluginContentPlayer/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..c63bba0cd0555730de475e6b1aa9b82dab82b458 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/pom.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>PlayWallPlugins</artifactId> + <groupId>de.tobias.playpad</groupId> + <version>7.1.0</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>PlayWallPluginContentPlayer</artifactId> + + <properties> + <project.outputDirectory>../../build/${project.version}</project.outputDirectory> + <project.artifactName>${project.artifactId}-v${project.version}</project.artifactName> + </properties> + + <dependencies> + <dependency> + <groupId>de.tobias.playpad</groupId> + <artifactId>PlayWallCore</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>de.thecodelabs</groupId> + <artifactId>versionizer-maven-plugin</artifactId> + <version>${versionizer-maven-plugin.version}</version> + <configuration> + <resourceFile>plugin.yml</resourceFile> + </configuration> + <executions> + <execution> + <id>resource-fill</id> + <goals> + <goal>resource-fill</goal> + </goals> + <phase>compile</phase> + </execution> + </executions> + </plugin> + + <!--Scala Plugin--> + <plugin> + <groupId>net.alchim31.maven</groupId> + <artifactId>scala-maven-plugin</artifactId> + <executions> + <execution> + <id>scala-compile-first</id> + <phase>process-resources</phase> + <goals> + <goal>add-source</goal> + <goal>compile</goal> + </goals> + </execution> + <execution> + <id>scala-test-compile</id> + <phase>process-test-resources</phase> + <goals> + <goal>testCompile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.1.1</version> + <configuration> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + <outputDirectory>${project.outputDirectory}</outputDirectory> + <finalName>${project.artifactName}</finalName> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>assemble-all</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <distributionManagement> + <repository> + <id>release</id> + <name>TheCodeLabs-releases</name> + <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url> + </repository> + <snapshotRepository> + <id>snapshots</id> + <name>TheCodeLabs-snapshots</name> + <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url> + </snapshotRepository> + </distributionManagement> + + <repositories> + <repository> + <id>release</id> + <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-release</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + <repository> + <id>snapshots</id> + <url>https://maven.thecodelabs.de/artifactory/TheCodeLabs-snapshots</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + +</project> \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/PadContent.xml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/PadContent.xml new file mode 100644 index 0000000000000000000000000000000000000000..32da3b2a4dcc9e49a66cbac1a9bb23b5528c2a53 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/PadContent.xml @@ -0,0 +1,6 @@ +<Actions> + <Component id="content_player" name="plugin.content.Player.name" icon="MONITOR_MULTIPLE" + class="de.thecodelabs.utils.ui.icon.MaterialDesignIcon" + size="30">de.tobias.playpad.plugin.content.pad.ContentPlayerPadContentFactory + </Component> +</Actions> \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base.properties b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base.properties new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base_de.properties b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..f349884fe1a09c06e16bd93793838ac6430afbb8 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/lang/base_de.properties @@ -0,0 +1,17 @@ +plugin.content.Player.name=Content Player + +plugin.content.player.settings=Content Player +plugin.content.player.settings.name=Name: +plugin.content.player.settings.x=X: +plugin.content.player.settings.y=Y: +plugin.content.player.settings.width=Breite: +plugin.content.player.settings.height=H\u00F6he: +plugin.content.player.settings.add=Hinzuf\u00FCgen +plugin.content.player.settings.remove=L\u00F6schen +plugin.content.player.settings.default_name=Zone + +plugin.content.pad.settings.lastFrame.label=Letztes Frame halten +plugin.content.pad.settings.lastFrame.checkbox=Aktiv +plugin.content.pad.settings.zone=Zonen +plugin.content.pad.settings.zone.addAll=Alle anw\u00E4hlen +plugin.content.pad.settings.zone.removeAll=Alle abw\u00E4hlen diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/plugin.yml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/plugin.yml new file mode 100644 index 0000000000000000000000000000000000000000..70a18e12c0441bf59f78ee543ce885c15034c894 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +main: "de.tobias.playpad.plugin.content.ContentPluginMain" +name: "ContentPlugin" +artifactId: "${pom.artifactId}" +groupId: "${pom.groupId}" +version: "${pom.version}" +build: 1 diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ContentPadSettings.fxml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ContentPadSettings.fxml new file mode 100644 index 0000000000000000000000000000000000000000..bfd7033978d027d36f881bb9957b7c158056cb89 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ContentPadSettings.fxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.*?> +<?import javafx.scene.layout.*?> +<?import org.controlsfx.control.CheckListView?> +<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> + <children> + <VBox layoutX="237.0" layoutY="-18.0" spacing="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.pad.settings.lastFrame.label" /> + <CheckBox fx:id="lastFrameCheckbox" mnemonicParsing="false" text="%plugin.content.pad.settings.lastFrame.checkbox" /> + </children> + </HBox> + <HBox spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.pad.settings.zone" /> + <CheckListView fx:id="zoneListView" prefHeight="150.0" /> + <VBox spacing="14.0"> + <children> + <Button fx:id="addAllZonesButton" onAction="#onAddAllZonesHandler" mnemonicParsing="false" text="%plugin.content.pad.settings.zone.addAll" /> + <Button fx:id="removeAllZonesButton" onAction="#onRemoveAllZonesHandler" mnemonicParsing="false" text="%plugin.content.pad.settings.zone.removeAll" /> + </children> + </VBox> + </children> + </HBox> + </children> + <padding> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" /> + </padding> + </VBox> + </children> +</AnchorPane> diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/PlayerView.fxml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/PlayerView.fxml new file mode 100644 index 0000000000000000000000000000000000000000..3428c4ea773b6b4a8e3838f54f9373d77107c718 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/PlayerView.fxml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> + + +<?import javafx.scene.layout.Pane?> +<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" /> diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ZoneSettings.fxml b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ZoneSettings.fxml new file mode 100644 index 0000000000000000000000000000000000000000..64036902597eb22c98b1b9881eee56e6aad82a12 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/resources/view/ZoneSettings.fxml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import de.thecodelabs.utils.ui.scene.input.NumberTextField?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.*?> +<?import javafx.scene.layout.*?> +<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> + <children> + <VBox layoutY="345.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <ListView fx:id="listView" prefWidth="250.0" VBox.vgrow="ALWAYS" /> + <HBox prefHeight="30.0" prefWidth="200.0" spacing="14.0"> + <children> + <Button fx:id="addButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#onAddHandle" text="%plugin.content.player.settings.add" HBox.hgrow="ALWAYS" /> + <Button fx:id="removeButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#onRemoveHandle" text="%plugin.content.player.settings.remove" HBox.hgrow="ALWAYS" /> + </children> + <padding> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" /> + </padding> + </HBox> + </children> + </VBox> + <VBox layoutX="200.0" prefHeight="400.0" prefWidth="401.0" spacing="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="250.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.name" /> + <TextField fx:id="nameTextField" /> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.x" /> + <NumberTextField fx:id="xTextField" /> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.y" /> + <NumberTextField fx:id="yTextField" /> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.width" /> + <NumberTextField fx:id="widthTextField" /> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%plugin.content.player.settings.height" /> + <NumberTextField fx:id="heightTextField" /> + </children> + </HBox> + </children> + <padding> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" /> + </padding> + </VBox> + </children> +</AnchorPane> diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/ContentPluginMain.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/ContentPluginMain.scala new file mode 100644 index 0000000000000000000000000000000000000000..2756703ed75e039767b9c5ba3e09324f46653b98 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/ContentPluginMain.scala @@ -0,0 +1,60 @@ +package de.tobias.playpad.plugin.content + +import de.thecodelabs.plugins.PluginDescriptor +import de.thecodelabs.storage.settings.{Storage, StorageTypes} +import de.thecodelabs.utils.util.Localization +import de.tobias.playpad.PlayPadPlugin +import de.tobias.playpad.plugin.content.player.ContentPlayerViewController +import de.tobias.playpad.plugin.content.settings.{ZoneConfiguration, ZoneSettingsViewController} +import de.tobias.playpad.plugin.{Module, PlayPadPluginStub, SettingsListener} +import de.tobias.playpad.profile.{Profile, ProfileListener} +import javafx.application.Platform + +class ContentPluginMain extends PlayPadPluginStub with SettingsListener with ProfileListener { + + private var module: Module = _ + + override def startup(descriptor: PluginDescriptor): Unit = { + module = new Module(descriptor.getName, descriptor.getArtifactId) + + val localization = Localization.loadBundle("lang/base", getClass.getClassLoader) + Localization.addResourceBundle(localization) + + PlayPadPlugin.getRegistries.getPadContents.loadComponentsFromFile("PadContent.xml", getClass.getClassLoader, module, localization) + PlayPadPlugin.getInstance().addAdditionalProfileSettingsTab(() => new ZoneSettingsViewController) + + PlayPadPlugin.getInstance().addSettingsListener(this) + Profile.registerListener(this) + } + + override def shutdown(): Unit = { + ContentPluginMain.playerViewController.getStageContainer.ifPresent(container => container.forceClose()) + } + + override def getModule: Module = module + + override def onLoad(profile: Profile): Unit = { + val path = profile.getRef.getCustomFilePath("Zones.json") + val zoneConfiguration = Storage.load(path, StorageTypes.JSON, classOf[ZoneConfiguration]) + profile.addCustomSettings(ContentPluginMain.zoneConfigurationKey, zoneConfiguration) + } + + override def onSave(profile: Profile): Unit = { + val path = profile.getRef.getCustomFilePath("Zones.json") + val zoneConfigurationObject = profile.getCustomSettings(ContentPluginMain.zoneConfigurationKey) + if (zoneConfigurationObject != null) { + Storage.save(path, StorageTypes.JSON, zoneConfigurationObject) + } + } + + override def reloadSettings(oldProfile: Profile, currentProfile: Profile): Unit = { + val zoneConfiguration = currentProfile.getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration] + Platform.runLater(() => ContentPluginMain.playerViewController.configurePlayers(zoneConfiguration)) + } +} + +object ContentPluginMain { + lazy val playerViewController: ContentPlayerViewController = new ContentPlayerViewController + + val zoneConfigurationKey = "ZoneConfiguration" +} \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala new file mode 100644 index 0000000000000000000000000000000000000000..3c298dcbfb2fcf167ef3d682cf03bb71c3d6c9da --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala @@ -0,0 +1,57 @@ +package de.tobias.playpad.plugin.content.pad + +import de.tobias.playpad.pad.PadStatus +import de.tobias.playpad.pad.mediapath.MediaPath +import de.tobias.playpad.plugin.content.ContentPluginMain +import de.tobias.playpad.plugin.content.util._ +import javafx.scene.media.MediaPlayer +import javafx.util.Duration + +class ContentPlayerMediaContainer(val content: ContentPlayerPadContent, val path: MediaPath, val mediaPlayer: MediaPlayer) { + def play(): Unit = { + content._durationProperty.bind(mediaPlayer.totalDurationProperty()) + content._positionProperty.bind(mediaPlayer.currentTimeProperty()) + ContentPluginMain.playerViewController.showMediaPlayer(content.getPad.getPadIndex, mediaPlayer, content.getSelectedZones) + + mediaPlayer.seek(Duration.ZERO) + mediaPlayer.play() + + content.getPad.setEof(false) + content.currentPlayingMediaIndexProperty().set(content.getMediaPlayers.indexOf(this)) + } + + def resume(): Unit = { + mediaPlayer.play() + } + + def pause(): Unit = { + mediaPlayer.pause() + } + + def next(): Unit = { + stop() + + val players = content.getMediaPlayers + val index = players.indexOf(this) + content.currentPlayingMediaIndexProperty().set(index) + + if (index + 1 < players.length) { + players(index + 1).play() + } else if (content.getPad.getPadSettings.isLoop) { + players.head.play() + } else { + content.getPad.setStatus(PadStatus.STOP) + } + } + + def stop(): Unit = { + mediaPlayer.stop() + ContentPluginMain.playerViewController.disconnectMediaPlayer(mediaPlayer, content.getSelectedZones) + + content._durationProperty.bind(content.totalDurationBinding()) + content._positionProperty.unbind() + content._positionProperty.set(Duration.ZERO) + } + + override def toString: String = f"MediaPlayerContainer: $path" +} \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala new file mode 100644 index 0000000000000000000000000000000000000000..c1db519a17b8119362c64e7385ba26d91f2b9a40 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala @@ -0,0 +1,322 @@ +package de.tobias.playpad.plugin.content.pad + +import de.thecodelabs.logger.Logger +import de.tobias.playpad.pad.content.play.{Durationable, Pauseable} +import de.tobias.playpad.pad.content.{PadContent, Playlistable} +import de.tobias.playpad.pad.fade.{Fadeable, LinearFadeController} +import de.tobias.playpad.pad.mediapath.MediaPath +import de.tobias.playpad.pad.{Pad, PadStatus} +import de.tobias.playpad.plugin.content.ContentPluginMain +import de.tobias.playpad.plugin.content.settings.{Zone, ZoneConfiguration} +import de.tobias.playpad.plugin.content.util._ +import de.tobias.playpad.profile.Profile +import de.tobias.playpad.volume.VolumeManager +import javafx.application.Platform +import javafx.beans.binding.{Bindings, ObjectBinding} +import javafx.beans.property._ +import javafx.collections.{FXCollections, ObservableList} +import javafx.scene.media.{Media, MediaPlayer} +import javafx.util.Duration + +import java.nio.file.Files +import java.util +import java.util.Optional +import java.util.stream.Collectors +import scala.jdk.CollectionConverters._ + +class ContentPlayerPadContent(val pad: Pad, val `type`: String) extends PadContent(pad) with Pauseable with Durationable with Playlistable with Fadeable { + + private val mediaPlayers: ObservableList[ContentPlayerMediaContainer] = FXCollections.observableArrayList() + private val currentRunningIndexProperty: IntegerProperty = new SimpleIntegerProperty(-1) + + private[pad] val _durationProperty = new SimpleObjectProperty[Duration] + private[pad] val _positionProperty = new SimpleObjectProperty[Duration] + + private var showingLastFrame: Boolean = false + private var isPause: Boolean = false + + private val fadeController = new LinearFadeController(value => { + if (getCurrentPlayingMediaIndex >= 0) { + ContentPluginMain.playerViewController + .setFadeValue(mediaPlayers(getCurrentPlayingMediaIndex).mediaPlayer, getSelectedZones, value) + } + }) + + override def getType: String = `type` + + override def getCurrentPlayingMediaIndex: Int = currentRunningIndexProperty.get() + + override def currentPlayingMediaIndexProperty(): IntegerProperty = currentRunningIndexProperty + + def getMediaPlayers: ObservableList[ContentPlayerMediaContainer] = mediaPlayers + + override def hasNext: Boolean = getCurrentPlayingMediaIndex + 1 < mediaPlayers.length + + /* + Control Methods + */ + + override def play(): Unit = { + if (isPause) { + mediaPlayers(getCurrentPlayingMediaIndex).resume() + } else { + ContentPluginMain.playerViewController.addActivePadToList(getPad.getPadIndex, getSelectedZones) + + getPad.setEof(false) + mediaPlayers.head.play() + } + showingLastFrame = false + isPause = false + } + + override def pause(): Unit = { + isPause = true + mediaPlayers(getCurrentPlayingMediaIndex).pause() + } + + override def next(): Unit = { + mediaPlayers(getCurrentPlayingMediaIndex).next() + } + + override def stop(): Boolean = { + isPause = false + mediaPlayers(getCurrentPlayingMediaIndex).stop() + currentRunningIndexProperty.set(-1) + + ContentPluginMain.playerViewController.removeActivePadFromList(getPad.getPadIndex, getSelectedZones) + true + } + + def onEof(): Unit = { + if (isFadeActive) { + ContentPluginMain.playerViewController.removeActivePadFromList(getPad.getPadIndex, getSelectedZones) + return + } + + if (shouldShowLastFrame() && !showingLastFrame // Only is settings is enabled and not already in last frame state + && !pad.getPadSettings.isLoop // Only go to last frame state, is looping is disabled + ) { + getPad.setStatus(PadStatus.PAUSE) + showingLastFrame = true + return + } + + showingLastFrame = false + + if (getPad.isEof) { + mediaPlayers(getCurrentPlayingMediaIndex).next() + return + } + } + + /* + Durationable + */ + + override def getDuration: Duration = _durationProperty.get() + + override def getPosition: Duration = _positionProperty.get() + + override def durationProperty(): ReadOnlyObjectProperty[Duration] = _durationProperty + + override def positionProperty(): ReadOnlyObjectProperty[Duration] = _positionProperty + + def totalDurationBinding(): ObjectBinding[Duration] = { + Bindings.createObjectBinding(() => mediaPlayers.stream() + .map(player => player.mediaPlayer.getTotalDuration) + .filter(duration => duration != null) + .reduce(Duration.ZERO, (o1: Duration, o2: Duration) => o1.add(o2)), + mediaPlayers.stream().map(player => { + if (player.mediaPlayer != null) { + player.mediaPlayer.totalDurationProperty() + } else { + null + } + }) + .filter(o => o != null) + .toArray(size => new Array[ReadOnlyObjectProperty[Duration]](size)): _*) + } + + /* + Fadeable + */ + + override def fadeIn(): Unit = { + val fadeIn = getPad.getPadSettings.getFade.getFadeIn + if (fadeIn.toMillis > 0) { + fadeController.fadeIn(fadeIn) + } + } + + override def fadeOut(onFinish: Runnable): Unit = { + val fadeOut = getPad.getPadSettings.getFade.getFadeOut + if (fadeOut.toMillis > 0) { + fadeController.fadeOut(fadeOut, () => { + if (onFinish != null) onFinish.run() + + if (getPad.getStatus == PadStatus.PLAY) { + getPad.setStatus(PadStatus.STOP) + } + }) + } + else { + onFinish.run() + } + } + + override def isFadeActive: Boolean = fadeController.isFading + + override def fade(from: Double, to: Double, duration: Duration, onFinish: Runnable): Unit = { + fadeController.fade(from, to, duration, onFinish) + } + + /* + Loading + */ + + override def isPadLoaded: Boolean = { + mediaPlayers.isNotEmpty && !mediaPlayers.stream().anyMatch(player => player.mediaPlayer.getStatus == MediaPlayer.Status.UNKNOWN) + } + + override def isLoaded(mediaPath: MediaPath): Boolean = { + val loadedOptional: Optional[Boolean] = mediaPlayers.stream() + .filter(item => item.path == mediaPath) + .findFirst() + .map(container => container.mediaPlayer.getStatus != MediaPlayer.Status.UNKNOWN) + loadedOptional.orElse(false) + } + + + override def isPadLoading: Boolean = mediaPlayers.stream().anyMatch(player => player.mediaPlayer.getStatus == MediaPlayer.Status.UNKNOWN) + + /** + * Load media files. + */ + override def loadMedia(): Unit = { + mediaPlayers.clear() + getPad.getPaths.forEach(loadMedia(_)) + } + + /** + * Load media file. + * + * @param mediaPath specify media path + */ + override def loadMedia(mediaPath: MediaPath): Unit = { + val path = mediaPath.getPath + if (Files.notExists(path)) { + Platform.runLater(() => getPad.setStatus(PadStatus.NOT_FOUND)) + return + } + + val media = new Media(path.toUri.toString) + val mediaPlayer = new MediaPlayer(media) + + mediaPlayer.setOnReady(() => { + getPad.setStatus(PadStatus.READY) + + _durationProperty.bind(totalDurationBinding()) + _positionProperty.set(Duration.ZERO) + + Platform.runLater(() => { + if (getPad.isPadVisible) { + getPad.getController.getView.showBusyView(false) + } + }) + }) + + mediaPlayer.errorProperty().addListener((_, _, newValue) => Platform.runLater(() => { + Logger.error(newValue) + pad.setStatus(PadStatus.ERROR) + })) + mediaPlayer.setOnError(() => Platform.runLater(() => { + if (getPad.isPadVisible) { + getPad.getController.getView.showBusyView(false) + } + Logger.error(mediaPlayer.getError) + pad.setStatus(PadStatus.ERROR) + })) + + mediaPlayer.setOnEndOfMedia(() => { + getPad.setEof(true) + onEof() + }) + + mediaPlayers.add(new ContentPlayerMediaContainer(this, mediaPath, mediaPlayer)) + } + + /** + * Unload media files. + */ + override def unloadMedia(): Unit = { + if ((getPad.getStatus eq PadStatus.PLAY) || (getPad.getStatus eq PadStatus.PAUSE)) getPad.setStatus(PadStatus.STOP) + + mediaPlayers.clear() + + Platform.runLater(() => { + if (getPad != null) { + getPad.setStatus(PadStatus.EMPTY) + } + }) + } + + /** + * Unload media file. + * + * @param mediaPath specify media path + */ + override def unloadMedia(mediaPath: MediaPath): Unit = { + val index = mediaPlayers.indexWhere(item => item.path.getId == mediaPath.getId) + + if (index >= 0) { + val playerContainer = mediaPlayers(index) + playerContainer.stop() + mediaPlayers.remove(index) + } + } + + override def reorderMedia(): Unit = { + val paths = pad.getPaths + mediaPlayers.sort((o1, o2) => Integer.compare(paths.indexOf(o1.path), paths.indexOf(o2.path))) + } + + /* + Volume + */ + + override def updateVolume(): Unit = { + val volume = VolumeManager.getInstance.computeVolume(getPad) + mediaPlayers.forEach(player => player.mediaPlayer.setVolume(volume)) + } + + /** + * Create a copy of the PadContent instance + * + * @param pad target pad + * @return copied content + */ + override def copy(pad: Pad): PadContent = { + val clone = new ContentPlayerPadContent(pad, getType) + clone.loadMedia() + clone + } + + /* + Custom Settings + */ + + def shouldShowLastFrame(): Boolean = { + pad.getPadSettings.getCustomSettings.getOrDefault(ContentPlayerPadContentFactory.lastFrame, false).asInstanceOf[Boolean] + } + + def getSelectedZones: Seq[Zone] = { + val zoneConfiguration = Profile.currentProfile().getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration] + + val customSettings = pad.getPadSettings.getCustomSettings + val selectedZoneNames = customSettings.getOrDefault( + ContentPlayerPadContentFactory.zones, + zoneConfiguration.zones.stream().map(zone => zone.getName).collect(Collectors.toList()) + ).asInstanceOf[util.List[String]] + zoneConfiguration.zones.asScala.filter(zone => selectedZoneNames.contains(zone.getName)).toSeq + } +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentFactory.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentFactory.scala new file mode 100644 index 0000000000000000000000000000000000000000..d08958d5da016d424a9204a12317b8fbade30f93 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentFactory.scala @@ -0,0 +1,25 @@ +package de.tobias.playpad.plugin.content.pad + +import de.tobias.playpad.pad.Pad +import de.tobias.playpad.pad.content.{PadContent, PadContentFactory} +import de.tobias.playpad.pad.view.IPadContentView +import de.tobias.playpad.viewcontroller.PadSettingsTabViewController +import javafx.scene.layout.Pane + +class ContentPlayerPadContentFactory(val `type`: String) extends PadContentFactory(`type`) { + + override def newInstance(pad: Pad): PadContent = new ContentPlayerPadContent(pad, getType) + + override def getPadContentPreview(pad: Pad, parentNode: Pane): IPadContentView = new ContentPlayerPadPreview(pad, parentNode) + + override def getSettingsViewController(pad: Pad): PadSettingsTabViewController = new ContentPlayerPadContentSettingsViewController(pad) + + override def getSupportedTypes: Array[String] = ContentPlayerPadContentFactory.FILE_EXTENSION +} + +object ContentPlayerPadContentFactory { + private val FILE_EXTENSION = Array("*.mp4", "*.mov") + + val lastFrame = "ContentLastFrame" + val zones = "zones" +} \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentSettingsViewController.scala new file mode 100644 index 0000000000000000000000000000000000000000..14d5e0ee477047de962dfd5959c2ee67d0a9c1c8 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContentSettingsViewController.scala @@ -0,0 +1,73 @@ +package de.tobias.playpad.plugin.content.pad + +import java.util + +import de.thecodelabs.utils.util.Localization +import de.tobias.playpad.pad.Pad +import de.tobias.playpad.plugin.content.ContentPluginMain +import de.tobias.playpad.plugin.content.settings.{Zone, ZoneConfiguration} +import de.tobias.playpad.profile.Profile +import de.tobias.playpad.viewcontroller.PadSettingsTabViewController +import javafx.beans.binding.Bindings +import javafx.fxml.FXML +import javafx.scene.control.{Button, CheckBox} +import org.controlsfx.control.CheckListView + +import scala.jdk.CollectionConverters._ + +class ContentPlayerPadContentSettingsViewController(val pad: Pad) extends PadSettingsTabViewController { + + @FXML + var lastFrameCheckbox: CheckBox = _ + @FXML + var zoneListView: CheckListView[Zone] = _ + + @FXML + var addAllZonesButton: Button = _ + @FXML + var removeAllZonesButton: Button = _ + + load("view", "ContentPadSettings", Localization.getBundle) + + override def init(): Unit = { + val zoneConfiguration = Profile.currentProfile().getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration] + zoneListView.getItems.addAll(zoneConfiguration.zones) + + addAllZonesButton.disableProperty().bind(Bindings.equal(Bindings.size(zoneListView.getCheckModel.getCheckedIndices), zoneListView.getItems.size())) + removeAllZonesButton.disableProperty().bind(Bindings.isEmpty(zoneListView.getCheckModel.getCheckedIndices)) + } + + override def getName: String = Localization.getString("plugin.content.player.settings") + + override def loadSettings(pad: Pad): Unit = { + val customSettings = pad.getPadSettings.getCustomSettings + val lastFrameOption = customSettings.get(ContentPlayerPadContentFactory.lastFrame) + if (lastFrameOption != null) { + lastFrameCheckbox.setSelected(lastFrameOption.toString.toBoolean) + } + + pad.getContent match { + case content: ContentPlayerPadContent => + content.getSelectedZones.foreach(item => zoneListView.getCheckModel.check(item)) + case _ => + } + } + + override def saveSettings(pad: Pad): Unit = { + val customSettings = pad.getPadSettings.getCustomSettings + customSettings.put(ContentPlayerPadContentFactory.lastFrame, lastFrameCheckbox.isSelected) + + val selectedZoneNames = zoneListView.getCheckModel.getCheckedItems.asScala.map(zone => zone.getName) + customSettings.put(ContentPlayerPadContentFactory.zones, new util.ArrayList(selectedZoneNames.asJavaCollection)) + } + + @FXML + def onAddAllZonesHandler(): Unit = { + zoneListView.getCheckModel.checkAll() + } + + @FXML + def onRemoveAllZonesHandler(): Unit = { + zoneListView.getCheckModel.clearChecks() + } +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadPreview.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadPreview.scala new file mode 100644 index 0000000000000000000000000000000000000000..6ff298194c1ec57c2f6e7262b8c1c96db6498476 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadPreview.scala @@ -0,0 +1,68 @@ +package de.tobias.playpad.plugin.content.pad + +import de.thecodelabs.utils.io.PathUtils +import de.tobias.playpad.pad.Pad +import de.tobias.playpad.pad.view.IPadContentView +import javafx.beans.binding.Bindings +import javafx.collections.ListChangeListener +import javafx.geometry.{Insets, Pos} +import javafx.scene.Parent +import javafx.scene.control.Label +import javafx.scene.layout.{Pane, Priority, VBox} +import javafx.scene.text.TextAlignment + +class ContentPlayerPadPreview(pad: Pad, parent: Pane) extends VBox with IPadContentView { + + val nameLabel: Label = new Label() + val subTitleLabel: Label = new Label() + + setupLabel(nameLabel) + setupLabel(subTitleLabel) + + getChildren.addAll(nameLabel, subTitleLabel) + setSpacing(3) + setPadding(new Insets(7)) + + getStyleClass.addListener(new ListChangeListener[String] { + override def onChanged(c: ListChangeListener.Change[_ <: String]): Unit = { + while (c.next()) { + if (c.wasRemoved()) { + nameLabel.getStyleClass.removeAll(c.getRemoved) + subTitleLabel.getStyleClass.removeAll(c.getRemoved) + } + + if (c.wasAdded()) { + nameLabel.getStyleClass.addAll(c.getAddedSubList) + subTitleLabel.getStyleClass.addAll(c.getAddedSubList) + } + } + } + }) + + nameLabel.textProperty.bind(pad.nameProperty) + pad.getContent match { + case content: ContentPlayerPadContent => + subTitleLabel.textProperty().bind(Bindings.createStringBinding(() => { + if (content.getCurrentPlayingMediaIndex < 0) "" else PathUtils.getFilenameWithoutExtension(pad.getPaths.get(content.getCurrentPlayingMediaIndex).getPath.getFileName) + }, content.currentPlayingMediaIndexProperty())) + case _ => + } + + private def setupLabel(label: Label): Unit = { + label.setWrapText(true) + label.setAlignment(Pos.CENTER) + label.setTextAlignment(TextAlignment.CENTER) + + label.prefWidthProperty.bind(parent.widthProperty) + label.setMaxHeight(Double.MaxValue) + + VBox.setVgrow(label, Priority.ALWAYS) + } + + override def getNode: Parent = this + + override def deInit(): Unit = { + nameLabel.textProperty().unbind() + subTitleLabel.textProperty().unbind() + } +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/ContentPlayerViewController.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/ContentPlayerViewController.scala new file mode 100644 index 0000000000000000000000000000000000000000..c659e296cd880469fcae5e27ca2f5b193fad0258 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/ContentPlayerViewController.scala @@ -0,0 +1,118 @@ +package de.tobias.playpad.plugin.content.player + +import de.thecodelabs.logger.Logger +import de.thecodelabs.utils.ui.size.IgnoreStageSizing +import de.thecodelabs.utils.ui.{NVC, NVCStage} +import de.tobias.playpad.PlayPadPlugin +import de.tobias.playpad.plugin.content.settings.{Zone, ZoneConfiguration} +import de.tobias.playpad.project.page.PadIndex +import javafx.geometry.Insets +import javafx.scene.layout._ +import javafx.scene.media.MediaPlayer +import javafx.scene.paint.Color +import javafx.stage.{Stage, StageStyle} + +import scala.collection.mutable.ListBuffer + +@IgnoreStageSizing +class ContentPlayerViewController extends NVC { + + private val mediaStacks: ListBuffer[MediaPlayerStack] = ListBuffer.empty + + load("view", "PlayerView") + private val stageContainer: NVCStage = applyViewControllerToStage + stageContainer.addCloseHook(() => false) + + Logger.debug("Create Player View Controller") + + override def init(): Unit = { + val parent = getParent.asInstanceOf[Pane] + parent.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY))) + } + + override def initStage(stage: Stage): Unit = { + super.initStage(stage) + stage.initStyle(StageStyle.UNDECORATED) + stage.setAlwaysOnTop(true) + + stage.getScene.setFill(Color.BLACK) + stage.getIcons.add(PlayPadPlugin.getInstance().getIcon) + } + + def showMediaPlayer(padIndex: PadIndex, mediaPlayer: MediaPlayer, zones: Seq[Zone]): Unit = { + val iterator = this.mediaStacks.iterator + while (iterator.hasNext) { + val mediaPlayerStack = iterator.next() + if (zones.contains(mediaPlayerStack.zone)) { + mediaPlayerStack.showMediaPlayer(padIndex, mediaPlayer) + } + } + } + + def disconnectMediaPlayer(mediaPlayer: MediaPlayer, zones: Seq[Zone]): Unit = { + val iterator = this.mediaStacks.iterator + while (iterator.hasNext) { + val mediaPlayerStack = iterator.next() + if (zones.contains(mediaPlayerStack.zone)) { + mediaPlayerStack.disconnectMediaPlayer(mediaPlayer) + } + } + } + + def configurePlayers(configuration: ZoneConfiguration): Unit = { + if (configuration.zones.isEmpty) { + closeStage() + return + } + + val parent = getParent.asInstanceOf[Pane] + parent.getChildren.clear() + + mediaStacks.clear() + configuration.zones.forEach(player => { + val mediaPlayerStack = new MediaPlayerStack(player) + mediaStacks.addOne(mediaPlayerStack) + parent.getChildren.add(mediaPlayerStack) + }) + + showStage() + + getStageContainer.ifPresent(container => { + val stage = container.getStage + + import scala.jdk.CollectionConverters._ + val zones = configuration.zones.asScala + val maxWidth = zones.map(player => player.x + player.width).max + val maxHeight = zones.map(player => player.y + player.height).max + + stage.setX(0) + stage.setY(0) + stage.setWidth(maxWidth) + stage.setHeight(maxHeight) + }) + } + + def addActivePadToList(padIndex: PadIndex, zones: Seq[Zone]): Unit = getMediaStacks(zones) + .foreach(mediaStack => mediaStack.addActivePad(padIndex)) + + def removeActivePadFromList(padIndex: PadIndex, zones: Seq[Zone]): Unit = getMediaStacks(zones) + .foreach(mediaStack => mediaStack.removeActivePad(padIndex)) + + def highlight(zone: Zone, on: Boolean): Unit = { + if (getMediaStack(zone).isEmpty) { + return + } + getMediaStack(zone).head.highlight(on) + } + + def setFadeValue(mediaPlayer: MediaPlayer, zones: Seq[Zone], value: Double): Unit = getMediaStacks(zones) + .foreach(mediaStack => mediaStack.setFadeValue(mediaPlayer, value)) + + private def getMediaStack(zone: Zone): ListBuffer[MediaPlayerStack] = { + getMediaStacks(List(zone)) + } + + private def getMediaStacks(zones: Seq[Zone]): ListBuffer[MediaPlayerStack] = { + mediaStacks.filter(mediaPlayer => zones.contains(mediaPlayer.zone)) + } +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/MediaPlayerStack.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/MediaPlayerStack.scala new file mode 100644 index 0000000000000000000000000000000000000000..15d3872130e3fe4b1d32c3ff3d67f11329a70c6d --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/player/MediaPlayerStack.scala @@ -0,0 +1,78 @@ +package de.tobias.playpad.plugin.content.player + +import java.util.stream.Collectors + +import de.thecodelabs.logger.Logger +import de.tobias.playpad.plugin.content.settings.Zone +import de.tobias.playpad.project.page.PadIndex +import javafx.geometry.Insets +import javafx.scene.layout.{Background, BackgroundFill, CornerRadii, StackPane} +import javafx.scene.media.{MediaPlayer, MediaView} +import javafx.scene.paint.Color + +import scala.collection.mutable +import scala.collection.mutable.ListBuffer + +class MediaPlayerStack(val zone: Zone) extends StackPane { + + private var activePlayers: ListBuffer[PadIndex] = ListBuffer.empty + val mediaViews: mutable.Map[MediaPlayer, MediaView] = new mutable.HashMap[MediaPlayer, MediaView]() + + setLayoutX(zone.x) + setLayoutY(zone.y) + setMinWidth(zone.width) + setMaxWidth(zone.width) + setMinHeight(zone.height) + setMaxHeight(zone.height) + + def addActivePad(padIndex: PadIndex): Unit = activePlayers.addOne(padIndex) + + def removeActivePad(padIndex: PadIndex): Unit = activePlayers = activePlayers.filter(element => element != padIndex) + + def showMediaPlayer(padIndex: PadIndex, mediaPlayer: MediaPlayer): Unit = { + if (!mediaViews.contains(mediaPlayer)) { + val mediaView = new MediaView(mediaPlayer) + mediaView.setFitWidth(zone.width) + mediaView.setFitHeight(zone.height) + mediaViews.put(mediaPlayer, mediaView) + } + + val mediaView = mediaViews(mediaPlayer) + mediaView.setUserData(padIndex) + mediaView.setOpacity(1.0) + + if (!getChildren.contains(mediaView)) { + val index = activePlayers.indexOf(padIndex) + try { + getChildren.add(index, mediaView) + } catch { + case e: Exception => + Logger.error(e) + getChildren.add(mediaView) + } + } + } + + def disconnectMediaPlayer(mediaPlayer: MediaPlayer): Unit = { + if (mediaViews.contains(mediaPlayer)) { + getChildren.remove(mediaViews(mediaPlayer)) + } + } + + def setFadeValue(mediaPlayer: MediaPlayer, value: Double): Unit = { + if (mediaViews.contains(mediaPlayer)) { + val mediaView = mediaViews(mediaPlayer) + mediaView.setOpacity(value) + } + } + + def highlight(on: Boolean): Unit = { + if (on) { + setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY))) + } else { + setBackground(null) + } + } + + override def toString: String = f"MediaPlayerStack: ${getChildren.stream().map(view => f"MediaView: ${view.getUserData}").collect(Collectors.joining(", "))}" +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneConfiguration.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneConfiguration.scala new file mode 100644 index 0000000000000000000000000000000000000000..956a0183c9eafa8245a6565558bf85aeaa176e4c --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneConfiguration.scala @@ -0,0 +1,43 @@ +package de.tobias.playpad.plugin.content.settings + +import java.util +import java.util.{List => JavaList} + +import de.thecodelabs.storage.settings.annotation.{FilePath, Key} +import de.tobias.playpad.Displayable +import javafx.beans.property.{SimpleStringProperty, StringProperty} + +@FilePath("players.json") +class ZoneConfiguration { + @Key + var zones: JavaList[Zone] = new util.ArrayList[Zone]() +} + +class Zone extends Displayable { + @Key + private var name: String = _ + @Key + var x: Double = _ + @Key + var y: Double = _ + @Key + var width: Double = _ + @Key + var height: Double = _ + + def getName: String = name + + def setName(name: String): Unit = { + this.name = name + _displayProperty.set(name) + } + + private val _displayProperty: StringProperty = new SimpleStringProperty(name) + + override def displayProperty(): StringProperty = { + _displayProperty.set(name) + _displayProperty + } + + override def toString: String = name +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneSettingsViewController.scala new file mode 100644 index 0000000000000000000000000000000000000000..bae668ff818ef49c8b463df091ccea02bffdb6f4 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/settings/ZoneSettingsViewController.scala @@ -0,0 +1,134 @@ +package de.tobias.playpad.plugin.content.settings + +import de.thecodelabs.utils.ui.scene.input.NumberTextField +import de.thecodelabs.utils.util.Localization +import de.tobias.playpad.plugin.content.ContentPluginMain +import de.tobias.playpad.profile.{Profile, ProfileSettings} +import de.tobias.playpad.project.Project +import de.tobias.playpad.viewcontroller.main.IMainViewController +import de.tobias.playpad.viewcontroller.option.{IProfileReloadTask, ProfileSettingsTabViewController} +import javafx.application.Platform +import javafx.fxml.FXML +import javafx.scene.control.{Button, ListCell, ListView, TextField} + +class ZoneSettingsViewController extends ProfileSettingsTabViewController with IProfileReloadTask { + + @FXML + var listView: ListView[Zone] = _ + + @FXML + var nameTextField: TextField = _ + @FXML + var xTextField: NumberTextField = _ + @FXML + var yTextField: NumberTextField = _ + @FXML + var widthTextField: NumberTextField = _ + @FXML + var heightTextField: NumberTextField = _ + + @FXML + var addButton: Button = _ + @FXML + var removeButton: Button = _ + + load("view", "ZoneSettings", Localization.getBundle) + + override def init(): Unit = { + listView.setCellFactory((_: ListView[Zone]) => new ListCell[Zone] { + override def updateItem(item: Zone, empty: Boolean): Unit = { + super.updateItem(item, empty) + if (!empty) { + textProperty().bind(item.displayProperty()) + } else { + textProperty().unbind() + setText("") + } + } + }) + listView.getSelectionModel.selectedItemProperty().addListener((_, oldValue, newValue) => { + val playerViewController = ContentPluginMain.playerViewController + + if (oldValue != null) { + saveSettingsToZone(oldValue) + playerViewController.highlight(oldValue, on = false) + } + if (newValue != null) { + showSettingsOfZone(newValue) + playerViewController.highlight(newValue, on = true) + } else { + clearTextFields() + } + }) + } + + private def saveSettingsToZone(zone: Zone): Unit = { + zone.setName(nameTextField.getText) + zone.x = xTextField.getText.toDouble + zone.y = yTextField.getText.toDouble + zone.width = widthTextField.getText.toDouble + zone.height = heightTextField.getText.toDouble + } + + private def showSettingsOfZone(zone: Zone): Unit = { + nameTextField.setText(zone.getName) + xTextField.setText(zone.x.toInt.toString) + yTextField.setText(zone.y.toInt.toString) + widthTextField.setText(zone.width.toInt.toString) + heightTextField.setText(zone.height.toInt.toString) + } + + private def clearTextFields(): Unit = { + nameTextField.setText("") + xTextField.setText("") + yTextField.setText("") + widthTextField.setText("") + heightTextField.setText("") + } + + // Actions + @FXML + def onAddHandle(): Unit = { + val newConfiguration = new Zone + newConfiguration.setName(Localization.getString("plugin.content.player.settings.default_name")) + + getZoneConfiguration.zones.add(newConfiguration) + listView.getItems.add(newConfiguration) + } + + @FXML + def onRemoveHandle(): Unit = { + val selectedItem = listView.getSelectionModel.getSelectedItem + if (selectedItem != null) { + listView.getItems.remove(selectedItem) + getZoneConfiguration.zones.remove(selectedItem) + } + } + + override def loadSettings(settings: Profile): Unit = { + listView.getItems.setAll(getZoneConfiguration.zones) + } + + override def saveSettings(settings: Profile): Unit = { + val selectedItem = listView.getSelectionModel.getSelectedItem + if (selectedItem != null) { + saveSettingsToZone(selectedItem) + } + } + + override def needReload(): Boolean = { + true + } + + override def validSettings(): Boolean = { + true + } + + override def name(): String = Localization.getString("plugin.content.player.settings") + + + override def getTask(settings: ProfileSettings, project: Project, controller: IMainViewController): Runnable = () => + Platform.runLater(() => ContentPluginMain.playerViewController.configurePlayers(getZoneConfiguration)) + + private def getZoneConfiguration: ZoneConfiguration = Profile.currentProfile().getCustomSettings(ContentPluginMain.zoneConfigurationKey).asInstanceOf[ZoneConfiguration] +} diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala new file mode 100644 index 0000000000000000000000000000000000000000..22836f6b9326accde9478b56a7e65861ff3e5fb3 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala @@ -0,0 +1,31 @@ +package de.tobias.playpad.plugin.content + +import javafx.collections.ObservableList + +package object util { + + implicit class ObservableListExtension[E >: Null](list: ObservableList[E]) { + def head: E = { + if (list.isEmpty) { + return null + } + + list.get(0) + } + + def apply(index: Int): E = list.get(index) + + def length: Long = list.size() + + def isNotEmpty: Boolean = !list.isEmpty + + def indexWhere(predicate: E => Boolean): Int = { + for (i <- 0 until list.size()) { + if (predicate(list.get(i))) { + return i + } + } + -1 + } + } +} diff --git a/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml b/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml index 1256a10cbe09899239a41d8c2bc2fe2f6d3135a0..2e1be5a7b2293b617048c7d311c779003afabad2 100644 --- a/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml +++ b/PlayWallPlugins/PlayWallPluginEqualizer/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallPlugins</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWallPluginEqualizer</artifactId> diff --git a/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java index 6ff24f83ac9122fa073da85a772a97ff6be76307..f65d2d28af1b7df25ed6f40c6a92f36a323deb95 100644 --- a/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java +++ b/PlayWallPlugins/PlayWallPluginEqualizer/src/main/java/de/tobias/playpad/equalizerplugin/impl/EqualizerPluginImpl.java @@ -1,8 +1,8 @@ package de.tobias.playpad.equalizerplugin.impl; import de.thecodelabs.logger.Logger; -import de.thecodelabs.plugins.PluginArtifact; import de.thecodelabs.plugins.PluginDescriptor; +import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.thecodelabs.utils.application.ApplicationUtils; import de.thecodelabs.utils.application.container.PathType; import de.thecodelabs.utils.ui.NVCStage; diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml b/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml index 698c86e1e9d034551a033d3dc323d9baa21fcdd0..796dc9ad10ed73ebf34dfecdd5c6b6f3e798b3cd 100644 --- a/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallPlugins</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWallPluginLaunchpad</artifactId> diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java index 3c153f971bccd8dc41be1b3c7cd99470d0c89286..0a62f947c6504e42134e4e139aaff43886478acf 100644 --- a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java @@ -2,8 +2,8 @@ package de.tobias.playpad.launchpadplugin.impl; import de.thecodelabs.logger.Logger; import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscriptionRegistry; -import de.thecodelabs.plugins.PluginArtifact; import de.thecodelabs.plugins.PluginDescriptor; +import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.tobias.playpad.launchpadplugin.midi.mk2.LaunchPadMK2; import de.tobias.playpad.launchpadplugin.midi.s.LaunchPadS; import de.tobias.playpad.plugin.Module; diff --git a/PlayWallPlugins/PlayWallPluginMedia/pom.xml b/PlayWallPlugins/PlayWallPluginMedia/pom.xml index c28080c20e25e6f0b6f8fd0c6a0963c3a47891fa..f420120ac351928558988fd3c347cec1302a364b 100644 --- a/PlayWallPlugins/PlayWallPluginMedia/pom.xml +++ b/PlayWallPlugins/PlayWallPluginMedia/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallPlugins</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <artifactId>PlayWallPluginMedia</artifactId> diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java index 4a9a5ec7b072aa401cb87eea1093050a199b6539..d9c10d492f3725b1bd743b09aab267bfe581046f 100644 --- a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java +++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/image/ImagePadContentFactory.java @@ -9,7 +9,7 @@ import javafx.collections.ListChangeListener; import javafx.collections.SetChangeListener; import javafx.css.PseudoClass; import javafx.geometry.Pos; -import javafx.scene.Node; +import javafx.scene.Parent; import javafx.scene.control.Label; import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; @@ -91,7 +91,7 @@ public class ImagePadContentFactory extends PadContentFactory { } @Override - public Node getNode() { + public Parent getNode() { return stackPane; } diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java index 0565647dc30745ffb5da019f0910176bad972704..3fa00ae758861e8750be5612b857fe3cc9f2b35b 100644 --- a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java +++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/main/impl/MediaPluginImpl.java @@ -2,8 +2,8 @@ package de.tobias.playpad.plugin.media.main.impl; import de.thecodelabs.logger.Logger; import de.thecodelabs.midi.action.ActionRegistry; -import de.thecodelabs.plugins.PluginArtifact; import de.thecodelabs.plugins.PluginDescriptor; +import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.thecodelabs.utils.ui.icon.FontAwesomeType; import de.thecodelabs.utils.ui.icon.FontIcon; import de.thecodelabs.utils.ui.scene.HUD; diff --git a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java index a8aca757db9af4a5e11da5973d0ffcd899ef1c37..14e2269f4a819ec63df0519285189c2c69be1cae 100644 --- a/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java +++ b/PlayWallPlugins/PlayWallPluginMedia/src/main/java/de/tobias/playpad/plugin/media/video/VideoPadContentFactory.java @@ -3,18 +3,13 @@ package de.tobias.playpad.plugin.media.video; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.content.PadContent; import de.tobias.playpad.pad.content.PadContentFactory; +import de.tobias.playpad.pad.preview.PadTextPreview; import de.tobias.playpad.pad.view.IPadContentView; import de.tobias.playpad.plugin.media.main.impl.MediaPluginImpl; import de.tobias.playpad.plugin.media.main.impl.MediaSettingsTabViewController; import de.tobias.playpad.viewcontroller.PadSettingsTabViewController; import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; -import javafx.geometry.Pos; -import javafx.scene.Node; -import javafx.scene.control.Label; import javafx.scene.layout.Pane; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import javafx.scene.text.TextAlignment; public class VideoPadContentFactory extends PadContentFactory { @@ -31,7 +26,7 @@ public class VideoPadContentFactory extends PadContentFactory { @Override public IPadContentView getPadContentPreview(Pad pad, Pane parentNode) { - return new VideoContentView(pad, parentNode); + return new PadTextPreview(pad, parentNode); } @Override @@ -50,31 +45,4 @@ public class VideoPadContentFactory extends PadContentFactory { return FILE_EXTENSION; } - private class VideoContentView implements IPadContentView { - - private Label nameLabel; - - VideoContentView(Pad pad, Pane parentNode) { - nameLabel = new Label(); - nameLabel.textProperty().bind(pad.nameProperty()); - - nameLabel.setWrapText(true); - nameLabel.setAlignment(Pos.CENTER); - nameLabel.setTextAlignment(TextAlignment.CENTER); - - nameLabel.prefWidthProperty().bind(parentNode.widthProperty()); - nameLabel.setMaxHeight(Double.MAX_VALUE); - VBox.setVgrow(nameLabel, Priority.ALWAYS); - } - - @Override - public Node getNode() { - return nameLabel; - } - - @Override - public void deInit() { - nameLabel.textProperty().unbind(); - } - } } diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml b/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml index 8e54821dac703bc7ec4685f5dd50a199f56fb10a..b2c4941c26d77e0b6aa485cf423b606017803b0e 100644 --- a/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml +++ b/PlayWallPlugins/PlayWallPluginNativeAudio/pom.xml @@ -8,7 +8,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallPlugins</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <properties> diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java index e0e75d8214d02545871f708dc5f0cacfe6bf9019..399cc42c4f02033e6d3efca1d96c4daaf987bc5b 100644 --- a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java +++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/audio/windows/NativeAudioWinHandler.java @@ -26,11 +26,11 @@ public class NativeAudioWinHandler extends AudioHandler implements Soundcardable static final String SOUND_CARD = "SoundCard"; private NativeAudio audioHandler; - private ObjectProperty<Duration> durationProperty; - private ObjectProperty<Duration> positionProperty; + private final ObjectProperty<Duration> durationProperty; + private final ObjectProperty<Duration> positionProperty; private static Thread positionThread; - private static List<NativeAudioWinHandler> playedHandlers = new ArrayList<>(); + private static final List<NativeAudioWinHandler> playedHandlers = new ArrayList<>(); private static final int SLEEP_TIME_POSITION = 50; static { diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java index 771db0fe9805a4aab1d286d97bd42c8acb9a61c8..1cba1f2a019dd1a84584c7d0bb785a252f822d1e 100644 --- a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java +++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/java/de/tobias/playpad/plugin/NativeAudioPathType.java @@ -7,7 +7,7 @@ public enum NativeAudioPathType implements ContainerPathType { AUDIO(PathType.LIBRARY.getFolder() + "/Audio"); - private String folder; + private final String folder; NativeAudioPathType(String folder) { this.folder = folder; diff --git a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala index 040c23f86adb8eb5eb4a08c1a3426e22c8e99607..c273ca5d167c831fa94c23bcc5e148ac9658a893 100644 --- a/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala +++ b/PlayWallPlugins/PlayWallPluginNativeAudio/src/main/scala/de/tobias/playpad/plugin/NativeAudioPluginImpl.scala @@ -1,6 +1,7 @@ package de.tobias.playpad.plugin -import de.thecodelabs.plugins.{PluginArtifact, PluginDescriptor} +import de.thecodelabs.plugins.PluginDescriptor +import de.thecodelabs.plugins.versionizer.PluginArtifact import de.thecodelabs.utils.util.OS import de.thecodelabs.utils.util.OS.OSType import de.tobias.playpad.plugin.loader.{MacAudioImplLoader, WindowsAudioImplLoader} diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml b/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml index d03d7fa22d7222e5f75363e91ca9d6ae54ee068a..2239ae0009ea855a08acdffc80c1756c3c5bc091 100644 --- a/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml +++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallPlugins</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java index 278ec6c4523045ae4784801f2b38d254efc57e0d..afa5ff76555f3a0eea4d166affb042e78d45424a 100644 --- a/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java +++ b/PlayWallPlugins/PlayWallPluginPlayoutLog/src/main/java/de/tobias/playpad/plugin/playout/PlayoutLogPlugin.java @@ -2,8 +2,8 @@ package de.tobias.playpad.plugin.playout; import de.thecodelabs.logger.LogLevel; import de.thecodelabs.logger.Logger; -import de.thecodelabs.plugins.PluginArtifact; import de.thecodelabs.plugins.PluginDescriptor; +import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.PlayPadPlugin; import de.tobias.playpad.plugin.Module; diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml b/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml index 85bc644f9a1801eb33e7e8b2ccee08592c3a1de8..d0b4ab9b7c8d5cd258d926eec7f1858becfd855b 100644 --- a/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml +++ b/PlayWallPlugins/PlayWallPluginWebAPI/pom.xml @@ -5,7 +5,7 @@ <parent> <artifactId>PlayWallPlugins</artifactId> <groupId>de.tobias.playpad</groupId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..c5b35f5f180fa76bf0c1f9681e96c9b03f30f4c5 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java @@ -0,0 +1,28 @@ +package de.tobias.playpad.plugin.api.websocket.settings; + +import de.thecodelabs.storage.settings.annotation.FilePath; +import de.thecodelabs.storage.settings.annotation.Key; + +@FilePath("webapi.json") +public class WebApiSettings { + @Key + private boolean enabled = false; + @Key + private int port = 9876; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..0b7b9cf8475b89313f3289e30aef44a2c86136a8 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties @@ -0,0 +1,5 @@ +webapi.settings=WebAPI +webapi.settings.enable=WebAPI +webapi.settings.enabled=Aktiv +webapi.settings.port=Port +webapi.settings.restart=\u00C4nderungen an den Einstellungen werden erst mit einem Neustart von PlayWall wirksam. \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml new file mode 100644 index 0000000000000000000000000000000000000000..473dba8d1a6441e62fed11fa04b87a6be18397b3 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import de.thecodelabs.utils.ui.scene.input.NumberTextField?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.CheckBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="14.0" + xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> + <children> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.enable"/> + <CheckBox fx:id="activeCheckbox" mnemonicParsing="false" text="%webapi.settings.enabled"/> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.port"/> + <NumberTextField fx:id="portTextField"/> + </children> + </HBox> + <Label text="%webapi.settings.restart"> + <padding> + <Insets left="164.0"/> + </padding> + </Label> + </children> + <padding> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/> + </padding> +</VBox> diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala index 2eb1c9a7579ed7a3b0e3f5a3abceeacdf219753b..0d4d7321ee3a880471919572daaea62d1da8517d 100644 --- a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala @@ -1,17 +1,27 @@ package de.tobias.playpad.plugin.api +import java.nio.file.{Files, Path} + import de.thecodelabs.logger.Logger -import de.thecodelabs.plugins.{PluginArtifact, PluginDescriptor} +import de.thecodelabs.plugins.PluginDescriptor +import de.thecodelabs.plugins.versionizer.PluginArtifact +import de.thecodelabs.storage.settings.{Storage, StorageTypes} +import de.thecodelabs.utils.application.ApplicationUtils +import de.thecodelabs.utils.application.container.PathType +import de.thecodelabs.utils.util.Localization import de.tobias.playpad.PlayPadPlugin import de.tobias.playpad.plugin.api.websocket.WebSocketHandler import de.tobias.playpad.plugin.api.websocket.listener.{PadStatusListener, ProjectListener} +import de.tobias.playpad.plugin.api.websocket.settings.{WebApiSettings, WebApiSettingsViewController} import de.tobias.playpad.plugin.{Module, PlayPadPluginStub} -import spark.Spark +import spark.{Request, Response, Spark} class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { private var module: Module = _ + private var webApiSettings: WebApiSettings = _ + override def startup(descriptor: PluginDescriptor): Unit = { module = new Module(descriptor.getName, descriptor.getArtifactId) @@ -20,16 +30,34 @@ class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { Logger.debug("Enable Web API Plugin") - Spark.port(9876) - Spark.webSocket("/api", WebSocketHandler.instance) - Spark.get("/", (_, _) => "PlayWall API") + val settingsPath = WebApiPlugin.getWebApiSettingsPath + if (Files.exists(settingsPath)) { + webApiSettings = Storage.load(StorageTypes.JSON, classOf[WebApiSettings]) + } + if (webApiSettings == null) { + webApiSettings = new WebApiSettings + } + + if (webApiSettings.isEnabled) { + Spark.port(webApiSettings.getPort) + Spark.webSocket("/api", WebSocketHandler.instance) + Spark.get("/", (_: Request, _: Response) => "PlayWall API") + Logger.info(f"Start WebAPI on port ${webApiSettings.getPort}") + } + + PlayPadPlugin.getInstance().addGlobalSettingsTab(() => new WebApiSettingsViewController(webApiSettings)) + Localization.addResourceBundle("plugin/webapi/lang/base", getClass.getClassLoader) } override def shutdown(): Unit = { - Logger.debug("Disable Web API Plugin") - Spark.stop() + Logger.debug("Disable Web API Plugin") } override def getModule: Module = module + } + +object WebApiPlugin { + def getWebApiSettingsPath: Path = ApplicationUtils.getApplication.getPath(PathType.CONFIGURATION, "webapi.json") +} \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala new file mode 100644 index 0000000000000000000000000000000000000000..4f86d86df6e85433d7bd38a2dfb21fcb99361fdd --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala @@ -0,0 +1,81 @@ +package de.tobias.playpad.plugin.api.websocket.settings + +import java.nio.file.Files + +import de.thecodelabs.logger.Logger +import de.thecodelabs.storage.settings.{Storage, StorageTypes} +import de.thecodelabs.utils.ui.scene.input.NumberTextField +import de.thecodelabs.utils.util.Localization +import de.tobias.playpad.plugin.api.WebApiPlugin +import de.tobias.playpad.settings.GlobalSettings +import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController +import javafx.fxml.FXML +import javafx.scene.control.CheckBox + +class WebApiSettingsViewController(val webApiSettings: WebApiSettings) extends GlobalSettingsTabViewController { + + load("plugin/webapi/view", "WebApiSettings", Localization.getBundle) + + @FXML + var activeCheckbox: CheckBox = _ + + @FXML + var portTextField: NumberTextField = _ + + /** + * Lädt alle Einstellungen vom Model in die GUI. + * + * @param settings Aktuelles GlobalSettings + */ + override def loadSettings(settings: GlobalSettings): Unit = { + activeCheckbox.setSelected(webApiSettings.isEnabled) + portTextField.setText(webApiSettings.getPort.toString) + } + + /** + * Speichert alle Änderungen in das Model. + * + * @param settings Aktuelles GlobalSettings + */ + override def saveSettings(settings: GlobalSettings): Unit = { + webApiSettings.setEnabled(activeCheckbox.isSelected) + webApiSettings.setPort(portTextField.getText.toInt) + + saveToFile() + } + + /** + * Gibt <code>true</code> zurück, wenn im Hauptprogramm etwas neu geladen werden muss. + * + * @return <code>true</code> Benötigt Reload + */ + override def needReload(): Boolean = { + false + } + + /** + * Prüft ob die eingetragen Einstellungen erlaubt sind. Bei falschen Eingaben können die Einstellungen nicht + * geschlossen werden. + * + * @return <code>true</code> Einstellungen erlaubt. <code>false</code> Einstellungen fehlerhaft. + */ + override def validSettings(): Boolean = { + true + } + + /** + * Gibt den Namen für den Tab zurück. + * + * @return Display Name des Tabs. + */ + override def name(): String = Localization.getString("webapi.settings") + + private def saveToFile(): Unit = { + val settingsPath = WebApiPlugin.getWebApiSettingsPath + if (Files.notExists(settingsPath)) { + Files.createDirectories(settingsPath.getParent) + } + Storage.save(StorageTypes.JSON, webApiSettings) + Logger.info(f"Save WebAPI settings to $settingsPath") + } +} diff --git a/PlayWallPlugins/pom.xml b/PlayWallPlugins/pom.xml index e633d8b643444f5319297ee50360e08d1722198a..53ba5f57847adeeca8830e9ac4dd854bcd0c0426 100644 --- a/PlayWallPlugins/pom.xml +++ b/PlayWallPlugins/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallDesktop</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> </parent> <modelVersion>4.0.0</modelVersion> @@ -20,6 +20,7 @@ <module>PlayWallPluginNativeAudio</module> <module>PlayWallPluginPlayoutLog</module> <module>PlayWallPluginWebAPI</module> + <module>PlayWallPluginContentPlayer</module> </modules> </project> \ No newline at end of file diff --git a/pom.xml b/pom.xml index 08781928dbc439dbf7103ba7a058b26b6301fa27..a876b2e40959b81847e79506ba84b7540809bed2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <groupId>de.tobias.playpad</groupId> <artifactId>PlayWallDesktop</artifactId> - <version>7.0.2</version> + <version>7.1.0</version> <packaging>pom</packaging> <properties> @@ -22,7 +22,7 @@ <components.version>${project.version}</components.version> <jlibs.version>2.0.6</jlibs.version> - <libPlugins.version>2.2.1</libPlugins.version> + <libPlugins.version>3.0.6</libPlugins.version> <versionizer-api.version>1.2.0</versionizer-api.version> <jlayer.version>1.0.1</jlayer.version> @@ -66,13 +66,6 @@ <type>pom</type> <scope>import</scope> </dependency> - <dependency> - <groupId>de.thecodelabs</groupId> - <artifactId>libPlugins</artifactId> - <version>${libPlugins.version}</version> - <type>pom</type> - <scope>import</scope> - </dependency> </dependencies> </dependencyManagement>