| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.netbeans.modules.gradle.execute.navigator; |
| |
| import org.netbeans.modules.gradle.api.GradleTask; |
| import org.netbeans.modules.gradle.api.NbGradleProject; |
| import org.netbeans.modules.gradle.spi.nodes.NodeUtils; |
| import java.awt.Image; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Set; |
| import javax.swing.Action; |
| import javax.swing.SwingUtilities; |
| import javax.swing.event.ChangeListener; |
| import javax.swing.tree.TreeSelectionModel; |
| import org.netbeans.api.annotations.common.StaticResource; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ProjectManager; |
| import org.netbeans.api.project.ProjectUtils; |
| import org.netbeans.modules.gradle.FavoriteTaskManager; |
| import org.netbeans.modules.gradle.api.GradleBaseProject; |
| import org.openide.explorer.ExplorerManager; |
| import org.openide.explorer.view.BeanTreeView; |
| import org.openide.filesystems.FileObject; |
| import org.openide.loaders.DataObject; |
| import org.openide.nodes.AbstractNode; |
| import org.openide.nodes.Children; |
| import org.openide.nodes.Node; |
| import org.openide.util.Lookup; |
| import org.openide.util.NbBundle.Messages; |
| import org.openide.util.RequestProcessor; |
| |
| import static org.netbeans.modules.gradle.execute.navigator.Bundle.*; |
| import org.netbeans.modules.gradle.nodes.TaskNode; |
| import org.netbeans.modules.gradle.spi.Utils; |
| import org.openide.util.WeakListeners; |
| import org.openide.util.lookup.Lookups; |
| |
| /** |
| * |
| * @author Laszlo Kishalmi |
| */ |
| public class TasksPanel extends javax.swing.JPanel implements ExplorerManager.Provider, Runnable { |
| |
| @StaticResource |
| private static final String GRADLE_ICON = "org/netbeans/modules/gradle/resources/gradle.png"; //NOI18 |
| |
| private final transient ExplorerManager manager = new ExplorerManager(); |
| private final BeanTreeView treeView; |
| private NbGradleProject current; |
| private Project currentP; |
| private final PropertyChangeListener pchadapter = (PropertyChangeEvent evt) -> { |
| if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) { |
| RequestProcessor.getDefault().post(TasksPanel.this); |
| } |
| }; |
| |
| /** |
| * Creates new form TasksPanel |
| */ |
| @Messages({ |
| "# {0} - The display name of the project", |
| "LBL_Tasks=Tasks of {0}", |
| "LBL_Favorites=Favorite Tasks" |
| }) |
| public TasksPanel() { |
| treeView = new BeanTreeView(); |
| setLayout(new java.awt.BorderLayout()); |
| |
| add(treeView, java.awt.BorderLayout.CENTER); |
| treeView.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); |
| } |
| |
| @Override |
| public ExplorerManager getExplorerManager() { |
| return manager; |
| } |
| |
| void navigate(DataObject d) { |
| if (current != null) { |
| current.removePropertyChangeListener(pchadapter); |
| } |
| NbGradleProject n = null; |
| |
| FileObject f = d.getPrimaryFile(); |
| if (!f.isFolder()) { |
| f = f.getParent(); |
| } |
| Project p = null; |
| try { |
| p = ProjectManager.getDefault().findProject(f); |
| if (p != null) { |
| n = NbGradleProject.get(p); |
| } |
| } catch (IOException | IllegalArgumentException ex) { |
| //Ignore we can't really do anything about this. |
| } |
| |
| if (n == null) { |
| release(); |
| return; |
| } |
| |
| current = n; |
| currentP = p; |
| current.addPropertyChangeListener(pchadapter); |
| RequestProcessor.getDefault().post(this); |
| } |
| |
| @Override |
| public void run() { |
| if (currentP != null) { |
| |
| GradleBaseProject prj = GradleBaseProject.get(currentP); |
| if (prj != null) { |
| final Children taskGroups = new Children.Array(); |
| ArrayList<String> glist = new ArrayList<>(prj.getTaskGroups()); |
| glist.remove(GradleBaseProject.PRIVATE_TASK_GROUP); |
| Collections.sort(glist, String.CASE_INSENSITIVE_ORDER); |
| |
| for (String group : glist) { |
| taskGroups.add(new Node[]{new TaskGroupNode(group, prj)}); |
| } |
| taskGroups.add(new Node[]{new TaskGroupNode(GradleBaseProject.PRIVATE_TASK_GROUP, prj)}); |
| |
| AbstractNode tasksNode = new AbstractNode(taskGroups, Lookups.singleton(currentP)) { |
| @Override |
| public Action[] getActions(boolean context) { |
| return new Action[0]; |
| } |
| |
| }; |
| tasksNode.setName("tasks"); //NOI18N |
| tasksNode.setDisplayName(Bundle.LBL_Tasks(ProjectUtils.getInformation(currentP).getDisplayName())); |
| tasksNode.setIconBaseWithExtension(GRADLE_ICON); |
| |
| AbstractNode favoritesNode = new AbstractNode(new FavoritesChildren()) { |
| @Override |
| public Action[] getActions(boolean context) { |
| return new Action[0]; |
| } |
| |
| }; |
| favoritesNode.setName("favorites"); //NOI18N |
| favoritesNode.setDisplayName(Bundle.LBL_Favorites()); |
| favoritesNode.setIconBaseWithExtension(GRADLE_ICON); |
| |
| final Children rootKids = new Children.Array(); |
| rootKids.add(new Node[]{favoritesNode, tasksNode}); |
| SwingUtilities.invokeLater(() -> { |
| treeView.setScrollsOnExpand(false); |
| treeView.setRootVisible(false); |
| manager.setRootContext(new AbstractNode(rootKids)); |
| treeView.expandAll(); |
| treeView.setScrollsOnExpand(true); |
| }); |
| return; |
| } |
| |
| } |
| SwingUtilities.invokeLater(() -> { |
| treeView.setRootVisible(false); |
| manager.setRootContext(createEmptyNode()); |
| }); |
| } |
| |
| void release() { |
| if (current != null) { |
| current.removePropertyChangeListener(pchadapter); |
| } |
| current = null; |
| currentP = null; |
| SwingUtilities.invokeLater(() -> { |
| treeView.setRootVisible(false); |
| manager.setRootContext(createEmptyNode()); |
| }); |
| } |
| |
| private static Node createEmptyNode() { |
| return new AbstractNode(Children.LEAF); |
| } |
| |
| private class TaskGroupNode extends AbstractNode { |
| |
| @Messages({ |
| "LBL_PrivateTasks=Other Tasks" |
| }) |
| @SuppressWarnings("OverridableMethodCallInConstructor") |
| public TaskGroupNode(String group, GradleBaseProject project) { |
| super(new TaskGroupChildren(group, project), Lookup.EMPTY); |
| setName(group); |
| String displayName = GradleBaseProject.PRIVATE_TASK_GROUP.equals(group) |
| ? LBL_PrivateTasks() |
| : Utils.capitalize(group); |
| setDisplayName(displayName); |
| } |
| |
| @Override |
| public Image getOpenedIcon(int type) { |
| return getIcon(true); |
| } |
| |
| @Override |
| public Image getIcon(int type) { |
| return getIcon(false); |
| } |
| |
| private Image getIcon(boolean opened) { |
| return NodeUtils.getTreeFolderIcon(opened); |
| } |
| |
| @Override |
| public Action[] getActions(boolean context) { |
| return new Action[0]; |
| } |
| |
| } |
| |
| private FavoriteTaskManager getFavoriteTaskManager() { |
| return currentP != null ? currentP.getLookup().lookup(FavoriteTaskManager.class) : null; |
| } |
| |
| private class TaskGroupChildren extends Children.Keys<GradleTask> { |
| |
| public TaskGroupChildren(String group, GradleBaseProject project) { |
| ArrayList<GradleTask> keys = new ArrayList<>(project.getTasks(group)); |
| Collections.sort(keys, Comparator.comparing(GradleTask::getName, String.CASE_INSENSITIVE_ORDER)); |
| setKeys(keys); |
| } |
| |
| @Override |
| protected Node[] createNodes(GradleTask key) { |
| return new Node[] {new TaskNode(currentP, key)}; |
| } |
| |
| } |
| |
| private class FavoritesChildren extends Children.Keys<GradleTask> { |
| private final ChangeListener listener; |
| |
| public FavoritesChildren() { |
| assert currentP != null; |
| FavoriteTaskManager fvm = getFavoriteTaskManager(); |
| listener = (e) -> { |
| Set<GradleTask> favs = fvm.getFavoriteTasks(); |
| setKeys(favs); |
| }; |
| fvm.addChangeListener(WeakListeners.change(listener, fvm)); |
| setKeys(fvm.getFavoriteTasks()); |
| } |
| |
| @Override |
| protected Node[] createNodes(GradleTask key) { |
| // NETBEANS-5340 It might happen that the currentP is null, but the listener |
| // still active on the previous project. |
| return currentP != null ? |
| new Node[] {new TaskNode(currentP, key)} : |
| new Node[0]; |
| } |
| |
| } |
| } |