All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.praxislive.ide.project.ui.LibrariesCustomizer Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2020 Neil C Smith.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 3 for more details.
 *
 * You should have received a copy of the GNU General Public License version 3
 * along with this work; if not, see http://www.gnu.org/licenses/
 *
 *
 * Please visit https://www.praxislive.org if you need additional information or
 * have any questions.
 */
package org.praxislive.ide.project.ui;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.swing.Action;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.praxislive.ide.project.DefaultPraxisProject;
import org.praxislive.ide.project.ProjectPropertiesImpl;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.view.ListView;
import org.openide.filesystems.FileChooserBuilder;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
 *
 */
@NbBundle.Messages({
    "ERR_removingInUse=Can't remove libraries in use by an active project",
    "TTL_import=Import library",
    "LBL_import=Import",
    "TTL_libraryURI=Add library",
    "LBL_libraryURI=Enter a library URI, path or Package URL",
    "HLP_libraryURI=PURL - pkg:maven/[group]/[artifact]@[version]"
})
class LibrariesCustomizer extends javax.swing.JPanel implements ExplorerManager.Provider {

    private final ExplorerManager manager;
    private final DefaultPraxisProject project;
    private final ProjectPropertiesImpl props;
    private final List libraries;
    private final List filesToImport;
    private final LibraryChildren children;
    private final Node root;

    LibrariesCustomizer(DefaultPraxisProject project) {
        this.project = Objects.requireNonNull(project);
        props = project.getLookup().lookup(ProjectPropertiesImpl.class);
        libraries = new ArrayList<>();
        filesToImport = new ArrayList<>();
        children = new LibraryChildren();
        root = new AbstractNode(children);
        manager = new ExplorerManager();
        refresh();
        manager.setRootContext(root);
        manager.addPropertyChangeListener(new ManagerListener());
        initComponents();
    }

    final void refresh() {
        libraries.clear();
        filesToImport.clear();
        if (props != null) {
            libraries.addAll(props.getLibraries());
        }
        refreshView();
    }
    
    final void updateProject() {
        copyFiles();
        props.setLibraries(libraries);
    }

    private void refreshView() {
        children.setLibraries(libraries);
    }
    
    private void copyFiles() {
        if (filesToImport.isEmpty()) {
            return;
        }
        try {
            FileObject libFolder = FileUtil.createFolder(project.getProjectDirectory(), "libs");
            for (FileObject libFile : filesToImport) {
                FileUtil.copyFile(libFile, libFolder, libFile.getName());
            }
        } catch (Exception ex) {
            Exceptions.printStackTrace(ex);
        } finally {
            filesToImport.clear();
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // //GEN-BEGIN:initComponents
    private void initComponents() {

        fileList = new ListView();
        importButton = new javax.swing.JButton();
        removeButton = new javax.swing.JButton();
        addButton = new javax.swing.JButton();

        importButton.setText(org.openide.util.NbBundle.getMessage(LibrariesCustomizer.class, "LibrariesCustomizer.importButton.text")); // NOI18N
        importButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importButtonActionPerformed(evt);
            }
        });

