net.andydvorak.intellij.lessc.ui.configurable.LessProfilesPanel.java Source code

Java tutorial

Introduction

Here is the source code for net.andydvorak.intellij.lessc.ui.configurable.LessProfilesPanel.java

Source

/*
 * Copyright 2012 Andrew C. Dvorak.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.andydvorak.intellij.lessc.ui.configurable;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.Conditions;
import com.intellij.util.PlatformIcons;
import net.andydvorak.intellij.lessc.LessManager;
import net.andydvorak.intellij.lessc.state.CssDirectory;
import net.andydvorak.intellij.lessc.ui.messages.UIBundle;
import net.andydvorak.intellij.lessc.state.LessProfile;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

class LessProfilesPanel extends MasterDetailsComponent implements SearchableConfigurable {

    @NotNull
    private final Project project;
    @NotNull
    private final LessManager lessManager;
    @NotNull
    private final AtomicBoolean isInitialized = new AtomicBoolean(false);

    private final List<LessProfileConfigurableForm> profileForms = new ArrayList<LessProfileConfigurableForm>();

    public LessProfilesPanel(@NotNull final Project project) {
        this.project = project;
        this.lessManager = LessManager.getInstance(project);
        initTree();
    }

    protected boolean wasObjectStored(final Object o) {
        if (o == null || LessProfile.class != o.getClass())
            return false;
        final LessProfile profile = (LessProfile) o;
        return lessManager.getProfileMap().containsKey(profile.getId());
    }

    public void apply() throws ConfigurationException {
        final Set<String> names = new HashSet<String>();

        // Check for duplicate profile names
        for (int i = 0; i < myRoot.getChildCount(); i++) {
            final MyNode node = (MyNode) myRoot.getChildAt(i);
            final LessProfileConfigurableForm form = (LessProfileConfigurableForm) node.getConfigurable();
            final LessProfile profile = form.getCurrentState();
            final String name = profile.getName();
            final String dirPath = profile.getLessDirPath();

            if (StringUtils.isBlank(name)) {
                selectNodeInTree(name);
                throw new ConfigurationException(UIBundle.message("blank.less.profile.name"));
            }

            if (names.contains(name)) {
                selectNodeInTree(name);
                throw new ConfigurationException(UIBundle.message("duplicate.less.profile.name", name));
            }

            if (StringUtils.isBlank(dirPath)) {
                selectNodeInTree(name);
                throw new ConfigurationException(UIBundle.message("blank.less.profile.source.dir"));
            }

            if (!profile.getLessDir().exists()) {
                if (!confirmWarning(UIBundle.message("nonexistent.less.profile.source.dir.title"),
                        UIBundle.message("nonexistent.less.profile.source.dir.prompt", dirPath))) {
                    selectNodeInTree(name);
                    throw new ConfigurationException(
                            UIBundle.message("nonexistent.less.profile.source.dir.error", dirPath));
                }
            }

            if (profile.getCssDirectories().isEmpty()) {
                selectNodeInTree(name);
                throw new ConfigurationException(UIBundle.message("no.less.profile.css.dirs"));
            }

            for (final CssDirectory cssDirectory : profile.getCssDirectories()) {
                if (!new File(cssDirectory.getPath()).exists()) {
                    if (!confirmWarning(UIBundle.message("nonexistent.less.profile.css.dir.title"),
                            UIBundle.message("nonexistent.less.profile.css.dir.prompt", dirPath))) {
                        selectNodeInTree(name);
                        throw new ConfigurationException(
                                UIBundle.message("nonexistent.less.profile.css.dir.error", dirPath));
                    }
                }
            }

            names.add(name);
        }

        super.apply();
    }

    protected void processRemovedItems() {
        final Map<Integer, LessProfile> profiles = getProfileMap();
        final List<Integer> deletedIds = new ArrayList<Integer>();

        // Compile a list of all profiles that are no longer present in the UI
        for (final LessProfile profile : lessManager.getProfiles()) {
            if (!profiles.containsKey(profile.getId())) {
                deletedIds.add(profile.getId());
            }
        }

        // Remove the deleted profiles from the manager
        for (final int id : deletedIds) {
            lessManager.removeProfile(id);
        }
    }

    public void reset() {
        reloadTree();
        super.reset();
    }

    @Override
    public void disposeUIResources() {
        super.disposeUIResources();
        isInitialized.set(false);
    }

    @Nullable
    protected ArrayList<AnAction> createActions(final boolean fromPopup) {
        final ArrayList<AnAction> result = new ArrayList<AnAction>();

        final String addText = UIBundle.message("action.add.less.profile.text");
        final String addDescription = UIBundle.message("action.add.less.profile.description");
        final String addPromptTitle = UIBundle.message("action.add.less.profile.prompt.title");

        result.add(new AnAction(addText, addDescription, PlatformIcons.ADD_ICON) {
            {
                registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
            }

            public void actionPerformed(final AnActionEvent event) {
                final String name = askForProfileName(addPromptTitle, "");
                if (name == null)
                    return;
                final LessProfile lessProfile = new LessProfile(getNextId(), name);
                addProfileNode(lessProfile);
            }
        });

        result.add(new MyDeleteAction(forAll(Conditions.alwaysTrue())));

        final String copyText = UIBundle.message("action.copy.less.profile.text");
        final String copyDescription = UIBundle.message("action.copy.less.profile.description");
        final String copyPromptTitle = UIBundle.message("action.copy.less.profile.prompt.title");

        result.add(new AnAction(copyText, copyDescription, PlatformIcons.COPY_ICON) {
            {
                registerCustomShortcutSet(
                        new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.CTRL_MASK)), myTree);
            }

            public void actionPerformed(final AnActionEvent event) {
                final String profileName = askForProfileName(copyPromptTitle, "");
                if (profileName == null)
                    return;
                final LessProfile clone = new LessProfile(getNextId(), (LessProfile) getSelectedObject());
                clone.setName(profileName);
                addProfileNode(clone);
            }

            public void update(final AnActionEvent event) {
                super.update(event);
                event.getPresentation().setEnabled(getSelectedObject() != null);
            }
        });

        return result;
    }

    private void addProfileNode(final LessProfile lessProfile) {
        final LessProfileConfigurableForm profileForm = new LessProfileConfigurableForm(project, lessProfile, this,
                TREE_UPDATER);
        profileForm.setModified(true);
        profileForms.add(profileForm);
        final MyNode node = new MyNode(profileForm);
        addNode(node, myRoot);
        selectNodeInTree(node);
    }

    private void reloadTree() {
        myRoot.removeAllChildren();
        profileForms.clear();
        final Collection<LessProfile> profiles = lessManager.getProfiles();
        for (final LessProfile profile : profiles) {
            final LessProfile clone = new LessProfile(profile.getId(), profile);
            final LessProfileConfigurableForm profileForm = new LessProfileConfigurableForm(project, clone, this,
                    TREE_UPDATER);
            profileForms.add(profileForm);
            addNode(new MyNode(profileForm), myRoot);
        }
        isInitialized.set(true);
    }

    private Map<Integer, LessProfile> getProfileMap() {
        if (!isInitialized.get()) {
            return getManagerProfileMap();
        } else {
            return getUIProfileMap();
        }
    }

    private Map<Integer, LessProfile> getManagerProfileMap() {
        return lessManager.getProfileMap();
    }

    private Map<Integer, LessProfile> getUIProfileMap() {
        final Map<Integer, LessProfile> profiles = new com.intellij.util.containers.HashMap<Integer, LessProfile>();
        for (int i = 0; i < myRoot.getChildCount(); i++) {
            final MyNode node = (MyNode) myRoot.getChildAt(i);
            final LessProfile lessProfile = ((LessProfileConfigurableForm) node.getConfigurable())
                    .getEditableObject();
            profiles.put(lessProfile.getId(), lessProfile);
        }
        return profiles;
    }

    private int getNextId() {
        int id = -1;
        for (final LessProfile profile : getManagerProfileMap().values()) {
            if (profile.getId() > id) {
                id = profile.getId();
            }
        }
        for (final LessProfile profile : getUIProfileMap().values()) {
            if (profile.getId() > id) {
                id = profile.getId();
            }
        }
        return id + 1;
    }

    @Nullable
    private String askForProfileName(final String title, final String initialName) {
        final String message = UIBundle.message("action.new.less.profile.prompt.message");
        return Messages.showInputDialog(message, title, Messages.getQuestionIcon(), initialName,
                new InputValidator() {
                    public boolean checkInput(final String newName) {
                        if (newName == null || newName.length() == 0) {
                            return false;
                        }
                        // Don't allow duplicate profile names
                        for (final LessProfile profile : getProfileMap().values()) {
                            if (StringUtils.equals(newName, profile.getName())) {
                                return false;
                            }
                        }
                        return true;
                    }

                    public boolean canClose(final String s) {
                        return checkInput(s);
                    }
                });
    }

    private boolean confirmWarning(final String title, final String message) {
        return Messages.YES == Messages.showYesNoDialog(message, title, Messages.getWarningIcon());
    }

    public void setPromptButtonsEnabled(final boolean enabled) {
        for (final LessProfileConfigurableForm profileForm : profileForms) {
            profileForm.setPromptButtonEnabled(enabled);
        }
    }
    /*
     * Method overrides and interface implementations
     */

    @NotNull
    public String getId() {
        return "lessc.profiles";
    }

    @Nls
    public String getDisplayName() {
        return UIBundle.message("pref.display.name");
    }

    @Nullable
    @NonNls
    public String getHelpTopic() {
        return null;
    }

    public Runnable enableSearch(final String option) {
        return null;
    }

    @Override
    protected String getEmptySelectionString() {
        return UIBundle.message("profile.empty.selection");
    }

    @Override
    protected String getComponentStateKey() {
        return "LessCompiler.UI";
    }

    @Override
    protected MasterDetailsStateService getStateService() {
        return MasterDetailsStateService.getInstance(project);
    }

}