From 4e082e9ee4ed89d50be279ebb644a402b1e80c7e Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Tue, 3 Dec 2024 23:59:45 +0100 Subject: [PATCH 01/15] feat: refactor plugin tree view compoent --- .../controllers/PluginTreeViewController.java | 381 ++++++++++++++++++ .../core/controllers/PluginsController.java | 364 +++-------------- .../src/main/resources/fxml/PluginsView.fxml | 80 ++-- 3 files changed, 467 insertions(+), 358 deletions(-) create mode 100644 owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java new file mode 100644 index 00000000..85b2e7f2 --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java @@ -0,0 +1,381 @@ +/* OwlPlug + * Copyright (C) 2021 Arthur + * + * This file is part of OwlPlug. + * + * OwlPlug is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 + * as published by the Free Software Foundation. + * + * OwlPlug is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OwlPlug. If not, see . + */ + +package com.owlplug.core.controllers; + +import com.owlplug.core.components.ApplicationDefaults; +import com.owlplug.core.components.ApplicationPreferences; +import com.owlplug.core.dao.SymlinkDAO; +import com.owlplug.core.model.IDirectory; +import com.owlplug.core.model.Plugin; +import com.owlplug.core.model.PluginComponent; +import com.owlplug.core.model.PluginDirectory; +import com.owlplug.core.model.Symlink; +import com.owlplug.core.services.PluginService; +import com.owlplug.core.ui.FilterableTreeItem; +import com.owlplug.core.ui.PluginTreeCell; +import com.owlplug.core.utils.FileUtils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleStringProperty; +import javafx.scene.control.TreeCell; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeView; +import javafx.util.Callback; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Controller +public class PluginTreeViewController extends BaseController { + + @Autowired + private PluginService pluginService; + @Autowired + private SymlinkDAO symlinkDAO; + + private SimpleStringProperty search = new SimpleStringProperty(); + private TreeView pluginTreeView; + private PluginTreeViewController.FileTree pluginTree; + private FilterableTreeItem treePluginNode; + private FilterableTreeItem treeFileRootNode; + + public PluginTreeViewController() { + pluginTreeView = new TreeView<>(); + treePluginNode = new FilterableTreeItem<>("(all)"); + treeFileRootNode = new FilterableTreeItem<>("(all)"); + + pluginTreeView.setCellFactory(new Callback, TreeCell>() { + @Override + public TreeCell call(TreeView p) { + return new PluginTreeCell(getApplicationDefaults(), pluginService); + } + }); + + pluginTreeView.setRoot(treePluginNode); + + // Binds search property to plugin tree filter + treePluginNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { + if (search.getValue() == null || search.getValue().isEmpty()) { + return null; + } + return (item) -> { + if (item instanceof Plugin) { + Plugin plugin = (Plugin) item; + return plugin.getName().toLowerCase().contains(search.getValue().toLowerCase()) + || (plugin.getCategory() != null && plugin.getCategory().toLowerCase().contains(search.getValue().toLowerCase())); + } else { + return item.toString().toLowerCase().contains(search.getValue().toLowerCase()); + } + }; + }, search)); + + // Binds search property to file tree filter + treeFileRootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { + if (search.getValue() == null || search.getValue().isEmpty()) { + return null; + } + return (item) -> { + if (item instanceof Plugin) { + Plugin plugin = (Plugin) item; + return plugin.getName().toLowerCase().contains(search.getValue().toLowerCase()) + || (plugin.getCategory() != null && plugin.getCategory().toLowerCase().contains(search.getValue().toLowerCase())); + } else { + return item.toString().toLowerCase().contains(search.getValue().toLowerCase()); + } + }; + }, search)); + + } + + public void refresh() { + pluginTreeView.refresh(); + } + + public SimpleStringProperty searchProperty() { + return this.search; + } + + public TreeView getTreeViewNode() { + return pluginTreeView; + } + + public void setDisplay(Display display) { + if (Display.DirectoryTree.equals(display)) { + pluginTreeView.setRoot(treeFileRootNode); + } else if (Display.FlatTree.equals(display)) { + pluginTreeView.setRoot(treePluginNode); + } + } + + /** + * Refreshes displayed plugins in tree views. + */ + public void clearAndFillPluginTree(Iterable plugins) { + + treePluginNode.getInternalChildren().clear(); + + + for (Plugin plugin : plugins) { + + FilterableTreeItem item = new FilterableTreeItem(plugin); + treePluginNode.getInternalChildren().add(item); + + // Display subcomponents in the plugin tree + if (plugin.getComponents().size() > 1) { + for (PluginComponent component : plugin.getComponents()) { + FilterableTreeItem compItem = new FilterableTreeItem<>(component); + item.getInternalChildren().add(compItem); + } + } + } + + treePluginNode.setExpanded(true); + + treeFileRootNode.getInternalChildren().clear(); + + generatePluginTree(plugins); + + Set userPluginDirectories = new HashSet<>(); + ApplicationPreferences prefs = this.getPreferences(); + if (prefs.getBoolean(ApplicationDefaults.VST2_DISCOVERY_ENABLED_KEY, false) + && !prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, "").isBlank()) { + String path = prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, ""); + userPluginDirectories.add(FileUtils.convertPath(path)); + userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.VST2_EXTRA_DIRECTORY_KEY)); + } + + if (prefs.getBoolean(ApplicationDefaults.VST3_DISCOVERY_ENABLED_KEY, false) + && !prefs.get(ApplicationDefaults.VST3_DIRECTORY_KEY, "").isBlank()) { + String path = prefs.get(ApplicationDefaults.VST3_DIRECTORY_KEY, ""); + userPluginDirectories.add(FileUtils.convertPath(path)); + userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.VST3_EXTRA_DIRECTORY_KEY)); + } + + if (prefs.getBoolean(ApplicationDefaults.AU_DISCOVERY_ENABLED_KEY, false) + && !prefs.get(ApplicationDefaults.AU_DIRECTORY_KEY, "").isBlank()) { + String path = prefs.get(ApplicationDefaults.AU_DIRECTORY_KEY, ""); + userPluginDirectories.add(FileUtils.convertPath(path)); + userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.AU_EXTRA_DIRECTORY_KEY)); + } + + if (prefs.getBoolean(ApplicationDefaults.LV2_DISCOVERY_ENABLED_KEY, false) + && !prefs.get(ApplicationDefaults.LV2_DIRECTORY_KEY, "").isBlank()) { + String path = prefs.get(ApplicationDefaults.LV2_DIRECTORY_KEY, ""); + userPluginDirectories.add(FileUtils.convertPath(path)); + userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.LV2_EXTRA_DIRECTORY_KEY)); + } + + for (String directory : userPluginDirectories) { + treeFileRootNode.getInternalChildren().add(initDirectoryRoot(pluginTree, directory)); + } + + treeFileRootNode.setExpanded(true); + + } + + /** + * Generates a PluginTree representation. [rootDir -> [ subDir1 -> [ plugin1 -> + * [ ] ], subDir2 -> [ plugin2 -> [] , plugin3 -> [] ]] ] + * + */ + private void generatePluginTree(Iterable plugins) { + + pluginTree = new PluginTreeViewController.FileTree(); + + for (Plugin plug : plugins) { + PluginTreeViewController.FileTree node = pluginTree; + String[] subDirs = plug.getPath().split("/"); + String currentPath = ""; + for (int i = 0; i < subDirs.length; i++) { + currentPath = currentPath + subDirs[i] + "/"; + String segment = subDirs[i]; + PluginTreeViewController.FileTree ft = new PluginTreeViewController.FileTree(); + + if (node.get(segment) == null) { + // Node is a plugin (End of branch) + if (i == subDirs.length - 1) { + ft.setNodeValue(plug); + + // Node is a directory + } else { + // TODO Should be optimized for large plugin set + List localPluginList = new ArrayList(); + for (Plugin p : plugins) { + if (p.getPath().startsWith(currentPath)) { + localPluginList.add(p); + } + } + + // Retrieve Symlink if exist + // TODO: This can be refactored to prevent trailing slash removal + Symlink symlink = symlinkDAO.findByPath(currentPath.substring(0, currentPath.length() - 1)); + if (symlink != null) { + symlink.setPluginList(localPluginList); + ft.setNodeValue(symlink); + } else { + PluginDirectory directory = new PluginDirectory(); + directory.setName(segment); + directory.setPath(currentPath); + directory.setPluginList(localPluginList); + ft.setNodeValue(directory); + } + + } + node.put(segment, ft); + } + node = node.get(segment); + } + } + } + + private FilterableTreeItem initDirectoryRoot(PluginTreeViewController.FileTree pluginTree, String directoryPath) { + + FilterableTreeItem item = new FilterableTreeItem<>(null); + item.setExpanded(true); + + PluginTreeViewController.FileTree treeHead = pluginTree; + String[] directories = directoryPath.split("/"); + + for (String dir : directories) { + if (treeHead != null) { + treeHead = treeHead.get(dir); + } + } + + if (treeHead != null && treeHead.getNodeValue() instanceof PluginDirectory) { + PluginDirectory directory = (PluginDirectory) treeHead.getNodeValue(); + directory.setRootDirectory(true); + item.setValue(directory); + buildDirectoryTree(treeHead, item, ""); + } + + return item; + + } + + /** + * Builds the directory tree view using filetree representation. If some + * directories contains only one subdirectory and nothing else, they are merged + * together in one node. + * + * @param pluginTree File tree representation + * @param node root tree node + * @param mergedParent Name of merged parent tree + */ + private void buildDirectoryTree(PluginTreeViewController.FileTree pluginTree, FilterableTreeItem node, String mergedParent) { + + String mergedParentName = mergedParent; + node.setExpanded(true); + + if (mergedParentName == null) { + mergedParentName = ""; + } + + // For each subdirectory (aka child nodes) + for (String dir : pluginTree.keySet()) { + PluginTreeViewController.FileTree child = pluginTree.get(dir); + // If child is empty then we have reached a plugin and we can't go deeper + if (child.values().isEmpty()) { + Plugin plugin = (Plugin) child.getNodeValue(); + FilterableTreeItem plugItem = new FilterableTreeItem<>(plugin); + node.getInternalChildren().add(plugItem); + + // Display subcomponents in the directory tree + if (plugin.getComponents().size() > 1) { + for (PluginComponent component : plugin.getComponents()) { + FilterableTreeItem compItem = new FilterableTreeItem<>(component); + plugItem.getInternalChildren().add(compItem); + } + } + + // If not we are exploring a directory + } else { + IDirectory directory; + // If child node contains only one directory we can merge it with the child node + if (child.size() == 1 && ((PluginTreeViewController.FileTree) child.values().toArray()[0]).getNodeValue() instanceof PluginDirectory + && !(node.getValue() instanceof Symlink) + && !(child.getNodeValue() instanceof Symlink)) { + + directory = (IDirectory) child.getNodeValue(); + mergedParentName = mergedParentName + directory.getName() + "/"; + + buildDirectoryTree(child, node, mergedParentName); + // We don't want to merge next directories in the current iteration + mergedParentName = ""; + + // In case our child cannot be merged (contains not only one subdirectory) + } else { + directory = (IDirectory) child.getNodeValue(); + directory.setDisplayName(mergedParentName + directory.getName()); + + // We don't want to merge next directories in the current iteration + mergedParentName = ""; + FilterableTreeItem item = new FilterableTreeItem<>(directory); + node.getInternalChildren().add(item); + buildDirectoryTree(child, item, mergedParentName); + } + } + } + } + + public void selectPluginInTreeById(long id) { + List items = getAllChildrens(pluginTreeView.getRoot()); + + for (TreeItem item : items) { + if (item.getValue() instanceof Plugin plugin + && plugin.getId().equals(id)) { + int row = pluginTreeView.getRow(item); + pluginTreeView.getSelectionModel().select(row); + } + } + + } + + private List getAllChildrens(TreeItem item) { + List items = new ArrayList<>(); + items.add(item); + + List childs = new ArrayList<>(item.getChildren()); + for (TreeItem child : childs) { + items.addAll(getAllChildrens(child)); + } + return items; + } + + class FileTree extends HashMap { + + private Object nodeValue; + + public void setNodeValue(Object nodeValue) { + this.nodeValue = nodeValue; + } + + public Object getNodeValue() { + return nodeValue; + } + } + + enum Display { + DirectoryTree, FlatTree + } + +} diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index 4de94ef1..782aec9e 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -18,36 +18,20 @@ package com.owlplug.core.controllers; -import com.owlplug.core.components.ApplicationDefaults; -import com.owlplug.core.components.ApplicationPreferences; import com.owlplug.core.components.CoreTaskFactory; import com.owlplug.core.controllers.dialogs.ExportDialogController; import com.owlplug.core.controllers.dialogs.NewLinkController; import com.owlplug.core.dao.PluginDAO; -import com.owlplug.core.dao.SymlinkDAO; -import com.owlplug.core.model.IDirectory; import com.owlplug.core.model.Plugin; -import com.owlplug.core.model.PluginComponent; -import com.owlplug.core.model.PluginDirectory; -import com.owlplug.core.model.Symlink; import com.owlplug.core.services.PluginService; import com.owlplug.core.ui.FilterableTreeItem; -import com.owlplug.core.ui.PluginTreeCell; -import com.owlplug.core.utils.FileUtils; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import javafx.beans.binding.Bindings; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TabPane; import javafx.scene.control.TextField; -import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; -import javafx.scene.control.TreeView; -import javafx.util.Callback; +import javafx.scene.layout.VBox; +import org.controlsfx.control.tableview2.FilteredTableView; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import jfxtras.styles.jmetro.JMetroStyleClass; @@ -60,8 +44,6 @@ public class PluginsController extends BaseController { @Autowired private PluginDAO pluginDAO; @Autowired - private SymlinkDAO symlinkDAO; - @Autowired private NodeInfoController nodeInfoController; @Autowired private NewLinkController newLinkController; @@ -69,24 +51,25 @@ public class PluginsController extends BaseController { private ExportDialogController exportDialogController; @Autowired protected CoreTaskFactory taskFactory; + @Autowired + protected PluginTreeViewController treeViewController; @FXML private Button syncButton; @FXML private Button exportButton; @FXML - private TreeView pluginTreeView; - @FXML private TabPane pluginTreeViewTabPane; @FXML private TextField searchTextField; @FXML private Button newLinkButton; - - private Iterable pluginList; - private FileTree pluginTree; - private FilterableTreeItem treePluginNode; - private FilterableTreeItem treeFileRootNode; + @FXML + private VBox pluginInfoPane; + @FXML + private VBox pluginsContainer; + @FXML + private FilteredTableView pluginTableView; /** * FXML initialize method. @@ -98,70 +81,50 @@ public void initialize() { newLinkController.show(); }); - treePluginNode = new FilterableTreeItem<>("(all)"); - treeFileRootNode = new FilterableTreeItem<>("(all)"); - - pluginTreeView.setCellFactory(new Callback, TreeCell>() { - @Override - public TreeCell call(TreeView p) { - return new PluginTreeCell(getApplicationDefaults(), pluginService); - } - }); - pluginTreeView.setRoot(treePluginNode); - - clearAndFillPluginTree(); + pluginsContainer.getChildren().add(treeViewController.getTreeViewNode()); // Dispatches treeView selection event to the nodeInfoController - pluginTreeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + treeViewController.getTreeViewNode().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { if (newValue != null) { TreeItem selectedItem = newValue; nodeInfoController.setNode(selectedItem.getValue()); } }); + treeViewController.searchProperty().bind(searchTextField.textProperty()); + pluginTreeViewTabPane.getStyleClass().add(JMetroStyleClass.UNDERLINE_TAB_PANE); // Handles tabPane selection event and toggles displayed treeView pluginTreeViewTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { if (newTab.getId().equals("treeTabAll")) { - pluginTreeView.setRoot(treePluginNode); + treeViewController.setDisplay(PluginTreeViewController.Display.FlatTree); + // TODO setVisible / managed in subcontroller + treeViewController.getTreeViewNode().setVisible(true); + treeViewController.getTreeViewNode().setManaged(true); + pluginInfoPane.setManaged(true); + pluginInfoPane.setVisible(true); + pluginTableView.setManaged(false); + pluginTableView.setVisible(false); + } else if (newTab.getId().equals("treeTabDirectories")) { + treeViewController.setDisplay(PluginTreeViewController.Display.DirectoryTree); + // TODO setVisible / managed in subcontroller + treeViewController.getTreeViewNode().setManaged(true); + treeViewController.getTreeViewNode().setVisible(true); + pluginInfoPane.setManaged(true); + pluginInfoPane.setVisible(true); + pluginTableView.setManaged(false); + pluginTableView.setVisible(false); } else { - pluginTreeView.setRoot(treeFileRootNode); + treeViewController.getTreeViewNode().setManaged(false); + treeViewController.getTreeViewNode().setVisible(false); + pluginInfoPane.setManaged(false); + pluginInfoPane.setVisible(false); + pluginTableView.setManaged(true); + pluginTableView.setVisible(true); } }); - // Binds search property to plugin tree filter - treePluginNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { - if (searchTextField.getText() == null || searchTextField.getText().isEmpty()) { - return null; - } - return (item) -> { - if (item instanceof Plugin) { - Plugin plugin = (Plugin) item; - return plugin.getName().toLowerCase().contains(searchTextField.getText().toLowerCase()) - || (plugin.getCategory() != null && plugin.getCategory().toLowerCase().contains(searchTextField.getText().toLowerCase())); - } else { - return item.toString().toLowerCase().contains(searchTextField.getText().toLowerCase()); - } - }; - }, searchTextField.textProperty())); - - // Binds search property to file tree filter - treeFileRootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> { - if (searchTextField.getText() == null || searchTextField.getText().isEmpty()) { - return null; - } - return (item) -> { - if (item instanceof Plugin) { - Plugin plugin = (Plugin) item; - return plugin.getName().toLowerCase().contains(searchTextField.getText().toLowerCase()) - || (plugin.getCategory() != null && plugin.getCategory().toLowerCase().contains(searchTextField.getText().toLowerCase())); - } else { - return item.toString().toLowerCase().contains(searchTextField.getText().toLowerCase()); - } - }; - }, searchTextField.textProperty())); - syncButton.setOnAction(e -> { this.getAnalyticsService().pageView("/app/core/action/syncPlugins"); pluginService.syncPlugins(); @@ -173,258 +136,21 @@ public TreeCell call(TreeView p) { exportDialogController.show(); }); - } - - public void refreshPluginTree() { - pluginTreeView.refresh(); - } - - /** - * Refreshes displayed plugins in tree views. - */ - public void clearAndFillPluginTree() { - - treePluginNode.getInternalChildren().clear(); - this.pluginList = pluginDAO.findAll(); - - for (Plugin plugin : pluginList) { - - FilterableTreeItem item = new FilterableTreeItem(plugin); - treePluginNode.getInternalChildren().add(item); - - // Display subcomponents in the plugin tree - if (plugin.getComponents().size() > 1) { - for (PluginComponent component : plugin.getComponents()) { - FilterableTreeItem compItem = new FilterableTreeItem<>(component); - item.getInternalChildren().add(compItem); - } - } - } - - treePluginNode.setExpanded(true); - - treeFileRootNode.getInternalChildren().clear(); - - generatePluginTree(); - - Set userPluginDirectories = new HashSet<>(); - ApplicationPreferences prefs = this.getPreferences(); - if (prefs.getBoolean(ApplicationDefaults.VST2_DISCOVERY_ENABLED_KEY, false) - && !prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, "").isBlank()) { - String path = prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, ""); - userPluginDirectories.add(FileUtils.convertPath(path)); - userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.VST2_EXTRA_DIRECTORY_KEY)); - } - - if (prefs.getBoolean(ApplicationDefaults.VST3_DISCOVERY_ENABLED_KEY, false) - && !prefs.get(ApplicationDefaults.VST3_DIRECTORY_KEY, "").isBlank()) { - String path = prefs.get(ApplicationDefaults.VST3_DIRECTORY_KEY, ""); - userPluginDirectories.add(FileUtils.convertPath(path)); - userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.VST3_EXTRA_DIRECTORY_KEY)); - } - - if (prefs.getBoolean(ApplicationDefaults.AU_DISCOVERY_ENABLED_KEY, false) - && !prefs.get(ApplicationDefaults.AU_DIRECTORY_KEY, "").isBlank()) { - String path = prefs.get(ApplicationDefaults.AU_DIRECTORY_KEY, ""); - userPluginDirectories.add(FileUtils.convertPath(path)); - userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.AU_EXTRA_DIRECTORY_KEY)); - } - - if (prefs.getBoolean(ApplicationDefaults.LV2_DISCOVERY_ENABLED_KEY, false) - && !prefs.get(ApplicationDefaults.LV2_DIRECTORY_KEY, "").isBlank()) { - String path = prefs.get(ApplicationDefaults.LV2_DIRECTORY_KEY, ""); - userPluginDirectories.add(FileUtils.convertPath(path)); - userPluginDirectories.addAll(prefs.getList(ApplicationDefaults.LV2_EXTRA_DIRECTORY_KEY)); - } - - for (String directory : userPluginDirectories) { - treeFileRootNode.getInternalChildren().add(initDirectoryRoot(pluginTree, directory)); - } - - treeFileRootNode.setExpanded(true); + this.clearAndFillPluginTree(); } - /** - * Generates a PluginTree representation. [rootDir -> [ subDir1 -> [ plugin1 -> - * [ ] ], subDir2 -> [ plugin2 -> [] , plugin3 -> [] ]] ] - * - */ - private void generatePluginTree() { - - pluginTree = new FileTree(); - - for (Plugin plug : pluginList) { - FileTree node = pluginTree; - String[] subDirs = plug.getPath().split("/"); - String currentPath = ""; - for (int i = 0; i < subDirs.length; i++) { - currentPath = currentPath + subDirs[i] + "/"; - String segment = subDirs[i]; - FileTree ft = new FileTree(); - - if (node.get(segment) == null) { - // Node is a plugin (End of branch) - if (i == subDirs.length - 1) { - ft.setNodeValue(plug); - - // Node is a directory - } else { - // TODO Should be optimized for large plugin set - List localPluginList = new ArrayList(); - for (Plugin p : pluginList) { - if (p.getPath().startsWith(currentPath)) { - localPluginList.add(p); - } - } - - // Retrieve Symlink if exist - // TODO: This can be refactored to prevent trailing slash removal - Symlink symlink = symlinkDAO.findByPath(currentPath.substring(0, currentPath.length() - 1)); - if (symlink != null) { - symlink.setPluginList(localPluginList); - ft.setNodeValue(symlink); - } else { - PluginDirectory directory = new PluginDirectory(); - directory.setName(segment); - directory.setPath(currentPath); - directory.setPluginList(localPluginList); - ft.setNodeValue(directory); - } - - } - node.put(segment, ft); - } - node = node.get(segment); - } - } - } - - private FilterableTreeItem initDirectoryRoot(FileTree pluginTree, String directoryPath) { - - FilterableTreeItem item = new FilterableTreeItem<>(null); - item.setExpanded(true); - - FileTree treeHead = pluginTree; - String[] directories = directoryPath.split("/"); - - for (String dir : directories) { - if (treeHead != null) { - treeHead = treeHead.get(dir); - } - } - - if (treeHead != null && treeHead.getNodeValue() instanceof PluginDirectory) { - PluginDirectory directory = (PluginDirectory) treeHead.getNodeValue(); - directory.setRootDirectory(true); - item.setValue(directory); - buildDirectoryTree(treeHead, item, ""); - } - - return item; - - } - - /** - * Builds the directory tree view using filetree representation. If some - * directories contains only one subdirectory and nothing else, they are merged - * together in one node. - * - * @param pluginTree File tree representation - * @param node root tree node - * @param mergedParent Name of merged parent tree - */ - private void buildDirectoryTree(FileTree pluginTree, FilterableTreeItem node, String mergedParent) { - - String mergedParentName = mergedParent; - node.setExpanded(true); - - if (mergedParentName == null) { - mergedParentName = ""; - } - - // For each subdirectory (aka child nodes) - for (String dir : pluginTree.keySet()) { - FileTree child = pluginTree.get(dir); - // If child is empty then we have reached a plugin and we can't go deeper - if (child.values().isEmpty()) { - Plugin plugin = (Plugin) child.getNodeValue(); - FilterableTreeItem plugItem = new FilterableTreeItem<>(plugin); - node.getInternalChildren().add(plugItem); - - // Display subcomponents in the directory tree - if (plugin.getComponents().size() > 1) { - for (PluginComponent component : plugin.getComponents()) { - FilterableTreeItem compItem = new FilterableTreeItem<>(component); - plugItem.getInternalChildren().add(compItem); - } - } - - // If not we are exploring a directory - } else { - IDirectory directory; - // If child node contains only one directory we can merge it with the child node - if (child.size() == 1 && ((FileTree) child.values().toArray()[0]).getNodeValue() instanceof PluginDirectory - && !(node.getValue() instanceof Symlink) - && !(child.getNodeValue() instanceof Symlink)) { - - directory = (IDirectory) child.getNodeValue(); - mergedParentName = mergedParentName + directory.getName() + "/"; - - buildDirectoryTree(child, node, mergedParentName); - // We don't want to merge next directories in the current iteration - mergedParentName = ""; - - // In case our child cannot be merged (contains not only one subdirectory) - } else { - directory = (IDirectory) child.getNodeValue(); - directory.setDisplayName(mergedParentName + directory.getName()); - - // We don't want to merge next directories in the current iteration - mergedParentName = ""; - FilterableTreeItem item = new FilterableTreeItem<>(directory); - node.getInternalChildren().add(item); - buildDirectoryTree(child, item, mergedParentName); - } - } - } + public void clearAndFillPluginTree() { + Iterable plugins = pluginDAO.findAll(); + treeViewController.clearAndFillPluginTree(plugins); } public void selectPluginInTreeById(long id) { - List items = getAllChildrens(pluginTreeView.getRoot()); - - for (TreeItem item : items) { - if (item.getValue() instanceof Plugin plugin - && plugin.getId().equals(id)) { - int row = pluginTreeView.getRow(item); - pluginTreeView.getSelectionModel().select(row); - } - } - + treeViewController.selectPluginInTreeById(id); } - - private List getAllChildrens(TreeItem item) { - List items = new ArrayList<>(); - items.add(item); - - List childs = new ArrayList<>(item.getChildren()); - for (TreeItem child : childs) { - items.addAll(getAllChildrens(child)); - } - return items; - } - - class FileTree extends HashMap { - - private Object nodeValue; - - public void setNodeValue(Object nodeValue) { - this.nodeValue = nodeValue; - } - - public Object getNodeValue() { - return nodeValue; - } + + public void refreshPluginTree() { + treeViewController.refresh(); } } diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index 6505b9e1..964071bb 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -14,13 +14,48 @@ + + -
+ + + + + + + + + +
- + + - + +
@@ -29,53 +64,20 @@ + - - - - - - - -
- + - - - - - - - + From a599ec4f2694a3b3f035ecdec8a15075c5168b04 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Thu, 5 Dec 2024 00:04:46 +0100 Subject: [PATCH 02/15] feat: add table view controller --- .../controllers/PluginTableController.java | 96 +++++++++++++++++++ .../core/controllers/PluginsController.java | 21 ++-- .../src/main/resources/fxml/PluginsView.fxml | 3 - 3 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java new file mode 100644 index 00000000..16cdac5e --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -0,0 +1,96 @@ +/* OwlPlug + * Copyright (C) 2021 Arthur + * + * This file is part of OwlPlug. + * + * OwlPlug is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 + * as published by the Free Software Foundation. + * + * OwlPlug is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OwlPlug. If not, see . + */ + +package com.owlplug.core.controllers; + +import com.owlplug.core.model.Plugin; +import com.owlplug.core.model.PluginFormat; +import com.owlplug.project.model.DawPlugin; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.image.ImageView; +import org.controlsfx.control.tableview2.FilteredTableView; +import org.controlsfx.control.tableview2.TableColumn2; +import org.springframework.stereotype.Controller; + +@Controller +public class PluginTableController extends BaseController { + + private TableView tableView; + + private ObservableList pluginList; + + public PluginTableController() { + tableView = new TableView<>(); + + TableColumn nameColumn = new TableColumn<>("Name"); + nameColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getName())); + TableColumn formatColumn = new TableColumn<>("Format"); + formatColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue().getFormat())); + formatColumn.setCellFactory(e -> new TableCell<>() { + @Override + public void updateItem(PluginFormat item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setText(null); + setGraphic(null); + } else { + setText(item.getText()); + setGraphic(new ImageView(getApplicationDefaults().getPluginFormatIcon(item))); + } + } + }); + TableColumn manufacturerColumn = new TableColumn<>("Manufacturer"); + manufacturerColumn.setCellValueFactory(cellData -> + new SimpleStringProperty(cellData.getValue().getManufacturerName())); + TableColumn versionColumn = new TableColumn<>("Version"); + versionColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getVersion())); + TableColumn categoryColumn = new TableColumn<>("Category"); + categoryColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getCategory())); + + tableView.getColumns().addAll(formatColumn, nameColumn, versionColumn, manufacturerColumn, categoryColumn); + + pluginList = FXCollections.observableArrayList(); + tableView.setItems(pluginList); + + } + + public void displayPlugins(Iterable plugins) { + pluginList.removeAll(); + plugins.forEach(pluginList::add); + } + + public TableView getTableView() { + return tableView; + + } + + public void refresh() { + tableView.refresh(); + } + + +} + + + diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index 782aec9e..ab5713a4 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -24,14 +24,12 @@ import com.owlplug.core.dao.PluginDAO; import com.owlplug.core.model.Plugin; import com.owlplug.core.services.PluginService; -import com.owlplug.core.ui.FilterableTreeItem; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TabPane; import javafx.scene.control.TextField; import javafx.scene.control.TreeItem; import javafx.scene.layout.VBox; -import org.controlsfx.control.tableview2.FilteredTableView; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import jfxtras.styles.jmetro.JMetroStyleClass; @@ -53,6 +51,8 @@ public class PluginsController extends BaseController { protected CoreTaskFactory taskFactory; @Autowired protected PluginTreeViewController treeViewController; + @Autowired + protected PluginTableController tableController; @FXML private Button syncButton; @@ -68,8 +68,6 @@ public class PluginsController extends BaseController { private VBox pluginInfoPane; @FXML private VBox pluginsContainer; - @FXML - private FilteredTableView pluginTableView; /** * FXML initialize method. @@ -82,6 +80,7 @@ public void initialize() { }); pluginsContainer.getChildren().add(treeViewController.getTreeViewNode()); + pluginsContainer.getChildren().add(tableController.getTableView()); // Dispatches treeView selection event to the nodeInfoController treeViewController.getTreeViewNode().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { @@ -104,8 +103,8 @@ public void initialize() { treeViewController.getTreeViewNode().setManaged(true); pluginInfoPane.setManaged(true); pluginInfoPane.setVisible(true); - pluginTableView.setManaged(false); - pluginTableView.setVisible(false); + tableController.getTableView().setManaged(false); + tableController.getTableView().setVisible(false); } else if (newTab.getId().equals("treeTabDirectories")) { treeViewController.setDisplay(PluginTreeViewController.Display.DirectoryTree); // TODO setVisible / managed in subcontroller @@ -113,15 +112,15 @@ public void initialize() { treeViewController.getTreeViewNode().setVisible(true); pluginInfoPane.setManaged(true); pluginInfoPane.setVisible(true); - pluginTableView.setManaged(false); - pluginTableView.setVisible(false); + tableController.getTableView().setManaged(false); + tableController.getTableView().setVisible(false); } else { treeViewController.getTreeViewNode().setManaged(false); treeViewController.getTreeViewNode().setVisible(false); pluginInfoPane.setManaged(false); pluginInfoPane.setVisible(false); - pluginTableView.setManaged(true); - pluginTableView.setVisible(true); + tableController.getTableView().setManaged(true); + tableController.getTableView().setVisible(true); } }); @@ -143,6 +142,7 @@ public void initialize() { public void clearAndFillPluginTree() { Iterable plugins = pluginDAO.findAll(); treeViewController.clearAndFillPluginTree(plugins); + tableController.displayPlugins(plugins); } public void selectPluginInTreeById(long id) { @@ -151,6 +151,7 @@ public void selectPluginInTreeById(long id) { public void refreshPluginTree() { treeViewController.refresh(); + tableController.refresh(); } } diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index 964071bb..bb5206fe 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -52,9 +52,6 @@
- - -
From 52665c85e8cb931a71f142304fce2b89a35808e1 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Sun, 8 Dec 2024 19:02:33 +0100 Subject: [PATCH 03/15] chore: refactor and align plugins display controllers --- .../controllers/PluginInfoController.java | 8 ++-- .../controllers/PluginTableController.java | 5 +- .../controllers/PluginTreeViewController.java | 48 ++++++++++++------- .../core/controllers/PluginsController.java | 32 ++++++------- 4 files changed, 51 insertions(+), 42 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java index d479447e..8e39a438 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java @@ -130,7 +130,7 @@ public void initialize() { } else { pluginService.disablePlugin(currentPlugin); setPlugin(currentPlugin); - pluginsController.refreshPluginTree(); + pluginsController.refresh(); } }); @@ -138,7 +138,7 @@ public void initialize() { enableButton.setOnAction(e -> { pluginService.enablePlugin(currentPlugin); setPlugin(currentPlugin); - pluginsController.refreshPluginTree(); + pluginsController.refresh(); }); pluginComponentListView.setCellFactory(new PluginComponentCellFactory(this.getApplicationDefaults())); @@ -236,7 +236,7 @@ private void showUninstallDialog() { removeButton.setOnAction(removeEvent -> { dialog.close(); coreTaskFactory.createPluginRemoveTask(currentPlugin) - .setOnSucceeded(x -> pluginsController.clearAndFillPluginTree()).schedule(); + .setOnSucceeded(x -> pluginsController.displayPlugins()).schedule(); }); removeButton.getStyleClass().add("button-danger"); @@ -283,7 +283,7 @@ private void showDisableDialog() { disableButton.setOnAction(removeEvent -> { pluginService.disablePlugin(currentPlugin); setPlugin(currentPlugin); - pluginsController.refreshPluginTree(); + pluginsController.refresh(); dialog.close(); }); diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index 16cdac5e..e5a56d75 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -20,7 +20,6 @@ import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginFormat; -import com.owlplug.project.model.DawPlugin; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; @@ -29,8 +28,6 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.image.ImageView; -import org.controlsfx.control.tableview2.FilteredTableView; -import org.controlsfx.control.tableview2.TableColumn2; import org.springframework.stereotype.Controller; @Controller @@ -75,7 +72,7 @@ public void updateItem(PluginFormat item, boolean empty) { } - public void displayPlugins(Iterable plugins) { + public void setPlugins(Iterable plugins) { pluginList.removeAll(); plugins.forEach(pluginList::add); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java index 85b2e7f2..1261d74a 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java @@ -52,11 +52,13 @@ public class PluginTreeViewController extends BaseController { @Autowired private SymlinkDAO symlinkDAO; - private SimpleStringProperty search = new SimpleStringProperty(); - private TreeView pluginTreeView; + private final SimpleStringProperty search = new SimpleStringProperty(); + private final TreeView pluginTreeView; + private final FilterableTreeItem treePluginNode; + private final FilterableTreeItem treeFileRootNode; + private PluginTreeViewController.FileTree pluginTree; - private FilterableTreeItem treePluginNode; - private FilterableTreeItem treeFileRootNode; + public PluginTreeViewController() { pluginTreeView = new TreeView<>(); @@ -106,19 +108,19 @@ public TreeCell call(TreeView p) { } - public void refresh() { - pluginTreeView.refresh(); - } - public SimpleStringProperty searchProperty() { return this.search; } - public TreeView getTreeViewNode() { + public TreeView getTreeView() { return pluginTreeView; } - public void setDisplay(Display display) { + public void refresh() { + pluginTreeView.refresh(); + } + + public void setDisplayMode(Display display) { if (Display.DirectoryTree.equals(display)) { pluginTreeView.setRoot(treeFileRootNode); } else if (Display.FlatTree.equals(display)) { @@ -126,10 +128,14 @@ public void setDisplay(Display display) { } } + public void setPlugins(Iterable plugins) { + this.clearAndFillPluginTree(plugins); + } + /** * Refreshes displayed plugins in tree views. */ - public void clearAndFillPluginTree(Iterable plugins) { + private void clearAndFillPluginTree(Iterable plugins) { treePluginNode.getInternalChildren().clear(); @@ -193,8 +199,14 @@ public void clearAndFillPluginTree(Iterable plugins) { } /** - * Generates a PluginTree representation. [rootDir -> [ subDir1 -> [ plugin1 -> - * [ ] ], subDir2 -> [ plugin2 -> [] , plugin3 -> [] ]] ] + * Generates a PluginTree representation. + *
+   * [rootDir ->
+   *   [ subDir1 -> [ plugin1 -> [] ],
+   *     subDir2 -> [ plugin2 -> [] , plugin3 -> [] ]
+   *   ]
+   * ]
+   * 
* */ private void generatePluginTree(Iterable plugins) { @@ -338,7 +350,7 @@ private void buildDirectoryTree(PluginTreeViewController.FileTree pluginTree, Fi } public void selectPluginInTreeById(long id) { - List items = getAllChildrens(pluginTreeView.getRoot()); + List items = getNestedChildren(pluginTreeView.getRoot()); for (TreeItem item : items) { if (item.getValue() instanceof Plugin plugin @@ -350,13 +362,13 @@ public void selectPluginInTreeById(long id) { } - private List getAllChildrens(TreeItem item) { + private List getNestedChildren(TreeItem item) { List items = new ArrayList<>(); items.add(item); - List childs = new ArrayList<>(item.getChildren()); - for (TreeItem child : childs) { - items.addAll(getAllChildrens(child)); + List children = new ArrayList<>(item.getChildren()); + for (TreeItem child : children) { + items.addAll(getNestedChildren(child)); } return items; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index ab5713a4..07ccc616 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -79,11 +79,11 @@ public void initialize() { newLinkController.show(); }); - pluginsContainer.getChildren().add(treeViewController.getTreeViewNode()); + pluginsContainer.getChildren().add(treeViewController.getTreeView()); pluginsContainer.getChildren().add(tableController.getTableView()); // Dispatches treeView selection event to the nodeInfoController - treeViewController.getTreeViewNode().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + treeViewController.getTreeView().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { if (newValue != null) { TreeItem selectedItem = newValue; nodeInfoController.setNode(selectedItem.getValue()); @@ -97,26 +97,26 @@ public void initialize() { // Handles tabPane selection event and toggles displayed treeView pluginTreeViewTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { if (newTab.getId().equals("treeTabAll")) { - treeViewController.setDisplay(PluginTreeViewController.Display.FlatTree); + treeViewController.setDisplayMode(PluginTreeViewController.Display.FlatTree); // TODO setVisible / managed in subcontroller - treeViewController.getTreeViewNode().setVisible(true); - treeViewController.getTreeViewNode().setManaged(true); + treeViewController.getTreeView().setVisible(true); + treeViewController.getTreeView().setManaged(true); pluginInfoPane.setManaged(true); pluginInfoPane.setVisible(true); tableController.getTableView().setManaged(false); tableController.getTableView().setVisible(false); } else if (newTab.getId().equals("treeTabDirectories")) { - treeViewController.setDisplay(PluginTreeViewController.Display.DirectoryTree); + treeViewController.setDisplayMode(PluginTreeViewController.Display.DirectoryTree); // TODO setVisible / managed in subcontroller - treeViewController.getTreeViewNode().setManaged(true); - treeViewController.getTreeViewNode().setVisible(true); + treeViewController.getTreeView().setManaged(true); + treeViewController.getTreeView().setVisible(true); pluginInfoPane.setManaged(true); pluginInfoPane.setVisible(true); tableController.getTableView().setManaged(false); tableController.getTableView().setVisible(false); } else { - treeViewController.getTreeViewNode().setManaged(false); - treeViewController.getTreeViewNode().setVisible(false); + treeViewController.getTreeView().setManaged(false); + treeViewController.getTreeView().setVisible(false); pluginInfoPane.setManaged(false); pluginInfoPane.setVisible(false); tableController.getTableView().setManaged(true); @@ -129,27 +129,27 @@ public void initialize() { pluginService.syncPlugins(); }); - taskFactory.addSyncPluginsListener(() -> clearAndFillPluginTree()); + taskFactory.addSyncPluginsListener(this::displayPlugins); exportButton.setOnAction(e -> { exportDialogController.show(); }); - this.clearAndFillPluginTree(); + this.displayPlugins(); } - public void clearAndFillPluginTree() { + public void displayPlugins() { Iterable plugins = pluginDAO.findAll(); - treeViewController.clearAndFillPluginTree(plugins); - tableController.displayPlugins(plugins); + treeViewController.setPlugins(plugins); + tableController.setPlugins(plugins); } public void selectPluginInTreeById(long id) { treeViewController.selectPluginInTreeById(id); } - public void refreshPluginTree() { + public void refresh() { treeViewController.refresh(); tableController.refresh(); } From a648b8ba4c74efc20d30633e1860755a1de3f3a4 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Mon, 23 Dec 2024 23:49:29 +0100 Subject: [PATCH 04/15] feat: set plugins table and treeview vgrow --- .../com/owlplug/core/controllers/PluginTableController.java | 3 +++ .../com/owlplug/core/controllers/PluginTreeViewController.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index e5a56d75..30dcaca8 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -28,6 +28,8 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.image.ImageView; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; import org.springframework.stereotype.Controller; @Controller @@ -39,6 +41,7 @@ public class PluginTableController extends BaseController { public PluginTableController() { tableView = new TableView<>(); + VBox.setVgrow(tableView, Priority.ALWAYS); TableColumn nameColumn = new TableColumn<>("Name"); nameColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getName())); diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java index 1261d74a..80164520 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java @@ -40,6 +40,8 @@ import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; import javafx.util.Callback; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @@ -62,6 +64,7 @@ public class PluginTreeViewController extends BaseController { public PluginTreeViewController() { pluginTreeView = new TreeView<>(); + VBox.setVgrow(pluginTreeView, Priority.ALWAYS); treePluginNode = new FilterableTreeItem<>("(all)"); treeFileRootNode = new FilterableTreeItem<>("(all)"); From 407ff1c8ff58ca90b922dc0a2878ada65e43aa9f Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Mon, 30 Dec 2024 15:07:24 +0100 Subject: [PATCH 05/15] feat: add columns in plugin table and add scanDirectoryPath property --- .../core/components/ApplicationDefaults.java | 2 +- .../core/components/CoreTaskFactory.java | 21 ++---- .../controllers/PluginTableController.java | 64 ++++++++++++++++++- .../java/com/owlplug/core/model/Plugin.java | 15 +++-- .../owlplug/core/services/PluginService.java | 33 +++++++++- .../discovery/PluginFileCollector.java | 1 + .../fileformats/AuComponentFile.java | 7 +- .../discovery/fileformats/Lv2BundleFile.java | 7 +- .../discovery/fileformats/OsxVstFile.java | 9 +-- .../discovery/fileformats/PluginFile.java | 24 ++++++- .../discovery/fileformats/SoVstFile.java | 7 +- .../discovery/fileformats/Vst3BundleFile.java | 7 +- .../discovery/fileformats/Vst3DllFile.java | 7 +- .../discovery/fileformats/VstDllFile.java | 8 +-- .../com/owlplug/core/ui/PluginStateView.java | 4 ++ .../com/owlplug/core/ui/PluginTreeCell.java | 2 +- .../com/owlplug/core/utils/FileUtils.java | 22 +++++++ .../explore/services/ExploreService.java | 5 +- 18 files changed, 175 insertions(+), 70 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java b/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java index 2d618b52..05ec03c8 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java +++ b/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java @@ -68,7 +68,7 @@ public class ApplicationDefaults { public final Image tagImage = new Image(getClass().getResourceAsStream("/icons/tag-white-16.png")); public final Image symlinkImage = new Image(getClass().getResourceAsStream("/icons/folderlink-grey-16.png")); public final Image userImage = new Image(getClass().getResourceAsStream("/icons/user-white-32.png")); - public final Image rootDirectoryImage = new Image(getClass().getResourceAsStream("/icons/foldersearch-grey-16.png")); + public final Image scanDirectoryImage = new Image(getClass().getResourceAsStream("/icons/foldersearch-grey-16.png")); public final Image verifiedSourceImage = new Image(getClass().getResourceAsStream("/icons/doublecheck-grey-16.png")); public final Image suggestedSourceImage = new Image( ApplicationDefaults.class.getResourceAsStream("/icons/check-grey-16.png")); diff --git a/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java b/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java index 7d9548cc..39bf6d35 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java +++ b/owlplug-client/src/main/java/com/owlplug/core/components/CoreTaskFactory.java @@ -24,6 +24,7 @@ import com.owlplug.core.dao.SymlinkDAO; import com.owlplug.core.model.Plugin; import com.owlplug.core.services.NativeHostService; +import com.owlplug.core.services.PluginService; import com.owlplug.core.tasks.FileSyncTask; import com.owlplug.core.tasks.PluginRemoveTask; import com.owlplug.core.tasks.PluginSyncTask; @@ -48,6 +49,8 @@ public class CoreTaskFactory extends BaseTaskFactory { @Autowired private PluginDAO pluginDAO; @Autowired + private PluginService pluginService; + @Autowired private PluginFootprintDAO pluginFootprintDAO; @Autowired private SymlinkDAO symlinkDAO; @@ -122,24 +125,8 @@ public TaskExecutionContext createPluginSyncTask(String directoryScope) { } public TaskExecutionContext createFileStatSyncTask() { - Set directorySet = new TreeSet<>(); - if (prefs.getBoolean(ApplicationDefaults.VST2_DISCOVERY_ENABLED_KEY, false)) { - directorySet.add(prefs.get(ApplicationDefaults.VST_DIRECTORY_KEY, "")); - directorySet.addAll(prefs.getList(ApplicationDefaults.VST2_EXTRA_DIRECTORY_KEY)); - } - if (prefs.getBoolean(ApplicationDefaults.VST3_DISCOVERY_ENABLED_KEY, false)) { - directorySet.add(prefs.get(ApplicationDefaults.VST3_DIRECTORY_KEY, "")); - directorySet.addAll(prefs.getList(ApplicationDefaults.VST3_EXTRA_DIRECTORY_KEY)); - } - if (prefs.getBoolean(ApplicationDefaults.AU_DISCOVERY_ENABLED_KEY, false)) { - directorySet.add(prefs.get(ApplicationDefaults.AU_DIRECTORY_KEY, "")); - directorySet.addAll(prefs.getList(ApplicationDefaults.AU_EXTRA_DIRECTORY_KEY)); - } - if (prefs.getBoolean(ApplicationDefaults.LV2_DISCOVERY_ENABLED_KEY, false)) { - directorySet.add(prefs.get(ApplicationDefaults.LV2_DIRECTORY_KEY, "")); - directorySet.addAll(prefs.getList(ApplicationDefaults.LV2_EXTRA_DIRECTORY_KEY)); - } + Set directorySet = pluginService.getDirectoriesExplorationSet(); FileSyncTask task = new FileSyncTask(fileStatDAO, directorySet.stream().toList()); return create(task); diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index 30dcaca8..b7293993 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -20,6 +20,10 @@ import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginFormat; +import com.owlplug.core.model.PluginState; +import com.owlplug.core.services.PluginService; +import com.owlplug.core.ui.PluginStateView; +import com.owlplug.core.utils.FileUtils; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; @@ -30,15 +34,20 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class PluginTableController extends BaseController { + @Autowired + private PluginService pluginService; + private TableView tableView; private ObservableList pluginList; + public PluginTableController() { tableView = new TableView<>(); VBox.setVgrow(tableView, Priority.ALWAYS); @@ -67,8 +76,59 @@ public void updateItem(PluginFormat item, boolean empty) { versionColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getVersion())); TableColumn categoryColumn = new TableColumn<>("Category"); categoryColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getCategory())); + // Directory Column + TableColumn directoryColumn = new TableColumn<>("Directory"); + directoryColumn.setCellValueFactory(cellData -> new SimpleStringProperty( + FileUtils.getParentDirectoryName(cellData.getValue().getPath()))); + directoryColumn.setCellFactory(e -> new TableCell<>() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setText(null); + setGraphic(null); + } else { + setText(item); + setGraphic(new ImageView(getApplicationDefaults().directoryImage)); + } + } + }); + // Scan Directory Column + TableColumn scanDirectoryColumn = new TableColumn<>("Scan Dir."); + scanDirectoryColumn.setCellValueFactory(cellData -> new SimpleStringProperty( + FileUtils.getFilename(cellData.getValue().getScanDirectoryPath()))); + scanDirectoryColumn.setCellFactory(e -> new TableCell<>() { + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setText(null); + setGraphic(null); + } else { + setText(item); + setGraphic(new ImageView(getApplicationDefaults().scanDirectoryImage)); + } + } + }); + // Plugin State Column + TableColumn stateColumn = new TableColumn<>("State"); + stateColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>( + pluginService.getPluginState(cellData.getValue()))); + stateColumn.setCellFactory(e -> new TableCell<>() { + @Override + public void updateItem(PluginState item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setText(null); + setGraphic(null); + } else { + setGraphic(new PluginStateView(item)); + } + } + }); - tableView.getColumns().addAll(formatColumn, nameColumn, versionColumn, manufacturerColumn, categoryColumn); + tableView.getColumns().addAll(formatColumn, nameColumn, versionColumn, + manufacturerColumn, categoryColumn, directoryColumn, scanDirectoryColumn, stateColumn); pluginList = FXCollections.observableArrayList(); tableView.setItems(pluginList); @@ -76,7 +136,7 @@ public void updateItem(PluginFormat item, boolean empty) { } public void setPlugins(Iterable plugins) { - pluginList.removeAll(); + pluginList.clear(); plugins.forEach(pluginList::add); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/model/Plugin.java b/owlplug-client/src/main/java/com/owlplug/core/model/Plugin.java index a87f3c91..8cff22fc 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/model/Plugin.java +++ b/owlplug-client/src/main/java/com/owlplug/core/model/Plugin.java @@ -55,6 +55,7 @@ public class Plugin { protected String manufacturerName; protected String identifier; protected String path; + protected String scanDirectoryPath; protected String bundleId; protected String version; protected String screenshotUrl; @@ -82,12 +83,6 @@ public Plugin() { } - public Plugin(String name, String path, PluginFormat format) { - this.name = name; - this.path = path; - this.format = format; - } - public Long getId() { return id; } @@ -108,6 +103,14 @@ public void setPath(String path) { this.path = path; } + public String getScanDirectoryPath() { + return scanDirectoryPath; + } + + public void setScanDirectoryPath(String scanDirectoryPath) { + this.scanDirectoryPath = scanDirectoryPath; + } + public String getBundleId() { return bundleId; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java b/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java index 1b6328be..38b27b7e 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java +++ b/owlplug-client/src/main/java/com/owlplug/core/services/PluginService.java @@ -32,6 +32,8 @@ import com.owlplug.explore.services.ExploreService; import java.io.File; import java.util.List; +import java.util.Set; +import java.util.TreeSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -161,11 +163,11 @@ public Iterable findByComponentName(String name, PluginFormat pluginForm } /** - * Get the plugin path based on plugin format. + * Get the primary plugin path defined in preferences based on plugin format. * @param format plugin format * @return the directory path */ - public String getPluginPathByFormat(PluginFormat format) { + public String getPrimaryPluginPathByFormat(PluginFormat format) { if (PluginFormat.VST2.equals(format)) { return this.getPreferences().get(ApplicationDefaults.VST_DIRECTORY_KEY, ""); @@ -180,6 +182,33 @@ public String getPluginPathByFormat(PluginFormat format) { return this.getPreferences().get(ApplicationDefaults.VST_DIRECTORY_KEY, ""); } + /** + * Returns full list of explored directories during sync + * based on user preferences. + * @return the set of explored directories + */ + public Set getDirectoriesExplorationSet() { + Set directorySet = new TreeSet<>(); + + if (this.getPreferences().getBoolean(ApplicationDefaults.VST2_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(this.getPreferences().get(ApplicationDefaults.VST_DIRECTORY_KEY, "")); + directorySet.addAll(this.getPreferences().getList(ApplicationDefaults.VST2_EXTRA_DIRECTORY_KEY)); + } + if (this.getPreferences().getBoolean(ApplicationDefaults.VST3_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(this.getPreferences().get(ApplicationDefaults.VST3_DIRECTORY_KEY, "")); + directorySet.addAll(this.getPreferences().getList(ApplicationDefaults.VST3_EXTRA_DIRECTORY_KEY)); + } + if (this.getPreferences().getBoolean(ApplicationDefaults.AU_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(this.getPreferences().get(ApplicationDefaults.AU_DIRECTORY_KEY, "")); + directorySet.addAll(this.getPreferences().getList(ApplicationDefaults.AU_EXTRA_DIRECTORY_KEY)); + } + if (this.getPreferences().getBoolean(ApplicationDefaults.LV2_DISCOVERY_ENABLED_KEY, false)) { + directorySet.add(this.getPreferences().get(ApplicationDefaults.LV2_DIRECTORY_KEY, "")); + directorySet.addAll(this.getPreferences().getList(ApplicationDefaults.LV2_EXTRA_DIRECTORY_KEY)); + } + return directorySet; + } + /** * Check if format discovery is enabled. * @param format pluginFormat diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/PluginFileCollector.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/PluginFileCollector.java index 7448ae08..89fb773c 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/PluginFileCollector.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/PluginFileCollector.java @@ -83,6 +83,7 @@ public List collect(String directoryPath, PluginFormat pluginFormat) if (!nestedPluginDetected && !file.equals(dir)) { PluginFile pluginFile = pluginFileResolver.resolve(file); if (pluginFile != null) { + pluginFile.setScanDirectory(dir); collectedFiles.add(pluginFile); } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/AuComponentFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/AuComponentFile.java index 500bbeae..e4f70d2a 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/AuComponentFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/AuComponentFile.java @@ -37,17 +37,14 @@ public AuComponentFile(File pluginFile) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.AU); + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.AU); File plist = new File(this.getPluginFile().getAbsolutePath() + "/Contents/Info.plist"); if (plist.exists()) { OsxPlistFile plistFile = new OsxPlistFile(plist); plistFile.bindProperties(plugin); } - - plugin.setDisabled(this.isDisabled()); return plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Lv2BundleFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Lv2BundleFile.java index e4d1f8df..d4383e53 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Lv2BundleFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Lv2BundleFile.java @@ -54,11 +54,8 @@ public Lv2BundleFile(File file) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.LV2); - - plugin.setDisabled(this.isDisabled()); + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.LV2); return plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/OsxVstFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/OsxVstFile.java index 9f2ce0ba..20694201 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/OsxVstFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/OsxVstFile.java @@ -47,18 +47,15 @@ public OsxVstFile(File file) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.VST2); + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.VST2); File plist = new File(this.getPluginFile().getAbsolutePath() + "/Contents/Info.plist"); if (plist.exists()) { OsxPlistFile plistFile = new OsxPlistFile(plist); plistFile.bindProperties(plugin); } - - plugin.setDisabled(this.isDisabled()); - + return plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/PluginFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/PluginFile.java index 7d759c58..f25d98e0 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/PluginFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/PluginFile.java @@ -20,13 +20,17 @@ import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginComponent; +import com.owlplug.core.utils.FileUtils; import java.io.File; import java.util.List; import java.util.Objects; +import org.apache.commons.io.FilenameUtils; public abstract class PluginFile { private File pluginFile; + + private File scanDirectory; public PluginFile(File pluginFile) { this.pluginFile = pluginFile; @@ -34,6 +38,16 @@ public PluginFile(File pluginFile) { public abstract Plugin toPlugin(); + Plugin createPlugin() { + Plugin plugin = new Plugin(); + plugin.setScanDirectoryPath(FileUtils.convertPath(this.getScanDirectory().getAbsolutePath())); + plugin.setPath(FileUtils.convertPath(this.getPluginFile().getAbsolutePath())); + plugin.setName(FilenameUtils.removeExtension(this.getPluginFile().getName())); + plugin.setDisabled(this.isDisabled()); + + return plugin; + } + public List toComponents() { return null; } @@ -45,7 +59,15 @@ public File getPluginFile() { public void setPluginFile(File pluginFile) { this.pluginFile = pluginFile; } - + + public File getScanDirectory() { + return scanDirectory; + } + + public void setScanDirectory(File scanDirectory) { + this.scanDirectory = scanDirectory; + } + public boolean isDisabled() { return pluginFile.getAbsolutePath().endsWith(".disabled"); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/SoVstFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/SoVstFile.java index 0a191243..f082b558 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/SoVstFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/SoVstFile.java @@ -24,11 +24,8 @@ public SoVstFile(File pluginFile) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.VST2); - - plugin.setDisabled(this.isDisabled()); + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.VST2); return plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3BundleFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3BundleFile.java index 6f5100e6..e9db0580 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3BundleFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3BundleFile.java @@ -52,9 +52,8 @@ public Vst3BundleFile(File pluginFile) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.VST3); + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.VST3); File plist = new File(this.getPluginFile().getAbsolutePath() + "/Contents/Info.plist"); if (plist.exists()) { @@ -78,8 +77,6 @@ public Plugin toPlugin() { } } } - - plugin.setDisabled(this.isDisabled()); return plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3DllFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3DllFile.java index ad80526f..84739584 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3DllFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/Vst3DllFile.java @@ -43,11 +43,8 @@ public static boolean formatCheck(File file) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.VST3); - - plugin.setDisabled(this.isDisabled()); + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.VST3); return plugin; diff --git a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/VstDllFile.java b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/VstDllFile.java index e44f99a7..7582c5ee 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/VstDllFile.java +++ b/owlplug-client/src/main/java/com/owlplug/core/tasks/plugins/discovery/fileformats/VstDllFile.java @@ -43,12 +43,8 @@ public static boolean formatCheck(File file) { @Override public Plugin toPlugin() { - String pluginName = FilenameUtils.removeExtension(this.getPluginFile().getName()); - String pluginPath = this.getPluginFile().getAbsolutePath().replace("\\", "/"); - Plugin plugin = new Plugin(pluginName, pluginPath, PluginFormat.VST2); - - plugin.setDisabled(this.isDisabled()); - + Plugin plugin = createPlugin(); + plugin.setFormat(PluginFormat.VST2); return plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/ui/PluginStateView.java b/owlplug-client/src/main/java/com/owlplug/core/ui/PluginStateView.java index c9ded0ba..54be9651 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/ui/PluginStateView.java +++ b/owlplug-client/src/main/java/com/owlplug/core/ui/PluginStateView.java @@ -12,6 +12,10 @@ public PluginStateView() { super("Unknown"); } + public PluginStateView(PluginState pluginState) { + setPluginState(pluginState); + } + public void setPluginState(PluginState state) { Circle circle = new Circle(0, 0, 2); diff --git a/owlplug-client/src/main/java/com/owlplug/core/ui/PluginTreeCell.java b/owlplug-client/src/main/java/com/owlplug/core/ui/PluginTreeCell.java index b75f1651..4a87deda 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/ui/PluginTreeCell.java +++ b/owlplug-client/src/main/java/com/owlplug/core/ui/PluginTreeCell.java @@ -138,7 +138,7 @@ private void renderDirectory(IDirectory dir) { icon = new ImageView(applicationDefaults.symlinkImage); } else if (dir instanceof PluginDirectory pluginDirectory) { if (pluginDirectory.isRootDirectory()) { - icon = new ImageView(applicationDefaults.rootDirectoryImage); + icon = new ImageView(applicationDefaults.scanDirectoryImage); } else { icon = new ImageView(applicationDefaults.directoryImage); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/utils/FileUtils.java b/owlplug-client/src/main/java/com/owlplug/core/utils/FileUtils.java index 838296be..017686e0 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/utils/FileUtils.java +++ b/owlplug-client/src/main/java/com/owlplug/core/utils/FileUtils.java @@ -127,6 +127,28 @@ public static void deleteDirectory(File source) throws IOException { org.apache.commons.io.FileUtils.deleteDirectory(source); } + public static String getParentDirectoryName(String path) { + File file = new File(path); + File parentFile = file.getParentFile(); + + if (file.exists() && parentFile != null && parentFile.exists()) { + return parentFile.getName(); + } + + return null; + + } + + public static String getFilename(String path) { + if (path == null || path.isEmpty()) { + return null; + } + + File file = new File(path); + return file.getName(); + + } + public static String humanReadableByteCount(long bytes, boolean si) { int unit = si ? 1000 : 1024; if (bytes < unit) diff --git a/owlplug-client/src/main/java/com/owlplug/explore/services/ExploreService.java b/owlplug-client/src/main/java/com/owlplug/explore/services/ExploreService.java index c7dfeb20..1e9833a0 100644 --- a/owlplug-client/src/main/java/com/owlplug/explore/services/ExploreService.java +++ b/owlplug-client/src/main/java/com/owlplug/explore/services/ExploreService.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.owlplug.core.components.ApplicationDefaults; import com.owlplug.core.model.PluginFormat; import com.owlplug.core.model.platform.RuntimePlatform; import com.owlplug.core.services.BaseService; @@ -258,7 +257,7 @@ public boolean canDeterminateBundleInstallFolder(PackageBundle bundle) { } else if (formats.size() > 1) { List paths = new ArrayList<>(); for (PluginFormat format : formats) { - paths.add(this.pluginService.getPluginPathByFormat(format)); + paths.add(this.pluginService.getPrimaryPluginPathByFormat(format)); } // check if all path are equals return paths.stream().allMatch(s -> s.equals(paths.get(0))); @@ -278,7 +277,7 @@ public boolean canDeterminateBundleInstallFolder(PackageBundle bundle) { public String getBundleInstallFolder(PackageBundle bundle) { PluginFormat format = filterEnabledFormats(bundle.getFormats()).getFirst(); - return pluginService.getPluginPathByFormat(format); + return pluginService.getPrimaryPluginPathByFormat(format); } From 8940253e5bc111b55af3d25040d24b3dc6735def Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Mon, 30 Dec 2024 22:55:37 +0100 Subject: [PATCH 06/15] feat: toggle plugins info view display on double click --- .../core/controllers/PluginsController.java | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index 07ccc616..3eeaed88 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -87,13 +87,37 @@ public void initialize() { if (newValue != null) { TreeItem selectedItem = newValue; nodeInfoController.setNode(selectedItem.getValue()); + setInfoPaneDisplay(true); + } + }); + treeViewController.getTreeView().setOnMouseClicked(mouseEvent -> { + if (mouseEvent.getClickCount() == 2) { + toggleInfoPaneDisplay(); } }); - treeViewController.searchProperty().bind(searchTextField.textProperty()); + tableController.getTableView().setOnMouseClicked(mouseEvent -> { + if (mouseEvent.getClickCount() == 2) { + toggleInfoPaneDisplay(); + } + }); + tableController.getTableView().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + nodeInfoController.setNode(newValue); + } + }); + pluginTreeViewTabPane.getStyleClass().add(JMetroStyleClass.UNDERLINE_TAB_PANE); + // Default display (flat tree) + treeViewController.setDisplayMode(PluginTreeViewController.Display.FlatTree); + treeViewController.getTreeView().setVisible(true); + treeViewController.getTreeView().setManaged(true); + tableController.getTableView().setManaged(false); + tableController.getTableView().setVisible(false); + setInfoPaneDisplay(true); + // Handles tabPane selection event and toggles displayed treeView pluginTreeViewTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { if (newTab.getId().equals("treeTabAll")) { @@ -101,26 +125,23 @@ public void initialize() { // TODO setVisible / managed in subcontroller treeViewController.getTreeView().setVisible(true); treeViewController.getTreeView().setManaged(true); - pluginInfoPane.setManaged(true); - pluginInfoPane.setVisible(true); tableController.getTableView().setManaged(false); tableController.getTableView().setVisible(false); + setInfoPaneDisplay(true); } else if (newTab.getId().equals("treeTabDirectories")) { treeViewController.setDisplayMode(PluginTreeViewController.Display.DirectoryTree); // TODO setVisible / managed in subcontroller treeViewController.getTreeView().setManaged(true); treeViewController.getTreeView().setVisible(true); - pluginInfoPane.setManaged(true); - pluginInfoPane.setVisible(true); tableController.getTableView().setManaged(false); tableController.getTableView().setVisible(false); + setInfoPaneDisplay(true); } else { treeViewController.getTreeView().setManaged(false); treeViewController.getTreeView().setVisible(false); - pluginInfoPane.setManaged(false); - pluginInfoPane.setVisible(false); tableController.getTableView().setManaged(true); tableController.getTableView().setVisible(true); + setInfoPaneDisplay(false); } }); @@ -154,4 +175,14 @@ public void refresh() { tableController.refresh(); } + private void setInfoPaneDisplay(boolean display) { + pluginInfoPane.setManaged(display); + pluginInfoPane.setVisible(display); + } + + private void toggleInfoPaneDisplay() { + pluginInfoPane.setManaged(!pluginInfoPane.isManaged()); + pluginInfoPane.setVisible(!pluginInfoPane.isVisible()); + } + } From 6d8a0d095d349aee8cb6f2f0b698571599721744 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Thu, 2 Jan 2025 15:51:39 +0100 Subject: [PATCH 07/15] feat: add search property binding on plugin table --- .../controllers/PluginTableController.java | 27 ++++++++++- .../controllers/PluginTreeViewController.java | 5 ++ .../core/controllers/PluginsController.java | 47 ++++++++++++------- .../src/main/resources/fxml/PluginsView.fxml | 2 +- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index b7293993..b82c2594 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -24,10 +24,12 @@ import com.owlplug.core.services.PluginService; import com.owlplug.core.ui.PluginStateView; import com.owlplug.core.utils.FileUtils; +import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import javafx.collections.transformation.FilteredList; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -43,10 +45,15 @@ public class PluginTableController extends BaseController { @Autowired private PluginService pluginService; + private final SimpleStringProperty search = new SimpleStringProperty(); private TableView tableView; private ObservableList pluginList; + // Wraps an ObservableList and filters its content using the provided Predicate. + // All changes in the ObservableList are propagated immediately to the FilteredList. + private FilteredList filteredPluginList; + public PluginTableController() { tableView = new TableView<>(); @@ -131,7 +138,17 @@ public void updateItem(PluginState item, boolean empty) { manufacturerColumn, categoryColumn, directoryColumn, scanDirectoryColumn, stateColumn); pluginList = FXCollections.observableArrayList(); - tableView.setItems(pluginList); + filteredPluginList = new FilteredList<>(pluginList); + + filteredPluginList.predicateProperty().bind(Bindings.createObjectBinding(() -> { + if (search.getValue() == null || search.getValue().isEmpty()) { + return null; + } + return (plugin) -> plugin.getName().toLowerCase().contains(search.getValue().toLowerCase()) + || (plugin.getCategory() != null && plugin.getCategory().toLowerCase().contains(search.getValue().toLowerCase())); + }, search)); + + tableView.setItems(filteredPluginList); } @@ -142,7 +159,15 @@ public void setPlugins(Iterable plugins) { public TableView getTableView() { return tableView; + } + + public void setNodeManaged(boolean isManaged) { + this.tableView.setManaged(isManaged); + this.tableView.setVisible(isManaged); + } + public SimpleStringProperty searchProperty() { + return this.search; } public void refresh() { diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java index 80164520..ff983c82 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTreeViewController.java @@ -131,6 +131,11 @@ public void setDisplayMode(Display display) { } } + public void setNodeManaged(boolean isManaged) { + this.pluginTreeView.setManaged(isManaged); + this.pluginTreeView.setVisible(isManaged); + } + public void setPlugins(Iterable plugins) { this.clearAndFillPluginTree(plugins); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index 3eeaed88..c1c00776 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -59,7 +59,7 @@ public class PluginsController extends BaseController { @FXML private Button exportButton; @FXML - private TabPane pluginTreeViewTabPane; + private TabPane displaySwitchTabPane; @FXML private TextField searchTextField; @FXML @@ -79,9 +79,15 @@ public void initialize() { newLinkController.show(); }); + // Add Plugin Table and TreeView to the scene graph pluginsContainer.getChildren().add(treeViewController.getTreeView()); pluginsContainer.getChildren().add(tableController.getTableView()); + /* =================== + * Plugins TreeView properties init and bindings + * =================== + */ + // Dispatches treeView selection event to the nodeInfoController treeViewController.getTreeView().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { if (newValue != null) { @@ -97,6 +103,11 @@ public void initialize() { }); treeViewController.searchProperty().bind(searchTextField.textProperty()); + /* =================== + * Plugins Table properties init and bindings + * =================== + */ + tableController.getTableView().setOnMouseClicked(mouseEvent -> { if (mouseEvent.getClickCount() == 2) { toggleInfoPaneDisplay(); @@ -108,9 +119,17 @@ public void initialize() { } }); - pluginTreeViewTabPane.getStyleClass().add(JMetroStyleClass.UNDERLINE_TAB_PANE); + tableController.searchProperty().bind(searchTextField.textProperty()); + + + /* =================== + * Controller and node graph initialization + * =================== + */ + + displaySwitchTabPane.getStyleClass().add(JMetroStyleClass.UNDERLINE_TAB_PANE); - // Default display (flat tree) + // Set default display (flat plugin tree) treeViewController.setDisplayMode(PluginTreeViewController.Display.FlatTree); treeViewController.getTreeView().setVisible(true); treeViewController.getTreeView().setManaged(true); @@ -119,28 +138,20 @@ public void initialize() { setInfoPaneDisplay(true); // Handles tabPane selection event and toggles displayed treeView - pluginTreeViewTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { + displaySwitchTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { if (newTab.getId().equals("treeTabAll")) { treeViewController.setDisplayMode(PluginTreeViewController.Display.FlatTree); - // TODO setVisible / managed in subcontroller - treeViewController.getTreeView().setVisible(true); - treeViewController.getTreeView().setManaged(true); - tableController.getTableView().setManaged(false); - tableController.getTableView().setVisible(false); + treeViewController.setNodeManaged(true); + tableController.setNodeManaged(false); setInfoPaneDisplay(true); } else if (newTab.getId().equals("treeTabDirectories")) { treeViewController.setDisplayMode(PluginTreeViewController.Display.DirectoryTree); - // TODO setVisible / managed in subcontroller - treeViewController.getTreeView().setManaged(true); - treeViewController.getTreeView().setVisible(true); - tableController.getTableView().setManaged(false); - tableController.getTableView().setVisible(false); + treeViewController.setNodeManaged(true); + tableController.setNodeManaged(false); setInfoPaneDisplay(true); } else { - treeViewController.getTreeView().setManaged(false); - treeViewController.getTreeView().setVisible(false); - tableController.getTableView().setManaged(true); - tableController.getTableView().setVisible(true); + treeViewController.setNodeManaged(false); + tableController.setNodeManaged(true); setInfoPaneDisplay(false); } }); diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index bb5206fe..6da4ba8e 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -57,7 +57,7 @@ - + From 174a42c5c3b57e1cb0f66f48070941839c3a7a49 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Thu, 2 Jan 2025 16:10:31 +0100 Subject: [PATCH 08/15] refactor: rename and compare plugin display tab selection using instance ref --- .../owlplug/core/controllers/PluginsController.java | 12 ++++++++++-- .../src/main/resources/fxml/PluginsView.fxml | 6 +++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index c1c00776..32e4acb0 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -26,6 +26,7 @@ import com.owlplug.core.services.PluginService; import javafx.fxml.FXML; import javafx.scene.control.Button; +import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TextField; import javafx.scene.control.TreeItem; @@ -60,6 +61,13 @@ public class PluginsController extends BaseController { private Button exportButton; @FXML private TabPane displaySwitchTabPane; + @FXML + private Tab displayListTab; + @FXML + private Tab displayDirectoriesTab; + @FXML + private Tab displayTableTab; + @FXML private TextField searchTextField; @FXML @@ -139,12 +147,12 @@ public void initialize() { // Handles tabPane selection event and toggles displayed treeView displaySwitchTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { - if (newTab.getId().equals("treeTabAll")) { + if (newTab.equals(displayListTab)) { treeViewController.setDisplayMode(PluginTreeViewController.Display.FlatTree); treeViewController.setNodeManaged(true); tableController.setNodeManaged(false); setInfoPaneDisplay(true); - } else if (newTab.getId().equals("treeTabDirectories")) { + } else if (newTab.equals(displayDirectoriesTab)) { treeViewController.setDisplayMode(PluginTreeViewController.Display.DirectoryTree); treeViewController.setNodeManaged(true); tableController.setNodeManaged(false); diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index 6da4ba8e..12ab49d4 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -59,9 +59,9 @@ - - - + + + From 41fbab7df616341bfbc8a529cceb17d515084199 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Fri, 3 Jan 2025 15:55:42 +0100 Subject: [PATCH 09/15] style: improve plugin table colors and borders --- owlplug-client/src/main/resources/owlplug.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/owlplug-client/src/main/resources/owlplug.css b/owlplug-client/src/main/resources/owlplug.css index 824a0ac3..b30b3db7 100644 --- a/owlplug-client/src/main/resources/owlplug.css +++ b/owlplug-client/src/main/resources/owlplug.css @@ -90,6 +90,11 @@ TextArea .content { -fx-background-color: danger-color; } +.table-view { + -fx-background-color: card-pane-color; + -fx-border-width: 0px; +} + .chip-view { -fx-max-height: 45px ; } From d2ba28ca22ef8acc604022e34c8b222c9d9322ae Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Sat, 4 Jan 2025 10:15:37 +0100 Subject: [PATCH 10/15] feat: add plugin table context menu --- .../controllers/PluginTableController.java | 62 +++++++++++++++++++ .../core/controllers/PluginsController.java | 4 +- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index b82c2594..f808d7db 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -24,14 +24,20 @@ import com.owlplug.core.services.PluginService; import com.owlplug.core.ui.PluginStateView; import com.owlplug.core.utils.FileUtils; +import com.owlplug.core.utils.PlatformUtils; +import java.io.File; import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; +import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.image.ImageView; import javafx.scene.layout.Priority; @@ -42,6 +48,9 @@ @Controller public class PluginTableController extends BaseController { + @Autowired + private PluginsController pluginsController; + @Autowired private PluginService pluginService; @@ -137,6 +146,20 @@ public void updateItem(PluginState item, boolean empty) { tableView.getColumns().addAll(formatColumn, nameColumn, versionColumn, manufacturerColumn, categoryColumn, directoryColumn, scanDirectoryColumn, stateColumn); + + + tableView.setRowFactory(tv -> { + TableRow row = new TableRow<>(); + row.itemProperty().addListener((obs, oldItem, newItem) -> { + if (newItem != null) { + row.setContextMenu(createPluginContextMenu(newItem)); + } + }); + return row ; + }); + tableView.setContextMenu(createPluginContextMenu(new Plugin())); + + pluginList = FXCollections.observableArrayList(); filteredPluginList = new FilteredList<>(pluginList); @@ -174,6 +197,45 @@ public void refresh() { tableView.refresh(); } + private ContextMenu createPluginContextMenu(Plugin plugin) { + + ContextMenu menu = new ContextMenu(); + MenuItem openDirItem = new MenuItem("Reveal in File Explorer"); + openDirItem.setOnAction(e -> { + File pluginFile = new File(plugin.getPath()); + PlatformUtils.openFromDesktop(pluginFile.getParentFile()); + }); + + menu.getItems().addAll(openDirItem, new SeparatorMenuItem()); + + if (plugin.isDisabled()) { + MenuItem enableItem = new MenuItem ("Enable plugin"); + enableItem.setOnAction(e -> { + pluginService.enablePlugin(plugin); + // TODO refresh view + reset plugin info ? + }); + menu.getItems().add(enableItem); + } else { + MenuItem disableItem = new MenuItem("Disable plugin"); + disableItem.setOnAction(e -> { + // TODO add confirmation for disabling plugin + pluginService.disablePlugin(plugin); + // TODO refresh view + reset plugin info ? + }); + menu.getItems().add(disableItem); + } + + menu.getItems().add(new SeparatorMenuItem()); + + MenuItem infoDisplayItem = new MenuItem("Toggle info display"); + menu.getItems().add(infoDisplayItem); + infoDisplayItem.setOnAction(e -> { + pluginsController.toggleInfoPaneDisplay(); + }); + + return menu; + } + } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index 32e4acb0..f50df19f 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -194,12 +194,12 @@ public void refresh() { tableController.refresh(); } - private void setInfoPaneDisplay(boolean display) { + public void setInfoPaneDisplay(boolean display) { pluginInfoPane.setManaged(display); pluginInfoPane.setVisible(display); } - private void toggleInfoPaneDisplay() { + public void toggleInfoPaneDisplay() { pluginInfoPane.setManaged(!pluginInfoPane.isManaged()); pluginInfoPane.setVisible(!pluginInfoPane.isVisible()); } From eec0be645c350d3fd2509112e7d453734b57b640 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Mon, 6 Jan 2025 23:17:22 +0100 Subject: [PATCH 11/15] feat: add disable confirmation dialog on plugin table --- .../controllers/PluginInfoController.java | 99 ++++++------------- .../controllers/PluginTableController.java | 36 ++++--- .../DisablePluginDialogController.java | 90 +++++++++++++++++ 3 files changed, 135 insertions(+), 90 deletions(-) create mode 100644 owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java index 8e39a438..f463b767 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginInfoController.java @@ -23,6 +23,7 @@ import com.owlplug.core.components.ApplicationDefaults; import com.owlplug.core.components.CoreTaskFactory; import com.owlplug.core.components.ImageCache; +import com.owlplug.core.controllers.dialogs.DisablePluginDialogController; import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginComponent; import com.owlplug.core.services.PluginService; @@ -35,9 +36,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; -import javafx.geometry.Insets; import javafx.scene.control.Button; -import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.effect.ColorAdjust; @@ -49,7 +48,6 @@ import javafx.scene.layout.BackgroundRepeat; import javafx.scene.layout.BackgroundSize; import javafx.scene.layout.Pane; -import javafx.scene.layout.VBox; import org.controlsfx.control.ToggleSwitch; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @@ -65,6 +63,8 @@ public class PluginInfoController extends BaseController { private ImageCache imageCache; @Autowired private CoreTaskFactory coreTaskFactory; + @Autowired + private DisablePluginDialogController disableController; @FXML private Pane pluginScreenshotPane; @@ -101,7 +101,7 @@ public class PluginInfoController extends BaseController { @FXML private ToggleSwitch nativeDiscoveryToggleButton; - private Plugin currentPlugin = null; + private Plugin plugin = null; private ArrayList knownPluginImages = new ArrayList<>(); /** @@ -126,35 +126,40 @@ public void initialize() { disableButton.setOnAction(e -> { if (this.getPreferences().getBoolean(ApplicationDefaults.SHOW_DIALOG_DISABLE_PLUGIN_KEY, true)) { - this.showDisableDialog(); + this.disableController.setPlugin(plugin); + this.disableController.show(); } else { - pluginService.disablePlugin(currentPlugin); - setPlugin(currentPlugin); - pluginsController.refresh(); + this.disableController.disablePluginWithoutPrompt(plugin); } - }); enableButton.setOnAction(e -> { - pluginService.enablePlugin(currentPlugin); - setPlugin(currentPlugin); + pluginService.enablePlugin(plugin); + setPlugin(plugin); pluginsController.refresh(); }); pluginComponentListView.setCellFactory(new PluginComponentCellFactory(this.getApplicationDefaults())); nativeDiscoveryToggleButton.selectedProperty().addListener((observable, oldValue, newValue) -> { - if (currentPlugin != null && currentPlugin.getFootprint() != null) { - currentPlugin.getFootprint().setNativeDiscoveryEnabled(newValue); - pluginService.save(currentPlugin.getFootprint()); + if (plugin != null && plugin.getFootprint() != null) { + plugin.getFootprint().setNativeDiscoveryEnabled(newValue); + pluginService.save(plugin.getFootprint()); } - }); } public void setPlugin(Plugin plugin) { - this.currentPlugin = plugin; + this.plugin = plugin; + refresh(); + } + + public void refresh() { + + if (plugin == null) { + return; + } pluginFormatIcon.setImage(this.getApplicationDefaults().getPluginFormatIcon(plugin.getFormat())); pluginFormatLabel.setText(plugin.getFormat().getText() + " Plugin"); pluginTitleLabel.setText(plugin.getName()); @@ -190,13 +195,13 @@ public void setPlugin(Plugin plugin) { } private void setPluginImage() { - if (currentPlugin.getScreenshotUrl() == null || currentPlugin.getScreenshotUrl().isEmpty()) { - String url = pluginService.resolveImageUrl(currentPlugin); - currentPlugin.setScreenshotUrl(url); - pluginService.save(currentPlugin); + if (plugin.getScreenshotUrl() == null || plugin.getScreenshotUrl().isEmpty()) { + String url = pluginService.resolveImageUrl(plugin); + plugin.setScreenshotUrl(url); + pluginService.save(plugin); } - String url = currentPlugin.getScreenshotUrl(); + String url = plugin.getScreenshotUrl(); if (knownPluginImages.contains(url) && !imageCache.contains(url)) { BackgroundImage bgImg = new BackgroundImage(this.getApplicationDefaults().pluginPlaceholderImage, @@ -224,7 +229,7 @@ private void showUninstallDialog() { DialogLayout layout = new DialogLayout(); layout.setHeading(new Label("Remove plugin")); - layout.setBody(new Label("Do you really want to remove " + currentPlugin.getName() + layout.setBody(new Label("Do you really want to remove " + plugin.getName() + " ? This will permanently delete the file from your hard drive.")); Button cancelButton = new Button("Cancel"); @@ -235,7 +240,7 @@ private void showUninstallDialog() { Button removeButton = new Button("Remove"); removeButton.setOnAction(removeEvent -> { dialog.close(); - coreTaskFactory.createPluginRemoveTask(currentPlugin) + coreTaskFactory.createPluginRemoveTask(plugin) .setOnSucceeded(x -> pluginsController.displayPlugins()).schedule(); }); removeButton.getStyleClass().add("button-danger"); @@ -244,53 +249,5 @@ private void showUninstallDialog() { dialog.setContent(layout); dialog.show(); } - - private void showDisableDialog() { - - DialogLayout layout = new DialogLayout(); - - layout.setHeading(new Label("Disable plugin")); - - VBox vbox = new VBox(10); - Label dialogLabel = new Label( - "Disabling a plugin will rename the plugin file by updating the extension. " - + "The suffix \".disabled\" will be appended to the filename causing the DAW to ignore the plugin. " - + "You can reactivate the plugin at any time from OwlPlug or by renaming the file manually."); - dialogLabel.setWrapText(true); - vbox.getChildren().add(dialogLabel); - - Label noteLabel = new Label("You may need admin privileges to rename plugins"); - noteLabel.getStyleClass().add("label-disabled"); - vbox.getChildren().add(noteLabel); - - CheckBox displayDialog = new CheckBox("Don't show me this message again"); - VBox.setMargin(displayDialog, new Insets(20,0,0,0)); - displayDialog.setSelected(!getPreferences().getBoolean(ApplicationDefaults.SHOW_DIALOG_DISABLE_PLUGIN_KEY, true)); - displayDialog.selectedProperty().addListener((observable, oldValue, newValue) -> { - this.getPreferences().putBoolean(ApplicationDefaults.SHOW_DIALOG_DISABLE_PLUGIN_KEY, !newValue); - }); - vbox.getChildren().add(displayDialog); - layout.setBody(vbox); - - Dialog dialog = this.getDialogManager().newDialog(); - - Button cancelButton = new Button("Cancel"); - cancelButton.setOnAction(cancelEvent -> { - dialog.close(); - }); - - Button disableButton = new Button("Disable Plugin"); - disableButton.setOnAction(removeEvent -> { - pluginService.disablePlugin(currentPlugin); - setPlugin(currentPlugin); - pluginsController.refresh(); - dialog.close(); - }); - - layout.setActions(disableButton, cancelButton); - layout.setPrefSize(600, 280); - dialog.setContent(layout); - dialog.show(); - } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index f808d7db..a9eadf28 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -18,6 +18,8 @@ package com.owlplug.core.controllers; +import com.owlplug.core.components.ApplicationDefaults; +import com.owlplug.core.controllers.dialogs.DisablePluginDialogController; import com.owlplug.core.model.Plugin; import com.owlplug.core.model.PluginFormat; import com.owlplug.core.model.PluginState; @@ -50,18 +52,15 @@ public class PluginTableController extends BaseController { @Autowired private PluginsController pluginsController; - + @Autowired + private DisablePluginDialogController disableController; @Autowired private PluginService pluginService; private final SimpleStringProperty search = new SimpleStringProperty(); - private TableView tableView; - - private ObservableList pluginList; + private final TableView tableView; - // Wraps an ObservableList and filters its content using the provided Predicate. - // All changes in the ObservableList are propagated immediately to the FilteredList. - private FilteredList filteredPluginList; + private final ObservableList pluginList; public PluginTableController() { @@ -146,8 +145,6 @@ public void updateItem(PluginState item, boolean empty) { tableView.getColumns().addAll(formatColumn, nameColumn, versionColumn, manufacturerColumn, categoryColumn, directoryColumn, scanDirectoryColumn, stateColumn); - - tableView.setRowFactory(tv -> { TableRow row = new TableRow<>(); row.itemProperty().addListener((obs, oldItem, newItem) -> { @@ -155,13 +152,15 @@ public void updateItem(PluginState item, boolean empty) { row.setContextMenu(createPluginContextMenu(newItem)); } }); - return row ; + return row; }); tableView.setContextMenu(createPluginContextMenu(new Plugin())); pluginList = FXCollections.observableArrayList(); - filteredPluginList = new FilteredList<>(pluginList); + // Wraps an ObservableList and filters its content using the provided Predicate. + // All changes in the ObservableList are propagated immediately to the FilteredList. + FilteredList filteredPluginList = new FilteredList<>(pluginList); filteredPluginList.predicateProperty().bind(Bindings.createObjectBinding(() -> { if (search.getValue() == null || search.getValue().isEmpty()) { @@ -212,15 +211,18 @@ private ContextMenu createPluginContextMenu(Plugin plugin) { MenuItem enableItem = new MenuItem ("Enable plugin"); enableItem.setOnAction(e -> { pluginService.enablePlugin(plugin); - // TODO refresh view + reset plugin info ? + pluginsController.refresh(); }); menu.getItems().add(enableItem); } else { MenuItem disableItem = new MenuItem("Disable plugin"); disableItem.setOnAction(e -> { - // TODO add confirmation for disabling plugin - pluginService.disablePlugin(plugin); - // TODO refresh view + reset plugin info ? + if (this.getPreferences().getBoolean(ApplicationDefaults.SHOW_DIALOG_DISABLE_PLUGIN_KEY, true)) { + this.disableController.setPlugin(plugin); + this.disableController.show(); + } else { + this.disableController.disablePluginWithoutPrompt(plugin); + } }); menu.getItems().add(disableItem); } @@ -236,8 +238,4 @@ private ContextMenu createPluginContextMenu(Plugin plugin) { return menu; } - } - - - diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java new file mode 100644 index 00000000..a550d1bc --- /dev/null +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java @@ -0,0 +1,90 @@ +package com.owlplug.core.controllers.dialogs; + +import com.owlplug.controls.DialogLayout; +import com.owlplug.core.components.ApplicationDefaults; +import com.owlplug.core.controllers.PluginInfoController; +import com.owlplug.core.controllers.PluginsController; +import com.owlplug.core.model.Plugin; +import com.owlplug.core.services.PluginService; +import javafx.geometry.Insets; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Controller +public class DisablePluginDialogController extends AbstractDialogController { + + @Autowired + private PluginsController pluginsController; + @Autowired + private PluginService pluginService; + @Autowired + private PluginInfoController pluginInfoController; + + private Plugin plugin; + + public DisablePluginDialogController() { + super(600,280); + } + + @Override + protected Node getBody() { + DialogLayout layout = new DialogLayout(); + VBox vbox = new VBox(10); + Label dialogLabel = new Label( + "Disabling a plugin will rename the plugin file by updating the extension. " + + "The suffix \".disabled\" will be appended to the filename causing the DAW to ignore the plugin. " + + "You can reactivate the plugin at any time from OwlPlug or by renaming the file manually."); + dialogLabel.setWrapText(true); + VBox.setVgrow(dialogLabel, Priority.ALWAYS); + vbox.getChildren().add(dialogLabel); + + Label noteLabel = new Label("You may need admin privileges to rename plugin file."); + noteLabel.getStyleClass().add("label-disabled"); + vbox.getChildren().add(noteLabel); + + CheckBox displayDialog = new CheckBox("Don't show me this message again"); + VBox.setMargin(displayDialog, new Insets(20,0,0,0)); + displayDialog.setSelected(!getPreferences().getBoolean(ApplicationDefaults.SHOW_DIALOG_DISABLE_PLUGIN_KEY, true)); + displayDialog.selectedProperty().addListener((observable, oldValue, newValue) -> { + this.getPreferences().putBoolean(ApplicationDefaults.SHOW_DIALOG_DISABLE_PLUGIN_KEY, !newValue); + }); + vbox.getChildren().add(displayDialog); + layout.setBody(vbox); + + Button cancelButton = new Button("Cancel"); + cancelButton.setOnAction(cancelEvent -> { + this.close(); + }); + + Button disableButton = new Button("Disable Plugin"); + disableButton.setOnAction(removeEvent -> { + this.disablePluginWithoutPrompt(plugin); + this.close(); + }); + + layout.setActions(disableButton, cancelButton); + return layout; + } + + @Override + protected Node getHeading() { + return new Label("Disable plugin " + plugin.getName()); + + } + + public void setPlugin(Plugin plugin) { + this.plugin = plugin; + } + + public void disablePluginWithoutPrompt(Plugin plugin) { + pluginService.disablePlugin(plugin); + pluginsController.refresh(); + pluginInfoController.refresh(); + } +} From 655048dd023fd98bad5bdaa055926c800117e4c1 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Mon, 6 Jan 2025 23:59:39 +0100 Subject: [PATCH 12/15] refactor: generate dialog layouts within controllers --- .../auth/controllers/AccountController.java | 12 ++--- .../core/components/DialogManager.java | 53 +------------------ .../dialogs/AbstractDialogController.java | 17 +++--- .../CrashRecoveryDialogController.java | 19 ++++--- .../DisablePluginDialogController.java | 12 ++--- .../dialogs/DonateDialogController.java | 16 +++--- .../dialogs/ExportDialogController.java | 22 ++++---- .../ListDirectoryDialogController.java | 14 ++--- .../dialogs/NewLinkController.java | 14 +++-- .../dialogs/WelcomeDialogController.java | 16 +++--- .../NewSourceDialogController.java | 15 +++--- 11 files changed, 74 insertions(+), 136 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/auth/controllers/AccountController.java b/owlplug-client/src/main/java/com/owlplug/auth/controllers/AccountController.java index 81ab3902..66a150bf 100644 --- a/owlplug-client/src/main/java/com/owlplug/auth/controllers/AccountController.java +++ b/owlplug-client/src/main/java/com/owlplug/auth/controllers/AccountController.java @@ -19,6 +19,7 @@ package com.owlplug.auth.controllers; import com.owlplug.auth.services.AuthenticationService; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.LazyViewRegistry; import com.owlplug.core.controllers.MainController; import com.owlplug.core.controllers.dialogs.AbstractDialogController; @@ -142,13 +143,10 @@ protected void onDialogShow() { } @Override - protected Node getBody() { - return viewRegistry.get(LazyViewRegistry.NEW_ACCOUNT_VIEW); - } - - @Override - protected Node getHeading() { - return null; + protected DialogLayout getLayout() { + DialogLayout layout = new DialogLayout(); + layout.setBody(viewRegistry.get(LazyViewRegistry.NEW_ACCOUNT_VIEW)); + return layout; } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/components/DialogManager.java b/owlplug-client/src/main/java/com/owlplug/core/components/DialogManager.java index 42001b81..a7f60f84 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/components/DialogManager.java +++ b/owlplug-client/src/main/java/com/owlplug/core/components/DialogManager.java @@ -54,33 +54,6 @@ public Dialog newDialog() { return dialog; } - /** - * Creates a new dialog. - * - * @param body - dialog body - * @return - */ - public Dialog newDialog(Node body) { - - DialogLayout layout = new DialogLayout(); - layout.setBody(body); - return newDialog(layout); - } - - /** - * Creates a new dialog. - * - * @param body - dialog body - * @param heading - dialog header - * @return - */ - public Dialog newDialog(Node body, Node heading) { - - DialogLayout layout = new DialogLayout(); - layout.setBody(body); - layout.setHeading(heading); - return newDialog(layout); - } /** * Creates a new dialog. @@ -90,37 +63,13 @@ public Dialog newDialog(Node body, Node heading) { * @param body - dialog body * @return the dialog */ - public Dialog newDialog(double width, double height, Node body) { - - DialogLayout layout = new DialogLayout(); + public Dialog newDialog(double width, double height, DialogLayout layout) { layout.setMaxSize(width, height); layout.setPrefSize(width, height); - layout.setBody(body); - return newDialog(layout); } - /** - * Creates a new dialog. - * - * @param width - dialog width - * @param height - dialog height - * @param body - dialog body - * @param heading - dialog header - * @return the dialog - */ - public Dialog newDialog(double width, double height, Node body, Node heading) { - - DialogLayout layout = new DialogLayout(); - layout.setMaxSize(width, height); - layout.setPrefSize(width, height); - layout.setBody(body); - layout.setHeading(heading); - - return newDialog(layout); - - } /** * Creates a new dialog based on dialog layout. diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java index 90df4c75..d058e53e 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java @@ -18,8 +18,8 @@ package com.owlplug.core.controllers.dialogs; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.controllers.BaseController; -import javafx.scene.Node; public abstract class AbstractDialogController extends BaseController { @@ -43,9 +43,7 @@ public AbstractDialogController(double width, double height) { this.height = height; } - protected abstract Node getBody(); - - protected abstract Node getHeading(); + protected abstract DialogLayout getLayout(); /** * Open and display dialog frame. @@ -55,16 +53,13 @@ public void show() { onDialogShow(); if (width != -1 && height != -1) { - if (this.getHeading() != null) { - this.getDialogManager().newDialog(width, height, this.getBody(), this.getHeading()); - } else { - this.getDialogManager().newDialog(width, height, this.getBody()); + if (this.getLayout() != null) { + this.getDialogManager().newDialog(width, height, this.getLayout()); } } else { - if (this.getHeading() != null) { - this.getDialogManager().newDialog(this.getBody(), this.getHeading()); + if (this.getLayout() != null) { } else { - this.getDialogManager().newDialog(this.getBody()); + this.getDialogManager().newDialog(this.getLayout()); } } this.getDialogManager().getDialog().setOverlayClose(overlayClose); diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/CrashRecoveryDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/CrashRecoveryDialogController.java index 00d2557d..8783f82a 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/CrashRecoveryDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/CrashRecoveryDialogController.java @@ -18,6 +18,7 @@ package com.owlplug.core.controllers.dialogs; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.ApplicationDefaults; import com.owlplug.core.components.LazyViewRegistry; import com.owlplug.core.controllers.OptionsController; @@ -132,16 +133,20 @@ public void initialize() { } - @Override - protected Node getBody() { - return lazyViewRegistry.get(LazyViewRegistry.CRASH_RECOVERY_VIEW); - } + protected DialogLayout getLayout() { + + DialogLayout layout = new DialogLayout(); - @Override - protected Node getHeading() { Label title = new Label("Ooh, something wrong happens :("); title.getStyleClass().add("heading-3"); - return title; + layout.setHeading(title); + layout.setBody(lazyViewRegistry.get(LazyViewRegistry.CRASH_RECOVERY_VIEW)); + + return layout; + } + + protected Node getBody() { + return lazyViewRegistry.get(LazyViewRegistry.CRASH_RECOVERY_VIEW); } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java index a550d1bc..a17e47ef 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DisablePluginDialogController.java @@ -7,7 +7,6 @@ import com.owlplug.core.model.Plugin; import com.owlplug.core.services.PluginService; import javafx.geometry.Insets; -import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; @@ -29,12 +28,13 @@ public class DisablePluginDialogController extends AbstractDialogController { private Plugin plugin; public DisablePluginDialogController() { - super(600,280); + super(600,300); } @Override - protected Node getBody() { + protected DialogLayout getLayout() { DialogLayout layout = new DialogLayout(); + layout.setHeading(new Label("Disable plugin " + plugin.getName())); VBox vbox = new VBox(10); Label dialogLabel = new Label( "Disabling a plugin will rename the plugin file by updating the extension. " @@ -72,12 +72,6 @@ protected Node getBody() { return layout; } - @Override - protected Node getHeading() { - return new Label("Disable plugin " + plugin.getName()); - - } - public void setPlugin(Plugin plugin) { this.plugin = plugin; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DonateDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DonateDialogController.java index 15519ab7..f6d3af91 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DonateDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/DonateDialogController.java @@ -19,10 +19,10 @@ package com.owlplug.core.controllers.dialogs; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.LazyViewRegistry; import com.owlplug.core.utils.PlatformUtils; import javafx.fxml.FXML; -import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; import org.springframework.beans.factory.annotation.Autowired; @@ -81,15 +81,17 @@ public void initialize() { } @Override - protected Node getBody() { - return lazyViewRegistry.get(LazyViewRegistry.DONATE_VIEW); - } + protected DialogLayout getLayout() { + DialogLayout dialogLayout = new DialogLayout(); - @Override - protected Node getHeading() { Label title = new Label("Owlplug is free !"); title.getStyleClass().add("heading-3"); - return title; + + dialogLayout.setHeading(title); + + dialogLayout.setBody(lazyViewRegistry.get(LazyViewRegistry.DONATE_VIEW)); + + return dialogLayout; } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ExportDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ExportDialogController.java index 19755aab..7f2ad524 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ExportDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ExportDialogController.java @@ -18,6 +18,7 @@ package com.owlplug.core.controllers.dialogs; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.LazyViewRegistry; import com.owlplug.core.model.Plugin; import com.owlplug.core.model.serializer.PluginCSVSerializer; @@ -27,7 +28,6 @@ import java.io.FileWriter; import java.io.IOException; import javafx.fxml.FXML; -import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; @@ -76,7 +76,7 @@ public void initialize() { fileChooser.setTitle("Save"); String exportType = exportComboBox.getSelectionModel().getSelectedItem(); - if("CSV".equals(exportType)) { + if ("CSV".equals(exportType)) { fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("CSV File", ".csv")); } else if ("JSON".equals(exportType)) { fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Json File", ".json")); @@ -84,7 +84,7 @@ public void initialize() { fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("All Files", "*.*")); File file = fileChooser.showSaveDialog(saveAsButton.getScene().getWindow()); - if(file != null) { + if (file != null) { try (FileWriter writer = new FileWriter(file)) { writer.write(exportTextArea.getText()); writer.flush(); @@ -107,7 +107,7 @@ private void refreshView() { String exportType = exportComboBox.getSelectionModel().getSelectedItem(); StringBuilder output = new StringBuilder(); - if("CSV".equals(exportType)) { + if ("CSV".equals(exportType)) { PluginCSVSerializer serializer = new PluginCSVSerializer(); output.append(serializer.getHeader()); output.append(serializer.serialize(plugins)); @@ -120,15 +120,15 @@ private void refreshView() { } @Override - protected Node getBody() { - return lazyViewRegistry.get(LazyViewRegistry.EXPORT_VIEW); + protected DialogLayout getLayout() { - } - - @Override - protected Node getHeading() { + DialogLayout layout = new DialogLayout(); Label title = new Label("Export Plugins"); title.getStyleClass().add("heading-3"); - return title; + layout.setHeading(title); + + layout.setBody(lazyViewRegistry.get(LazyViewRegistry.EXPORT_VIEW)); + + return layout; } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ListDirectoryDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ListDirectoryDialogController.java index 9d6c26ea..4c2fea94 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ListDirectoryDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/ListDirectoryDialogController.java @@ -18,6 +18,7 @@ package com.owlplug.core.controllers.dialogs; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.LazyViewRegistry; import com.owlplug.core.controllers.OptionsController; import java.util.ArrayList; @@ -26,7 +27,6 @@ import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.fxml.FXML; -import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.control.cell.TextFieldListCell; @@ -99,14 +99,10 @@ public void onChanged(Change change) { } - @Override - protected Node getBody() { - return lazyViewRegistry.get(LazyViewRegistry.LIST_DIRECTORY_VIEW); - } - - @Override - protected Node getHeading() { - return null; + protected DialogLayout getLayout() { + DialogLayout layout = new DialogLayout(); + layout.setBody(lazyViewRegistry.get(LazyViewRegistry.LIST_DIRECTORY_VIEW)); + return layout; } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/NewLinkController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/NewLinkController.java index f17b2975..8a324e98 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/NewLinkController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/NewLinkController.java @@ -19,6 +19,7 @@ package com.owlplug.core.controllers.dialogs; import com.owlplug.controls.AutoCompletePopup; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.ApplicationDefaults; import com.owlplug.core.components.CoreTaskFactory; import com.owlplug.core.components.LazyViewRegistry; @@ -187,17 +188,14 @@ private void setErrorMessage(String errorMessage) { } } - - @Override - protected Node getBody() { - return lazyViewRegistry.get(LazyViewRegistry.NEW_LINK_VIEW); - } - @Override - protected Node getHeading() { + protected DialogLayout getLayout() { + DialogLayout layout = new DialogLayout(); Label title = new Label("Create a new Link"); title.getStyleClass().add("heading-3"); - return title; + layout.setHeading(title); + layout.setBody(lazyViewRegistry.get(LazyViewRegistry.NEW_LINK_VIEW)); + return layout; } } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/WelcomeDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/WelcomeDialogController.java index 6bc65b88..c6bc960a 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/WelcomeDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/WelcomeDialogController.java @@ -18,6 +18,7 @@ package com.owlplug.core.controllers.dialogs; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.ApplicationDefaults; import com.owlplug.core.components.CoreTaskFactory; import com.owlplug.core.components.LazyViewRegistry; @@ -25,7 +26,6 @@ import com.owlplug.core.controllers.fragments.PluginPathFragmentController; import com.owlplug.core.model.platform.OperatingSystem; import javafx.fxml.FXML; -import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.image.ImageView; @@ -130,19 +130,19 @@ protected void onDialogShow() { } @Override - protected Node getBody() { - return lazyViewRegistry.get(LazyViewRegistry.WELCOME_VIEW); - } - - @Override - protected Node getHeading() { + protected DialogLayout getLayout() { + DialogLayout layout = new DialogLayout(); Label title = new Label("Owlplug is almost ready !"); title.getStyleClass().add("heading-3"); ImageView iv = new ImageView(this.getApplicationDefaults().rocketImage); iv.setFitHeight(20); iv.setFitWidth(20); title.setGraphic(iv); - return title; + layout.setHeading(title); + + layout.setBody(lazyViewRegistry.get(LazyViewRegistry.WELCOME_VIEW)); + + return layout; } } diff --git a/owlplug-client/src/main/java/com/owlplug/explore/controllers/NewSourceDialogController.java b/owlplug-client/src/main/java/com/owlplug/explore/controllers/NewSourceDialogController.java index a943e7bf..f47f657c 100644 --- a/owlplug-client/src/main/java/com/owlplug/explore/controllers/NewSourceDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/explore/controllers/NewSourceDialogController.java @@ -18,6 +18,7 @@ package com.owlplug.explore.controllers; +import com.owlplug.controls.DialogLayout; import com.owlplug.core.components.LazyViewRegistry; import com.owlplug.core.controllers.IEntityCreateOrUpdate; import com.owlplug.core.controllers.dialogs.AbstractDialogController; @@ -159,12 +160,8 @@ protected RemoteSource call() throws Exception { } @Override - protected Node getBody() { - return lazyViewRegistry.getAsNode(LazyViewRegistry.NEW_SOURCE_VIEW); - } - - @Override - protected Node getHeading() { + protected DialogLayout getLayout() { + DialogLayout layout = new DialogLayout(); Label title = new Label("Add a new source"); title.getStyleClass().add("heading-3"); @@ -172,7 +169,11 @@ protected Node getHeading() { iv.setFitHeight(20); iv.setFitWidth(20); title.setGraphic(iv); - return title; + layout.setHeading(title); + + layout.setBody(lazyViewRegistry.getAsNode(LazyViewRegistry.NEW_SOURCE_VIEW)); + return layout; + } } From 1c8e58cc156bec102681af1a0845821544cabb7c Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Tue, 7 Jan 2025 19:20:08 +0100 Subject: [PATCH 13/15] feat: use preferred view and select plugin in table and treeview --- .../core/components/ApplicationDefaults.java | 3 +++ .../controllers/PluginTableController.java | 11 ++++++++++ .../core/controllers/PluginsController.java | 21 +++++++++++++++++-- .../dialogs/AbstractDialogController.java | 11 ++-------- .../controllers/ProjectInfoController.java | 2 +- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java b/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java index 05ec03c8..3dc478b9 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java +++ b/owlplug-client/src/main/java/com/owlplug/core/components/ApplicationDefaults.java @@ -112,6 +112,8 @@ public class ApplicationDefaults { public static final String SHOW_DIALOG_DISABLE_PLUGIN_KEY = "SHOW_DIALOG_DISABLE_PLUGIN_KEY"; public static final String PROJECT_DIRECTORY_KEY = "PROJECT_DIRECTORY_KEY"; + public static final String PLUGIN_PREFERRED_DISPLAY_KEY = "PLUGIN_PREFERRED_DISPLAY_KEY"; + /** * Creates a new ApplicationDefaults. */ @@ -228,6 +230,7 @@ public String getOwlPlugRegistryUrl() { public String getStudiorackRegistryUrl() { return env.getProperty("studiorack.registry.url"); } + public String getEnvProperty(String property) { return env.getProperty(property); } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java index a9eadf28..0845eeb9 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginTableController.java @@ -28,6 +28,7 @@ import com.owlplug.core.utils.FileUtils; import com.owlplug.core.utils.PlatformUtils; import java.io.File; +import java.util.List; import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; @@ -41,6 +42,7 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableRow; import javafx.scene.control.TableView; +import javafx.scene.control.TreeItem; import javafx.scene.image.ImageView; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; @@ -188,6 +190,15 @@ public void setNodeManaged(boolean isManaged) { this.tableView.setVisible(isManaged); } + public void selectPluginById(long id) { + for (Plugin plugin : pluginList) { + if (plugin.getId().equals(id)) { + tableView.getSelectionModel().select(plugin); + break; + } + } + } + public SimpleStringProperty searchProperty() { return this.search; } diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java index f50df19f..009fef6b 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/PluginsController.java @@ -18,6 +18,7 @@ package com.owlplug.core.controllers; +import com.owlplug.core.components.ApplicationDefaults; import com.owlplug.core.components.CoreTaskFactory; import com.owlplug.core.controllers.dialogs.ExportDialogController; import com.owlplug.core.controllers.dialogs.NewLinkController; @@ -152,18 +153,30 @@ public void initialize() { treeViewController.setNodeManaged(true); tableController.setNodeManaged(false); setInfoPaneDisplay(true); + this.getPreferences().put(ApplicationDefaults.PLUGIN_PREFERRED_DISPLAY_KEY, "LIST"); } else if (newTab.equals(displayDirectoriesTab)) { treeViewController.setDisplayMode(PluginTreeViewController.Display.DirectoryTree); treeViewController.setNodeManaged(true); tableController.setNodeManaged(false); setInfoPaneDisplay(true); + this.getPreferences().put(ApplicationDefaults.PLUGIN_PREFERRED_DISPLAY_KEY, "DIRECTORIES"); } else { treeViewController.setNodeManaged(false); tableController.setNodeManaged(true); setInfoPaneDisplay(false); + this.getPreferences().put(ApplicationDefaults.PLUGIN_PREFERRED_DISPLAY_KEY, "TABLE"); } }); + if (this.getPreferences().get(ApplicationDefaults.PLUGIN_PREFERRED_DISPLAY_KEY, "").equals("TABLE")) { + displaySwitchTabPane.getSelectionModel().select(displayTableTab); + } else if (this.getPreferences().get(ApplicationDefaults.PLUGIN_PREFERRED_DISPLAY_KEY, "").equals("DIRECTORIES")) { + displaySwitchTabPane.getSelectionModel().select(displayDirectoriesTab); + } else { + displaySwitchTabPane.getSelectionModel().select(displayListTab); + } + + syncButton.setOnAction(e -> { this.getAnalyticsService().pageView("/app/core/action/syncPlugins"); pluginService.syncPlugins(); @@ -185,8 +198,12 @@ public void displayPlugins() { tableController.setPlugins(plugins); } - public void selectPluginInTreeById(long id) { - treeViewController.selectPluginInTreeById(id); + public void selectPluginById(long id) { + if (displaySwitchTabPane.getSelectionModel().getSelectedItem().equals(displayTableTab)) { + tableController.selectPluginById(id); + } else { + treeViewController.selectPluginInTreeById(id); + } } public void refresh() { diff --git a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java index d058e53e..1280ffa4 100644 --- a/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java +++ b/owlplug-client/src/main/java/com/owlplug/core/controllers/dialogs/AbstractDialogController.java @@ -49,18 +49,11 @@ public AbstractDialogController(double width, double height) { * Open and display dialog frame. */ public void show() { - onDialogShow(); - if (width != -1 && height != -1) { - if (this.getLayout() != null) { - this.getDialogManager().newDialog(width, height, this.getLayout()); - } + this.getDialogManager().newDialog(width, height, this.getLayout()); } else { - if (this.getLayout() != null) { - } else { - this.getDialogManager().newDialog(this.getLayout()); - } + this.getDialogManager().newDialog(this.getLayout()); } this.getDialogManager().getDialog().setOverlayClose(overlayClose); this.getDialogManager().getDialog().show(); diff --git a/owlplug-client/src/main/java/com/owlplug/project/controllers/ProjectInfoController.java b/owlplug-client/src/main/java/com/owlplug/project/controllers/ProjectInfoController.java index 52179de8..5e8ab707 100644 --- a/owlplug-client/src/main/java/com/owlplug/project/controllers/ProjectInfoController.java +++ b/owlplug-client/src/main/java/com/owlplug/project/controllers/ProjectInfoController.java @@ -162,7 +162,7 @@ public void updateItem(Plugin item, boolean empty) { Hyperlink link = new Hyperlink(); link.setGraphic(new ImageView(getApplicationDefaults().linkIconImage)); link.setOnAction(e -> { - pluginsController.selectPluginInTreeById(item.getId()); + pluginsController.selectPluginById(item.getId()); mainController.selectMainTab(MainController.PLUGINS_TAB_INDEX); }); setGraphic(link); From 0c2a166e8745bc0bc3637ac06e8ed9f093ca2da2 Mon Sep 17 00:00:00 2001 From: Arthur Poiret Date: Tue, 7 Jan 2025 19:28:01 +0100 Subject: [PATCH 14/15] style: fixed plugin search bar position --- owlplug-client/src/main/resources/fxml/PluginsView.fxml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/owlplug-client/src/main/resources/fxml/PluginsView.fxml b/owlplug-client/src/main/resources/fxml/PluginsView.fxml index 12ab49d4..b6945a21 100644 --- a/owlplug-client/src/main/resources/fxml/PluginsView.fxml +++ b/owlplug-client/src/main/resources/fxml/PluginsView.fxml @@ -2,7 +2,6 @@ - @@ -13,9 +12,8 @@ - - + @@ -27,7 +25,8 @@ - + +