// We store the maximum number (9) of recent tags to allow dynamic change of number of tags shown in the preferences.
// This implies to iterate in descending order, as the oldest elements will only be removed after we reach the maximum numbern and not the number of tags to show.
// However, as Set does not allow to iterate in descending order, we need to copy its elements into a List we can access in reverse order.
List<Tag> tags = new LinkedList<>(recentTags.keySet());
for (int i = tags.size()-1; i >= 0 && count <= tagsToShow; i--, count++) {
final Tag t = tags.get(i);
// Create action for reusing the tag, with keyboard shortcut Ctrl+(1-5)
String actionShortcutKey = "properties:recent:"+count;
String actionShortcutShiftKey = "properties:recent:shift:"+count;
Shortcut sc = Shortcut.registerShortcut(actionShortcutKey, tr("Choose recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL);
final JosmAction action = new JosmAction(actionShortcutKey, null, tr("Use this tag again"), sc, false) {
@Override
public void actionPerformed(ActionEvent e) {
keys.setSelectedItem(t.getKey());
// Update list of values (fix #7951)
// fix #8298 - update list of values before setting value (?)
focus.focusGained(null);
values.setSelectedItem(t.getValue());
selectValuesCombobox();
}
};
Shortcut scShift = Shortcut.registerShortcut(actionShortcutShiftKey, tr("Apply recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL_SHIFT);
final JosmAction actionShift = new JosmAction(actionShortcutShiftKey, null, tr("Use this tag again"), scShift, false) {
@Override
public void actionPerformed(ActionEvent e) {
action.actionPerformed(null);
performTagAdding();
selectKeysComboBox();
}
};
recentTagsActions.add(action);
recentTagsActions.add(actionShift);
disableTagIfNeeded(t, action);
// Find and display icon
ImageIcon icon = MapPaintStyles.getNodeIcon(t, false); // Filters deprecated icon
if (icon == null) {
// If no icon found in map style look at presets
Map<String, String> map = new HashMap<>();
map.put(t.getKey(), t.getValue());
for (TaggingPreset tp : TaggingPreset.getMatchingPresets(null, map, false)) {
icon = tp.getIcon();
if (icon != null) {
break;
}
}
// If still nothing display an empty icon
if (icon == null) {
icon = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB));
}
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.ipadx = 5;
mainPanel.add(new JLabel(action.isEnabled() ? icon : GuiHelper.getDisabledIcon(icon)), gbc);
// Create tag label
final String color = action.isEnabled() ? "" : "; color:gray";
final JLabel tagLabel = new JLabel("<html>"
+ "<style>td{border:1px solid gray; font-weight:normal"+color+"}</style>"
+ "<table><tr><td>" + XmlWriter.encode(t.toString(), true) + "</td></tr></table></html>");
if (action.isEnabled()) {
// Register action
mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), actionShortcutKey);
mainPanel.getActionMap().put(actionShortcutKey, action);
mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(scShift.getKeyStroke(), actionShortcutShiftKey);
mainPanel.getActionMap().put(actionShortcutShiftKey, actionShift);
// Make the tag label clickable and set tooltip to the action description (this displays also the keyboard shortcut)
tagLabel.setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
tagLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
tagLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
action.actionPerformed(null);
// add tags and close window on double-click
if (e.getClickCount()>1) {
buttonAction(0, null); // emulate OK click and close the dialog
}
// add tags on Shift-Click
if (e.isShiftDown()) {
performTagAdding();
selectKeysComboBox();
}
}
});
} else {
// Disable tag label
tagLabel.setEnabled(false);
// Explain in the tooltip why
tagLabel.setToolTipText(tr("The key ''{0}'' is already used", t.getKey()));
}
// Finally add label to the resulting panel
JPanel tagPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
tagPanel.add(tagLabel);
mainPanel.add(tagPanel, GBC.eol().fill(GBC.HORIZONTAL));