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

org.netbeans.modules.project.ui.RecentProjectsWidget Maven / Gradle / Ivy

The newest version!
/*
 * 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.project.ui;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.netbeans.api.progress.BaseProgressUtils;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.project.ui.api.RecentProjects;
import org.netbeans.modules.project.ui.api.UnloadedProjectInformation;
import org.netbeans.spi.dashboard.DashboardDisplayer;
import org.netbeans.spi.dashboard.DashboardWidget;
import org.netbeans.spi.dashboard.WidgetElement;
import org.openide.*;
import org.openide.awt.Actions;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.URLMapper;
import org.openide.util.*;
import org.openide.util.NbBundle.Messages;

/**
 * List of recent projects.
 */
@Messages({
    "TITLE_RecentProjects=Recent Projects",
    "LBL_NoRecentProjects=",
    "# {0} - Project name",
    "ERR_InvalidProject={0} is not a valid NetBeans project.",
    "LBL_OpenRecentProject=Open Recent Project"
})
public class RecentProjectsWidget implements DashboardWidget {

    private static final int MAX_PROJECTS = 5;

    private static final RequestProcessor RP = new RequestProcessor("RecentProjects");

    private final List elements;
    private final List projects;
    private final Set active;
    private final PropertyChangeListener projectsListener;

    private final Action newProject;
    private final Action openProject;
    private final Action projectGroups;

    public RecentProjectsWidget() {
        elements = new ArrayList<>();
        projects = new ArrayList<>();
        active = new HashSet<>();
        projectsListener = e -> {
            if (RecentProjects.PROP_RECENT_PROJECT_INFO.equals(e.getPropertyName())) {
                loadProjects();
            }
        };
        Action newProjectOriginal = Actions.forID("Project", "org.netbeans.modules.project.ui.NewProject");
        if (newProjectOriginal != null) {
            newProject = new ProjectDelegateAction(newProjectOriginal);
        } else {
            newProject = null;
        }
        Action openProjectOriginal = Actions.forID("Project", "org.netbeans.modules.project.ui.OpenProject");
        if (openProjectOriginal != null) {
            openProject = new ProjectDelegateAction(openProjectOriginal);
        } else {
            openProject = null;
        }
        Action projectGroupsOriginal = Actions.forID("Project", "org.netbeans.modules.project.ui.groups.GroupsMenu");
        if (projectGroupsOriginal != null) {
            projectGroups = new ProjectDelegateAction(projectGroupsOriginal);
        } else {
            projectGroups = null;
        }
        buildElements();
        loadProjects();
    }

    @Override
    public String title(DashboardDisplayer.Panel panel) {
        return Bundle.TITLE_RecentProjects();
    }

    @Override
    public List elements(DashboardDisplayer.Panel panel) {
        return List.copyOf(elements);
    }

    @Override
    public void showing(DashboardDisplayer.Panel panel) {
        if (active.isEmpty()) {
            RecentProjects.getDefault().addPropertyChangeListener(projectsListener);
        }
        active.add(panel);
        panel.refresh();
        loadProjects();
    }

    @Override
    public void hidden(DashboardDisplayer.Panel panel) {
        active.remove(panel);
        if (active.isEmpty()) {
            RecentProjects.getDefault().removePropertyChangeListener(projectsListener);
        }
    }

    // derived from RecentProjectsPanel in Welcome module
    private void loadProjects() {
        RP.execute(() -> {
            List existingProjects = new ArrayList<>(MAX_PROJECTS);
            for (UnloadedProjectInformation p : RecentProjects.getDefault().getRecentProjectInformation()) {
                try {
                    File projectDir = Utilities.toFile(p.getURL().toURI());
                    if (!projectDir.exists() || !projectDir.isDirectory()) {
                        continue;
                    }
                    existingProjects.add(p);
                    if (existingProjects.size() >= MAX_PROJECTS) {
                        break;
                    }
                } catch (Exception ex) {
                    Logger.getLogger(RecentProjectsWidget.class.getName()).log(Level.FINE, null, ex);
                }
            }
            EventQueue.invokeLater(() -> {
                updateProjectsList(existingProjects);
            });

        });

    }

    private void buildElements() {
        elements.clear();
        if (projects.isEmpty()) {
            elements.add(WidgetElement.unavailable(Bundle.LBL_NoRecentProjects()));
        } else {
            for (UnloadedProjectInformation project : projects) {
                elements.add(WidgetElement.actionLink(new OpenProjectAction(project)));
            }
        }
        if (newProject != null || openProject != null || projectGroups != null) {
            elements.add(WidgetElement.separator());
        }
        if (newProject != null) {
            elements.add(WidgetElement.actionLink(newProject));
        }
        if (openProject != null) {
            elements.add(WidgetElement.actionLink(openProject));
        }
        if (projectGroups != null) {
            elements.add(WidgetElement.actionLink(projectGroups));
        }
    }

    private void updateProjectsList(List projects) {
        if (!this.projects.equals(projects)) {
            this.projects.clear();
            this.projects.addAll(projects);
            buildElements();
            active.forEach(DashboardDisplayer.Panel::refresh);
        }
    }

    private static class ProjectDelegateAction extends AbstractAction {

        private final Action delegate;

        private ProjectDelegateAction(Action delegate) {
            super(Actions.cutAmpersand(String.valueOf(delegate.getValue(NAME)).replace("...", "")));
            this.delegate = delegate;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            delegate.actionPerformed(e);
        }

    }

    // derived from RecentProjectsPanel in Welcome panel
    private static class OpenProjectAction extends AbstractAction {

        private final UnloadedProjectInformation project;

        private OpenProjectAction(UnloadedProjectInformation project) {
            super(project.getDisplayName(), project.getIcon());
            this.project = project;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Runnable task = () -> {
                URL url = project.getURL();
                Project prj = null;

                FileObject dir = URLMapper.findFileObject(url);
                if (dir != null && dir.isFolder()) {
                    try {
                        prj = ProjectManager.getDefault().findProject(dir);
                    } catch (IOException ioEx) {
                        // Ignore invalid folders
                    }
                }

                if (prj != null) {
                    OpenProjects.getDefault().open(new Project[]{prj}, false, true);
                } else {
                    NotifyDescriptor nd = new NotifyDescriptor.Message(
                            Bundle.ERR_InvalidProject(project.getDisplayName()));
                    DialogDisplayer.getDefault().notify(nd);
                }
            };
            BaseProgressUtils.runOffEventDispatchThread(task, Bundle.LBL_OpenRecentProject(),
                    new AtomicBoolean(false), false);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy