Dynamically Changing the Display Names of Menus and Popups
- by Geertjan
Very interesting thing and handy to know when needed is the fact that "menuText" and "popupText" (from org.openide.awt.ActionRegistration) can be changed dynamically, via "putValue" as shown below for "popupText". The Action class, in this case, needs to be eager, hence you won't receive the object of interest via the constructor, but you can easily use the global Lookup for that purpose instead, as also shown below.
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.swing.AbstractAction;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectUtils;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.Utilities;
@ActionID(
category = "Project",
id = "org.ptt.DemoProjectAction")
@ActionRegistration(
lazy = false,
displayName = "NOT-USED")
@ActionReference(path = "Projects/Actions", position = 0)
public final class DemoProjectAction extends AbstractAction{
private final ProjectInformation context;
public DemoProjectAction() {
putValue("popupText", "Select Me To See Current Time!");
context = ProjectUtils.getInformation(
Utilities.actionsGlobalContext().lookup(Project.class));
}
@Override
public void actionPerformed(ActionEvent e) {
refresh();
}
protected void refresh() {
DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
String formatted = formatter.format(System.currentTimeMillis());
putValue("popupText", "Time: " + formatted + " (" + context.getDisplayName() +")");
}
}
Now, let's do something semi useful and display, in the popup, which is available when you right-click a project, 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 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.filesystems.FileAttributeEvent;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileRenameEvent;
import org.openide.util.Utilities;
@ActionID(
category = "Project",
id = "org.ptt.TrackProjectTimerAction")
@ActionRegistration(
lazy = false,
displayName = "NOT-USED")
@ActionReference(
path = "Projects/Actions",
position = 0)
public final class TrackProjectTimerAction extends AbstractAction implements FileChangeListener {
private final Project context;
private Long startTime;
private Long changedTime;
private DateFormat formatter;
public TrackProjectTimerAction() {
putValue("popupText", "Enable project time tracker");
this.formatter = new SimpleDateFormat("HH:mm:ss");
context = Utilities.actionsGlobalContext().lookup(Project.class);
context.getProjectDirectory().addRecursiveListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
startTimer();
}
protected void startTimer() {
startTime = System.currentTimeMillis();
String formattedStartTime = formatter.format(startTime);
putValue("popupText", "Timer started: " + formattedStartTime + " (" +
ProjectUtils.getInformation(context).getDisplayName() + ")");
}
@Override
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;
}
@Override
public void fileFolderCreated(FileEvent fe) {}
@Override
public void fileDataCreated(FileEvent fe) {}
@Override
public void fileDeleted(FileEvent fe) {}
@Override
public void fileRenamed(FileRenameEvent fre) {}
@Override
public void fileAttributeChanged(FileAttributeEvent fae) {}
}