com.opendoorlogistics.studio.scripts.list.ScriptsPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.opendoorlogistics.studio.scripts.list.ScriptsPanel.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v3
 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt
 ******************************************************************************/
package com.opendoorlogistics.studio.scripts.list;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Action;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;

import org.apache.commons.io.FilenameUtils;

import com.opendoorlogistics.api.ODLApi;
import com.opendoorlogistics.api.ui.Disposable;
import com.opendoorlogistics.core.scripts.ScriptConstants;
import com.opendoorlogistics.core.scripts.ScriptsProvider;
import com.opendoorlogistics.core.scripts.ScriptsProvider.HasScriptsProvider;
import com.opendoorlogistics.core.scripts.elements.Script;
import com.opendoorlogistics.core.scripts.elements.ScriptEditorType;
import com.opendoorlogistics.core.utils.io.WatchSingleDirectory;
import com.opendoorlogistics.core.utils.io.WatchSingleDirectory.DirectoryChangedListener;
import com.opendoorlogistics.core.utils.ui.FileBrowserPanel;
import com.opendoorlogistics.api.ui.UIFactory.FilenameChangeListener;
import com.opendoorlogistics.core.utils.ui.LayoutUtils;
import com.opendoorlogistics.studio.PreferencesManager;
import com.opendoorlogistics.studio.PreferencesManager.PrefKey;
import com.opendoorlogistics.studio.appframe.AppPermissions;
import com.opendoorlogistics.studio.scripts.componentwizard.SetupComponentWizard;
import com.opendoorlogistics.studio.scripts.execution.ScriptUIManager;
import com.opendoorlogistics.studio.utils.SwingFriendlyDirectoryChangedListener;
import com.opendoorlogistics.utils.ui.SimpleAction;
import com.opendoorlogistics.utils.ui.SimpleActionConfig;

final public class ScriptsPanel extends JPanel implements DirectoryChangedListener, Disposable, HasScriptsProvider {
    private final ScriptsTree scriptsTree;
    private final List<MyAction> actions;
    private final ScriptUIManager scriptUIManager;
    private final JPopupMenu popup;
    private final ODLApi api;
    private final FileBrowserPanel dirChooser;
    private File directory;
    private WatchSingleDirectory watcher;

    // public boolean isRunnable(ScriptNode node) {
    // return node != null && launchScriptEditor.hasLoadedData() && node.isAvailable() && node.isRunnable();
    // }

    private abstract class MyAction extends SimpleAction {
        private final boolean needsLoadedData;
        private final boolean needsRunnable;
        private final boolean needsAvailable;

        public MyAction(SimpleActionConfig config, boolean needsLoadedData, boolean needsRunnable,
                boolean needsAvailable) {
            super(config);
            this.needsLoadedData = needsLoadedData;
            this.needsRunnable = needsRunnable;
            this.needsAvailable = needsAvailable;
        }

        @Override
        public void updateEnabledState() {
            ScriptNode selected = scriptsTree.getSelectedValue();
            boolean enabled = true;
            if (requiresSelection && selected == null) {
                enabled = false;
            }
            if (enabled && needsLoadedData && scriptUIManager.hasLoadedData() == false) {
                enabled = false;
            }
            if (enabled && needsRunnable && (selected == null || selected.isRunnable() == false)) {
                enabled = false;
            }
            if (enabled && needsAvailable && (selected == null || selected.isAvailable() == false)) {
                enabled = false;
            }
            setEnabled(enabled);
        }
    }