        removeButton.setText(org.openide.util.NbBundle.getMessage(LibrariesCustomizer.class, "LibrariesCustomizer.removeButton.text")); // NOI18N
        removeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeButtonActionPerformed(evt);
            }
        });

        addButton.setText(org.openide.util.NbBundle.getMessage(LibrariesCustomizer.class, "LibrariesCustomizer.addButton.text")); // NOI18N
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(fileList, javax.swing.GroupLayout.PREFERRED_SIZE, 312, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(importButton, javax.swing.GroupLayout.DEFAULT_SIZE, 91, Short.MAX_VALUE)
                    .addComponent(removeButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(addButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(fileList, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(importButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(addButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(removeButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// //GEN-END:initComponents

    private void importButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed
        importFiles();
    }//GEN-LAST:event_importButtonActionPerformed

    private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
        removeSelectedNodes();
    }//GEN-LAST:event_removeButtonActionPerformed

    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
        addURI();
    }//GEN-LAST:event_addButtonActionPerformed

    private void importFiles() {
        FileChooserBuilder fcb = new FileChooserBuilder(LibrariesCustomizer.class)
                .setFilesOnly(true)
                .setTitle(Bundle.TTL_import())
                .setApproveText(Bundle.LBL_import())
                .forceUseOfDefaultWorkingDirectory(true)
                .setAcceptAllFileFilterUsed(true)
                .setFileFilter(new FileNameExtensionFilter("JAR files", "jar"));
        File[] files = fcb.showMultiOpenDialog();
        if (files != null) {
            for (File file : files) {
                FileObject fo = FileUtil.toFileObject(file);
                if (FileUtil.isParentOf(project.getProjectDirectory(), fo)) {
                    if (fo.hasExt("jar")) {
                        checkAndAddURI(fo.toURI().relativize(project.getProjectDirectory().toURI()));
                    }
                } else {
                    filesToImport.add(fo);
                    if (fo.hasExt("jar")) {
                        try {
                            checkAndAddURI(new URI(null, null, "libs/" + file.getName(), null));
                        } catch (URISyntaxException ex) {
                            Exceptions.printStackTrace(ex);
                        }
                    }
                }
            }
            refreshView();
        }
    }
    
    
    private void addURI() {
        var input = new NotifyDescriptor.InputLine(Bundle.LBL_libraryURI(), Bundle.TTL_libraryURI());
        input.createNotificationLineSupport().setInformationMessage(Bundle.HLP_libraryURI());
        Object ret = DialogDisplayer.getDefault().notify(input);
        if (ret == NotifyDescriptor.OK_OPTION) {
            try {
                checkAndAddURI(new URI(input.getInputText().trim()));
            } catch (URISyntaxException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        refreshView();
    }
    
    private boolean checkAndAddURI(URI lib) {
        if (libraries.contains(lib)) {
            return false;
        } else {
            return libraries.add(lib);
        }
    }
    
    private void removeSelectedNodes() {
        boolean inUse = false;
        List existing = props.getLibraries();
        for (Node node : manager.getSelectedNodes()) {
            if (!(node instanceof LibraryNode)) {
                continue;
            }
            final URI lib = ((LibraryNode) node).uri;
            if (project.isActive()) {
                if (existing.contains(lib)) {
                    inUse = true;
                } else {
                    libraries.remove(lib);
                }
            } else {
                libraries.remove(lib);
            }
        }
        if (inUse) {
            ProjectDialogManager.get(project).reportError(Bundle.ERR_removingInUse());
        }
        refreshView();
    }
    

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addButton;
    private javax.swing.JScrollPane fileList;
    private javax.swing.JButton importButton;
    private javax.swing.JButton removeButton;
    // End of variables declaration//GEN-END:variables

    @Override
    public ExplorerManager getExplorerManager() {
        return manager;
    }

    private class ManagerListener implements PropertyChangeListener {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
                if (manager.getSelectedNodes().length > 0) {
                    removeButton.setEnabled(true);
                } else {
                    removeButton.setEnabled(false);
                }

            }
        }
    }

    private class LibraryNode extends AbstractNode {

        private final URI uri;

        LibraryNode(URI uri) {
            super(Children.LEAF);
            this.uri = uri;
        }

        @Override
        public Action getPreferredAction() {
            return null;
        }

        @Override
        public Action[] getActions(boolean context) {
            return new Action[0];
        }

        @Override
        public String getDisplayName() {
            return uri.toString();
        }

    }

    private class LibraryChildren extends Children.Keys {

        void setLibraries(List keys) {
            setKeys(keys);
        }

        @Override
        protected Node[] createNodes(URI key) {
            return new Node[]{new LibraryNode(key)};
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy