Tuesday Dec 18, 2012

Project Time Tracker

Based on yesterday's blog entry, let's do something semi useful and display, in the project popup, which is available when you right-click a project in the Projects window, the time since the last change was made anywhere in the project, i.e., we can listen recursively to any changes done within a project and then update the popup with the newly acquired information, dynamically:

import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.AbstractAction;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileAttributeEvent;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileRenameEvent;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;

        category = "Demo",
        id = "org.ptt.TrackProjectSelectionAction")
        lazy = false,
        displayName = "NOT-USED")
        path = "Projects/Actions",
        position = 0)
public final class TrackProjectSelectionAction extends AbstractAction
        implements LookupListener, FileChangeListener {

    private Lookup.Result<Project> projects;
    private Project context;
    private Long startTime;
    private Long changedTime;
    private DateFormat formatter;
    private List<Project> timedProjects;

    public TrackProjectSelectionAction() {
        putValue("popupText", "Timer");
        formatter = new SimpleDateFormat("HH:mm:ss");
        timedProjects = new ArrayList<Project>();
        projects = Utilities.actionsGlobalContext().lookupResult(Project.class);
                WeakListeners.create(LookupListener.class, this, projects));
        resultChanged(new LookupEvent(projects));

    public void resultChanged(LookupEvent le) {
        Collection<? extends Project> allProjects = projects.allInstances();
        if (allProjects.size() == 1) {
            Project currentProject = allProjects.iterator().next();
            if (!timedProjects.contains(currentProject)) {
                String currentProjectName =
                putValue("popupText", "Start Timer for Project: " + currentProjectName);
                        "Current Project: " + currentProjectName);
                context = currentProject;

    public void actionPerformed(ActionEvent e) {

    protected void refresh() {
        startTime = System.currentTimeMillis();
        String formattedStartTime = formatter.format(startTime);
        putValue("popupText", "Timer started: " + formattedStartTime + " ("
                + ProjectUtils.getInformation(context).getDisplayName() + ")");

    public void fileChanged(FileEvent fe) {
        changedTime = System.currentTimeMillis();
        formatter = new SimpleDateFormat("mm:ss");
        String formattedLapse = formatter.format(changedTime - startTime);
        putValue("popupText", "Time since last change: " + formattedLapse + " ("
                + ProjectUtils.getInformation(context).getDisplayName() + ")");
        startTime = changedTime;

    public void fileFolderCreated(FileEvent fe) {}
    public void fileDataCreated(FileEvent fe) {}
    public void fileDeleted(FileEvent fe) {}
    public void fileRenamed(FileRenameEvent fre) {}
    public void fileAttributeChanged(FileAttributeEvent fae) {}

Some more work needs to be done to complete the above, i.e., for each project you somehow need to maintain the start time and last change and redisplay that whenever the user right-clicks the project.


Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.


« December 2012 »