    /**
     * Create the panel.
     */
    public ScriptsPanel(ODLApi api, File directory, ScriptUIManager launchScriptEditor) {
        this.scriptUIManager = launchScriptEditor;
        this.api = api;

        // find a sensible directory
        if (directory == null) {
            directory = new File(ScriptConstants.DIRECTORY);
            if (!directory.exists()) {
                directory = new File("");
            }
        }
        this.directory = directory;
        setLayout(new BorderLayout(0, 0));

        // Add directory browser and label at the top in their own panel.
        // Label is wrapped in a panel because alignment is being ignored and this at least makes it properly centred.
        // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4275005
        boolean lockedDir = scriptUIManager.getAppPermissions().isScriptDirectoryLocked();
        if (!lockedDir) {
            JLabel lblLabel = new JLabel("Scripts directory");
            JPanel labelPanel = new JPanel(new BorderLayout());
            labelPanel.add(lblLabel, BorderLayout.CENTER);
            labelPanel.setMaximumSize(lblLabel.getMinimumSize());
            dirChooser = new FileBrowserPanel(directory.getAbsolutePath(), new FilenameChangeListener() {

                @Override
                public void filenameChanged(String newFilename) {
                    ScriptsPanel.this.directory = new File(newFilename);
                    onDirectoryChanged(ScriptsPanel.this.directory);
                }
            }, true, "Select");
            JPanel topPanel = LayoutUtils.createVerticalBoxLayout(labelPanel, dirChooser);
            add(topPanel, BorderLayout.NORTH);
        } else {
            dirChooser = null;
        }

        // add toolbar at the bottom
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        add(toolBar, BorderLayout.SOUTH);

        // create all actions and add as buttons and menu items
        popup = new JPopupMenu();
        actions = createActions(launchScriptEditor.getAppPermissions());
        for (Action action : actions) {
            toolBar.add(action);
            popup.add(action);
        }

        // add list in the centre
        scriptsTree = new ScriptsTree(scriptUIManager, popup);
        scriptsTree.addTreeSelectionListener(new TreeSelectionListener() {

            @Override
            public void valueChanged(TreeSelectionEvent e) {
                ScriptsPanel.this.updateAppearance();
            }
        });
        add(scriptsTree.getScrollPane(), BorderLayout.CENTER);

        // // create selection changed listener on the list
        // listControl.addListSelectionListener(new ListSelectionListener() {
        //
        // @Override
        // public void valueChanged(ListSelectionEvent e) {
        // updateAppearance();
        // }
        // });

        // finally file the list
        onDirectoryChanged(directory);

    }

    public List<File> getScriptsByType(ScriptEditorType type) {
        return scriptsTree.getScriptsByType(type);
    }

    private boolean isOkDirectory() {
        return directory != null && directory.isDirectory() && directory.exists();
    }

    private List<MyAction> createActions(AppPermissions appPermissions) {
        ArrayList<MyAction> ret = new ArrayList<>();

        if (appPermissions.isScriptEditingAllowed()) {

            ret.add(new MyAction(SimpleActionConfig.addItem.setItemName("script"), false, false, false) {

                @Override
                public void actionPerformed(ActionEvent e) {

                    Script script = new SetupComponentWizard(SwingUtilities.getWindowAncestor(ScriptsPanel.this),
                            api, scriptUIManager.getAvailableFieldsQuery()).showModal();
                    // Script script =new ScriptWizardActions(api,SwingUtilities.getWindowAncestor(ScriptsPanel.this)).promptUser();
                    if (script != null) {
                        scriptUIManager.launchScriptEditor(script, null, isOkDirectory() ? directory : null);
                    }
                }
            });

            ret.add(new MyAction(SimpleActionConfig.editItem.setItemName("script"), false, false, true) {

                @Override
                public void actionPerformed(ActionEvent e) {
                    ScriptNode node = scriptsTree.getSelectedValue();
                    if (node != null && node.isAvailable()) {
                        ScriptsPanel.this.scriptUIManager.launchScriptEditor(node.getFile(),
                                node.getLaunchEditorId());
                    }
                }
            });

            ret.add(new MyAction(SimpleActionConfig.deleteItem.setItemName("script"), false, false, false) {

                @Override
                public void actionPerformed(ActionEvent e) {
                    ScriptNode node = scriptsTree.getSelectedValue();
                    if (node == null) {
                        return;
                    }
                    if (JOptionPane.showConfirmDialog(ScriptsPanel.this,
                            "Really delete script " + node.getFile().getName() + " from disk?", "Delete script",
                            JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION) {
                        if (!node.getFile().delete()) {
                            JOptionPane.showMessageDialog(ScriptsPanel.this, "Could not delete file");
                        } else {
                            onDirectoryChanged(directory);
                        }
                    }
                }

                @Override
                public void updateEnabledState() {
                    ScriptNode selected = scriptsTree.getSelectedValue();
                    boolean enabled = true;
                    if (selected == null) {
                        enabled = false;
                    }
                    if (enabled && selected.isScriptRoot() == false) {
                        // can only delete the root
                        enabled = false;
                    }
                    setEnabled(enabled);
                }
            });

            ret.add(new MyAction(SimpleActionConfig.testCompileScript, true, false, true) {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ScriptNode node = scriptsTree.getSelectedValue();
                    if (node != null) {
                        scriptUIManager.testCompileScript(node.getFile(), node.getLaunchExecutorId());
                    }
                }
            });

            ret.add(new MyAction(SimpleActionConfig.runScript, true, true, true) {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ScriptNode node = scriptsTree.getSelectedValue();
                    if (node != null) {
                        scriptUIManager.executeScript(node.getFile(), node.getLaunchExecutorId());
                    }
                }

                @Override
                public void updateEnabledState() {
                    setEnabled(ScriptNode.isRunnable(scriptsTree.getSelectedValue(), scriptUIManager));
                }
            });

        }

        return ret;
    }

    public void updateAppearance() {
        for (MyAction action : actions) {
            action.updateEnabledState();
        }
        scriptsTree.updateAppearance();

    }

    @Override
    public void onDirectoryChanged(File directory) {
        // set new directory
        this.directory = directory;
        PreferencesManager.getSingleton().setDirectory(PrefKey.SCRIPTS_DIR, directory);

        // check to see if watcher is pointing at wrong one
        if (watcher != null && watcher.getDirectory().equals(directory) == false) {
            shutdownDirectoryWatcher();
        }

        ScriptNode selected = scriptsTree.getSelectedValue();
        if (isOkDirectory()) {
            scriptsTree.setEnabled(true);
            final File[] files = directory.listFiles(new FileFilter() {

                @Override
                public boolean accept(File pathname) {
                    return pathname.isFile()
                            && FilenameUtils.isExtension(pathname.getAbsolutePath(), ScriptConstants.FILE_EXT);
                }
            });

            scriptsTree.setFiles(files);

            // reselect
            if (selected != null) {
                scriptsTree.setSelected(selected);
            }

            // init watcher
            if (watcher == null) {
                watcher = WatchSingleDirectory.launch(directory, new SwingFriendlyDirectoryChangedListener(this));
            }
        } else {
            shutdownDirectoryWatcher();

            // set list to empty
            scriptsTree.setFiles(new File[] {});
            scriptsTree.setEnabled(false);
        }

        updateAppearance();
    }

    public void shutdownDirectoryWatcher() {
        if (watcher != null) {
            watcher.shutdown();
            watcher = null;
        }
    }

    // public static void main(String[] args) {
    //
    // javax.swing.SwingUtilities.invokeLater(new Runnable() {
    // public void run() {
    // InitialiseStudio.initialise();
    // JFrame frame = new JFrame("");
    // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // // frame.setContentPane(new ScriptsPanel(new File("C:\\Users\\Phil\\Documents")));
    // frame.setContentPane(new ScriptsPanelV2(null, null));
    // frame.pack();
    // frame.setSize(600, 600);
    // frame.setVisible(true);
    // }
    // });
    // }

    @Override
    public synchronized void dispose() {
        if (watcher != null) {
            watcher.shutdown();
            watcher = null;
        }
    }

    public ScriptNode[] getScripts() {
        return scriptsTree.getScriptNodes();
    }

    @Override
    public ScriptsProvider getScriptsProvider() {
        return scriptsTree.getScriptsProvider();
    }

    public void setScriptsDirectory(File directory) {
        if (dirChooser != null) {
            dirChooser.setFilename(directory.getAbsolutePath());
        }
        onDirectoryChanged(directory);
    }
}