source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java@ 4139

Last change on this file since 4139 was 4139, checked in by stoecker, 13 years ago

fix #6474 - fix toolbar action entries for some actions and fix fullscreen mode start

  • Property svn:eol-style set to native
File size: 36.3 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.preferences;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.Container;
8import java.awt.Dimension;
9import java.awt.GridBagLayout;
10import java.awt.GridLayout;
11import java.awt.LayoutManager;
12import java.awt.Rectangle;
13import java.awt.datatransfer.DataFlavor;
14import java.awt.datatransfer.Transferable;
15import java.awt.datatransfer.UnsupportedFlavorException;
16import java.awt.event.ActionEvent;
17import java.awt.event.ActionListener;
18import java.awt.event.InputEvent;
19import java.io.IOException;
20import java.util.ArrayList;
21import java.util.Arrays;
22import java.util.Collection;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.Map;
28
29import javax.swing.AbstractAction;
30import javax.swing.Action;
31import javax.swing.DefaultListCellRenderer;
32import javax.swing.DefaultListModel;
33import javax.swing.Icon;
34import javax.swing.ImageIcon;
35import javax.swing.JButton;
36import javax.swing.JComponent;
37import javax.swing.JLabel;
38import javax.swing.JList;
39import javax.swing.JMenuItem;
40import javax.swing.JPanel;
41import javax.swing.JPopupMenu;
42import javax.swing.JScrollPane;
43import javax.swing.JTable;
44import javax.swing.JToolBar;
45import javax.swing.JTree;
46import javax.swing.ListCellRenderer;
47import javax.swing.MenuElement;
48import javax.swing.TransferHandler;
49import javax.swing.event.ListSelectionEvent;
50import javax.swing.event.ListSelectionListener;
51import javax.swing.event.TreeSelectionEvent;
52import javax.swing.event.TreeSelectionListener;
53import javax.swing.table.AbstractTableModel;
54import javax.swing.tree.DefaultMutableTreeNode;
55import javax.swing.tree.DefaultTreeCellRenderer;
56import javax.swing.tree.DefaultTreeModel;
57import javax.swing.tree.TreePath;
58
59import org.openstreetmap.josm.Main;
60import org.openstreetmap.josm.actions.ActionParameter;
61import org.openstreetmap.josm.actions.AdaptableAction;
62import org.openstreetmap.josm.actions.ParameterizedAction;
63import org.openstreetmap.josm.actions.ParameterizedActionDecorator;
64import org.openstreetmap.josm.gui.tagging.TaggingPreset;
65import org.openstreetmap.josm.tools.GBC;
66import org.openstreetmap.josm.tools.ImageProvider;
67
68public class ToolbarPreferences implements PreferenceSettingFactory {
69
70
71 private static final String EMPTY_TOOLBAR_MARKER = "<!-empty-!>";
72
73 public static class ActionDefinition {
74 private final Action action;
75 private String name = "";
76 private String icon = "";
77 private ImageIcon ico = null;
78 private final Map<String, Object> parameters = new HashMap<String, Object>();
79
80 public ActionDefinition(Action action) {
81 this.action = action;
82 }
83
84 public Map<String, Object> getParameters() {
85 return parameters;
86 }
87
88 public Action getParametrizedAction() {
89 if (getAction() instanceof ParameterizedAction)
90 return new ParameterizedActionDecorator((ParameterizedAction) getAction(), parameters);
91 else
92 return getAction();
93 }
94
95 public Action getAction() {
96 return action;
97 }
98
99 public String getName() {
100 return name;
101 }
102
103 public String getDisplayName() {
104 return name.isEmpty() ? (String) action.getValue(Action.NAME) : name;
105 }
106
107 public String getDisplayTooltip() {
108 if(!name.isEmpty())
109 return name;
110
111 Object tt = action.getValue(TaggingPreset.OPTIONAL_TOOLTIP_TEXT);
112 if (tt != null)
113 return (String) tt;
114
115 return (String) action.getValue(Action.SHORT_DESCRIPTION);
116 }
117
118 public Icon getDisplayIcon() {
119 return ico != null ? ico : (Icon) action.getValue(Action.SMALL_ICON);
120 }
121
122 public void setName(String name) {
123 this.name = name;
124 }
125
126 public String getIcon() {
127 return icon;
128 }
129
130 public void setIcon(String icon) {
131 this.icon = icon;
132 ico = ImageProvider.getIfAvailable("", icon);
133 }
134
135 public boolean isSeparator() {
136 return action == null;
137 }
138
139 public static ActionDefinition getSeparator() {
140 return new ActionDefinition(null);
141 }
142 }
143
144 public static class ActionParser {
145 private final Map<String, Action> actions;
146 private final StringBuilder result = new StringBuilder();
147 private int index;
148 private char[] s;
149
150 public ActionParser(Map<String, Action> actions) {
151 this.actions = actions;
152 }
153
154 private String readTillChar(char ch1, char ch2) {
155 result.setLength(0);
156 while (index < s.length && s[index] != ch1 && s[index] != ch2) {
157 if (s[index] == '\\') {
158 index++;
159 if (index >= s.length) {
160 break;
161 }
162 }
163 result.append(s[index]);
164 index++;
165 }
166 return result.toString();
167 }
168
169 private void skip(char ch) {
170 if (index < s.length && s[index] == ch) {
171 index++;
172 }
173 }
174
175 public ActionDefinition loadAction(String actionName) {
176 index = 0;
177 this.s = actionName.toCharArray();
178
179 String name = readTillChar('(', '{');
180 Action action = actions.get(name);
181
182 if (action == null)
183 return null;
184
185 ActionDefinition result = new ActionDefinition(action);
186
187 if (action instanceof ParameterizedAction) {
188 skip('(');
189
190 ParameterizedAction parametrizedAction = (ParameterizedAction)action;
191 Map<String, ActionParameter<?>> actionParams = new HashMap<String, ActionParameter<?>>();
192 for (ActionParameter<?> param: parametrizedAction.getActionParameters()) {
193 actionParams.put(param.getName(), param);
194 }
195
196 while (index < s.length && s[index] != ')') {
197 String paramName = readTillChar('=', '=');
198 skip('=');
199 String paramValue = readTillChar(',',')');
200 if (paramName.length() > 0) {
201 ActionParameter<?> actionParam = actionParams.get(paramName);
202 if (actionParam != null) {
203 result.getParameters().put(paramName, actionParam.readFromString(paramValue));
204 }
205 }
206 skip(',');
207 }
208 skip(')');
209 }
210 if (action instanceof AdaptableAction) {
211 skip('{');
212
213 while (index < s.length && s[index] != '}') {
214 String paramName = readTillChar('=', '=');
215 skip('=');
216 String paramValue = readTillChar(',','}');
217 if ("icon".equals(paramName) && paramValue.length() > 0)
218 result.setIcon(paramValue);
219 else if("name".equals(paramName) && paramValue.length() > 0)
220 result.setName(paramValue);
221 skip(',');
222 }
223 skip('}');
224 }
225
226 return result;
227 }
228
229 private void escape(String s) {
230 for (int i=0; i<s.length(); i++) {
231 char ch = s.charAt(i);
232 if (ch == '\\' || ch == '(' || ch == '{' || ch == ',' || ch == ')' || ch == '}' || ch == '=') {
233 result.append('\\');
234 result.append(ch);
235 } else {
236 result.append(ch);
237 }
238 }
239 }
240
241 @SuppressWarnings("unchecked")
242 public String saveAction(ActionDefinition action) {
243 result.setLength(0);
244
245 String val = (String) action.getAction().getValue("toolbar");
246 if(val == null)
247 return null;
248 escape(val);
249 if (action.getAction() instanceof ParameterizedAction) {
250 result.append('(');
251 List<ActionParameter<?>> params = ((ParameterizedAction)action.getAction()).getActionParameters();
252 for (int i=0; i<params.size(); i++) {
253 ActionParameter<Object> param = (ActionParameter<Object>)params.get(i);
254 escape(param.getName());
255 result.append('=');
256 Object value = action.getParameters().get(param.getName());
257 if (value != null) {
258 escape(param.writeToString(value));
259 }
260 if (i < params.size() - 1) {
261 result.append(',');
262 } else {
263 result.append(')');
264 }
265 }
266 }
267 if (action.getAction() instanceof AdaptableAction) {
268 boolean first = true;
269 String tmp = action.getName();
270 if(tmp.length() != 0) {
271 result.append(first ? "{" : ",");
272 result.append("name=");
273 escape(tmp);
274 first = false;
275 }
276 tmp = action.getIcon();
277 if(tmp.length() != 0) {
278 result.append(first ? "{" : ",");
279 result.append("icon=");
280 escape(tmp);
281 first = false;
282 }
283 if(!first)
284 result.append('}');
285 }
286
287 return result.toString();
288 }
289 }
290
291 private static class ActionParametersTableModel extends AbstractTableModel {
292
293 private ActionDefinition currentAction = ActionDefinition.getSeparator();
294
295 public int getColumnCount() {
296 return 2;
297 }
298
299 public int getRowCount() {
300 int adaptable = ((currentAction.getAction() instanceof AdaptableAction) ? 2 : 0);
301 if (currentAction.isSeparator() || !(currentAction.getAction() instanceof ParameterizedAction))
302 return adaptable;
303 ParameterizedAction pa = (ParameterizedAction)currentAction.getAction();
304 return pa.getActionParameters().size() + adaptable;
305 }
306
307 @SuppressWarnings("unchecked")
308 private ActionParameter<Object> getParam(int index) {
309 ParameterizedAction pa = (ParameterizedAction)currentAction.getAction();
310 return (ActionParameter<Object>) pa.getActionParameters().get(index);
311 }
312
313 public Object getValueAt(int rowIndex, int columnIndex) {
314 if(currentAction.getAction() instanceof AdaptableAction)
315 {
316 if (rowIndex < 2) {
317 switch (columnIndex) {
318 case 0:
319 return rowIndex == 0 ? tr("Tooltip") : tr("Icon");
320 case 1:
321 return rowIndex == 0 ? currentAction.getName() : currentAction.getIcon();
322 default:
323 return null;
324 }
325 } else
326 rowIndex -= 2;
327 }
328 ActionParameter<Object> param = getParam(rowIndex);
329 switch (columnIndex) {
330 case 0:
331 return param.getName();
332 case 1:
333 return param.writeToString(currentAction.getParameters().get(param.getName()));
334 default:
335 return null;
336 }
337 }
338
339 @Override
340 public boolean isCellEditable(int row, int column) {
341 return column == 1;
342 }
343
344 @Override
345 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
346 if(currentAction.getAction() instanceof AdaptableAction)
347 {
348 if (rowIndex == 0) {
349 currentAction.setName((String)aValue);
350 return;
351 } else if (rowIndex == 1) {
352 currentAction.setIcon((String)aValue);
353 return;
354 } else
355 rowIndex -= 2;
356 }
357 ActionParameter<Object> param = getParam(rowIndex);
358 currentAction.getParameters().put(param.getName(), param.readFromString((String)aValue));
359 }
360
361
362 public void setCurrentAction(ActionDefinition currentAction) {
363 this.currentAction = currentAction;
364 fireTableDataChanged();
365 }
366
367 }
368
369 /**
370 * Key: Registered name (property "toolbar" of action).
371 * Value: The action to execute.
372 */
373 private Map<String, Action> actions = new HashMap<String, Action>();
374 private Map<String, Action> regactions = new HashMap<String, Action>();
375
376 private DefaultMutableTreeNode rootActionsNode = new DefaultMutableTreeNode(tr("Actions"));
377
378 public JToolBar control = new JToolBar();
379
380 public PreferenceSetting createPreferenceSetting() {
381 return new Settings(rootActionsNode);
382 }
383
384 public class Settings implements PreferenceSetting {
385
386 private final class Move implements ActionListener {
387 public void actionPerformed(ActionEvent e) {
388 if (e.getActionCommand().equals("<") && actionsTree.getSelectionCount() > 0) {
389
390 int leadItem = selected.getSize();
391 if (selectedList.getSelectedIndex() != -1) {
392 int[] indices = selectedList.getSelectedIndices();
393 leadItem = indices[indices.length - 1];
394 }
395 for (TreePath selectedAction : actionsTree.getSelectionPaths()) {
396 DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectedAction.getLastPathComponent();
397 if (node.getUserObject() == null) {
398 selected.add(leadItem++, ActionDefinition.getSeparator());
399 } else if (node.getUserObject() instanceof Action) {
400 selected.add(leadItem++, new ActionDefinition((Action)node.getUserObject()));
401
402 }
403 }
404 } else if (e.getActionCommand().equals(">") && selectedList.getSelectedIndex() != -1) {
405 while (selectedList.getSelectedIndex() != -1) {
406 selected.remove(selectedList.getSelectedIndex());
407 }
408 } else if (e.getActionCommand().equals("up")) {
409 int i = selectedList.getSelectedIndex();
410 Object o = selected.get(i);
411 if (i != 0) {
412 selected.remove(i);
413 selected.add(i-1, o);
414 selectedList.setSelectedIndex(i-1);
415 }
416 } else if (e.getActionCommand().equals("down")) {
417 int i = selectedList.getSelectedIndex();
418 Object o = selected.get(i);
419 if (i != selected.size()-1) {
420 selected.remove(i);
421 selected.add(i+1, o);
422 selectedList.setSelectedIndex(i+1);
423 }
424 }
425 }
426 }
427
428 private class ActionTransferable implements Transferable {
429
430 private DataFlavor[] flavors = new DataFlavor[] { ACTION_FLAVOR };
431
432 private final List<ActionDefinition> actions;
433
434 public ActionTransferable(List<ActionDefinition> actions) {
435 this.actions = actions;
436 }
437
438 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
439 return actions;
440 }
441
442 public DataFlavor[] getTransferDataFlavors() {
443 return flavors;
444 }
445
446 public boolean isDataFlavorSupported(DataFlavor flavor) {
447 return flavors[0] == flavor;
448 }
449 }
450
451 private final Move moveAction = new Move();
452
453 private final DefaultListModel selected = new DefaultListModel();
454 private final JList selectedList = new JList(selected);
455
456 private final DefaultTreeModel actionsTreeModel;
457 private final JTree actionsTree;
458
459 private final ActionParametersTableModel actionParametersModel = new ActionParametersTableModel();
460 private final JTable actionParametersTable = new JTable(actionParametersModel);
461 private JPanel actionParametersPanel;
462
463 private JButton upButton;
464 private JButton downButton;
465 private JButton removeButton;
466 private JButton addButton;
467
468 private String movingComponent;
469
470 public Settings(DefaultMutableTreeNode rootActionsNode) {
471 actionsTreeModel = new DefaultTreeModel(rootActionsNode);
472 actionsTree = new JTree(actionsTreeModel);
473 }
474
475 private JButton createButton(String name) {
476 JButton b = new JButton();
477 if (name.equals("up")) {
478 b.setIcon(ImageProvider.get("dialogs", "up"));
479 } else if (name.equals("down")) {
480 b.setIcon(ImageProvider.get("dialogs", "down"));
481 } else {
482 b.setText(name);
483 }
484 b.addActionListener(moveAction);
485 b.setActionCommand(name);
486 return b;
487 }
488
489 private void updateEnabledState() {
490 int index = selectedList.getSelectedIndex();
491 upButton.setEnabled(index > 0);
492 downButton.setEnabled(index < selectedList.getModel().getSize() - 1);
493 removeButton.setEnabled(index != -1);
494 addButton.setEnabled(actionsTree.getSelectionCount() > 0);
495 }
496
497 public void addGui(PreferenceTabbedPane gui) {
498 actionsTree.setCellRenderer(new DefaultTreeCellRenderer() {
499 @Override
500 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
501 boolean leaf, int row, boolean hasFocus) {
502 DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
503 JLabel comp = (JLabel) super.getTreeCellRendererComponent(
504 tree, value, sel, expanded, leaf, row, hasFocus);
505 if (node.getUserObject() == null) {
506 comp.setText(tr("Separator"));
507 comp.setIcon(ImageProvider.get("preferences/separator"));
508 }
509 else if (node.getUserObject() instanceof Action) {
510 Action action = (Action) node.getUserObject();
511 comp.setText((String) action.getValue(Action.NAME));
512 comp.setIcon((Icon) action.getValue(Action.SMALL_ICON));
513 }
514 return comp;
515 }
516 });
517
518 ListCellRenderer renderer = new DefaultListCellRenderer(){
519 @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
520 String s;
521 Icon i;
522 ActionDefinition action = (ActionDefinition)value;
523 if (!action.isSeparator()) {
524 s = action.getDisplayName();
525 i = action.getDisplayIcon();
526 } else {
527 i = ImageProvider.get("preferences/separator");
528 s = tr("Separator");
529 }
530 JLabel l = (JLabel)super.getListCellRendererComponent(list, s, index, isSelected, cellHasFocus);
531 l.setIcon(i);
532 return l;
533 }
534 };
535 selectedList.setCellRenderer(renderer);
536 selectedList.addListSelectionListener(new ListSelectionListener(){
537 public void valueChanged(ListSelectionEvent e) {
538 boolean sel = selectedList.getSelectedIndex() != -1;
539 if (sel) {
540 actionsTree.clearSelection();
541 ActionDefinition action = (ActionDefinition) selected.get(selectedList.getSelectedIndex());
542 actionParametersModel.setCurrentAction(action);
543 actionParametersPanel.setVisible(actionParametersModel.getRowCount() > 0);
544 }
545 updateEnabledState();
546 }
547 });
548
549 selectedList.setDragEnabled(true);
550 selectedList.setTransferHandler(new TransferHandler() {
551 @Override
552 protected Transferable createTransferable(JComponent c) {
553 List<ActionDefinition> actions = new ArrayList<ActionDefinition>();
554 for (Object o: ((JList)c).getSelectedValues()) {
555 actions.add((ActionDefinition)o);
556 }
557 return new ActionTransferable(actions);
558 }
559
560 @Override
561 public int getSourceActions(JComponent c) {
562 return TransferHandler.MOVE;
563 }
564
565 @Override
566 public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
567 for (DataFlavor f : transferFlavors) {
568 if (ACTION_FLAVOR.equals(f))
569 return true;
570 }
571 return false;
572 }
573
574 @Override
575 public void exportAsDrag(JComponent comp, InputEvent e, int action) {
576 super.exportAsDrag(comp, e, action);
577 movingComponent = "list";
578 }
579
580 @Override
581 public boolean importData(JComponent comp, Transferable t) {
582 try {
583 int dropIndex = selectedList.locationToIndex(selectedList.getMousePosition(true));
584 List<?> draggedData = (List<?>) t.getTransferData(ACTION_FLAVOR);
585
586 Object leadItem = dropIndex >= 0 ? selected.elementAt(dropIndex) : null;
587 int dataLength = draggedData.size();
588
589
590 if (leadItem != null) {
591 for (Object o: draggedData) {
592 if (leadItem.equals(o))
593 return false;
594
595 }
596 }
597
598 int dragLeadIndex = -1;
599 boolean localDrop = "list".equals(movingComponent);
600
601 if (localDrop) {
602 dragLeadIndex = selected.indexOf(draggedData.get(0));
603 for (Object o: draggedData) {
604 selected.removeElement(o);
605 }
606 }
607 int[] indices = new int[dataLength];
608
609 if (localDrop) {
610 int adjustedLeadIndex = selected.indexOf(leadItem);
611 int insertionAdjustment = dragLeadIndex <= adjustedLeadIndex ? 1 : 0;
612 for (int i = 0; i < dataLength; i++) {
613 selected.insertElementAt(draggedData.get(i), adjustedLeadIndex + insertionAdjustment + i);
614 indices[i] = adjustedLeadIndex + insertionAdjustment + i;
615 }
616 } else {
617 for (int i = 0; i < dataLength; i++) {
618 selected.add(dropIndex, draggedData.get(i));
619 indices[i] = dropIndex + i;
620 }
621 }
622 selectedList.clearSelection();
623 selectedList.setSelectedIndices(indices);
624 movingComponent = "";
625 return true;
626 } catch (Exception e) {
627 e.printStackTrace();
628 }
629 return false;
630 }
631
632 @Override
633 protected void exportDone(JComponent source, Transferable data, int action) {
634 if (movingComponent.equals("list")) {
635 try {
636 List<?> draggedData = (List<?>) data.getTransferData(ACTION_FLAVOR);
637 boolean localDrop = selected.contains(draggedData.get(0));
638 if (localDrop) {
639 int[] indices = selectedList.getSelectedIndices();
640 Arrays.sort(indices);
641 for (int i = indices.length - 1; i >= 0; i--) {
642 selected.remove(indices[i]);
643 }
644 }
645 } catch (Exception e) {
646 e.printStackTrace();
647 }
648 movingComponent = "";
649 }
650 }
651 });
652
653 actionsTree.setTransferHandler(new TransferHandler() {
654 private static final long serialVersionUID = 1L;
655
656 @Override
657 public int getSourceActions( JComponent c ){
658 return TransferHandler.MOVE;
659 }
660
661 @Override
662 protected void exportDone(JComponent source, Transferable data, int action) {
663 }
664
665 @Override
666 protected Transferable createTransferable(JComponent c) {
667 TreePath[] paths = actionsTree.getSelectionPaths();
668 List<ActionDefinition> dragActions = new ArrayList<ActionDefinition>();
669 for (TreePath path : paths) {
670 DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
671 Object obj = node.getUserObject();
672 if (obj == null) {
673 dragActions.add(ActionDefinition.getSeparator());
674 }
675 else if (obj instanceof Action) {
676 dragActions.add(new ActionDefinition((Action) obj));
677 }
678 }
679 return new ActionTransferable(dragActions);
680 }
681 });
682 actionsTree.setDragEnabled(true);
683 actionsTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
684 public void valueChanged(TreeSelectionEvent e) {
685 updateEnabledState();
686 }
687 });
688
689 final JPanel left = new JPanel(new GridBagLayout());
690 left.add(new JLabel(tr("Toolbar")), GBC.eol());
691 left.add(new JScrollPane(selectedList), GBC.std().fill(GBC.BOTH));
692
693 final JPanel right = new JPanel(new GridBagLayout());
694 right.add(new JLabel(tr("Available")), GBC.eol());
695 right.add(new JScrollPane(actionsTree), GBC.eol().fill(GBC.BOTH));
696
697 final JPanel buttons = new JPanel(new GridLayout(6,1));
698 buttons.add(upButton = createButton("up"));
699 buttons.add(addButton = createButton("<"));
700 buttons.add(removeButton = createButton(">"));
701 buttons.add(downButton = createButton("down"));
702 updateEnabledState();
703
704 final JPanel p = new JPanel();
705 p.setLayout(new LayoutManager(){
706 public void addLayoutComponent(String name, Component comp) {}
707 public void removeLayoutComponent(Component comp) {}
708 public Dimension minimumLayoutSize(Container parent) {
709 Dimension l = left.getMinimumSize();
710 Dimension r = right.getMinimumSize();
711 Dimension b = buttons.getMinimumSize();
712 return new Dimension(l.width+b.width+10+r.width,l.height+b.height+10+r.height);
713 }
714 public Dimension preferredLayoutSize(Container parent) {
715 Dimension l = new Dimension(200, 200); //left.getPreferredSize();
716 Dimension r = new Dimension(200, 200); //right.getPreferredSize();
717 return new Dimension(l.width+r.width+10+buttons.getPreferredSize().width,Math.max(l.height, r.height));
718 }
719 public void layoutContainer(Container parent) {
720 Dimension d = p.getSize();
721 Dimension b = buttons.getPreferredSize();
722 int width = (d.width-10-b.width)/2;
723 left.setBounds(new Rectangle(0,0,width,d.height));
724 right.setBounds(new Rectangle(width+10+b.width,0,width,d.height));
725 buttons.setBounds(new Rectangle(width+5, d.height/2-b.height/2, b.width, b.height));
726 }
727 });
728 p.add(left);
729 p.add(buttons);
730 p.add(right);
731
732 actionParametersPanel = new JPanel(new GridBagLayout());
733 actionParametersPanel.add(new JLabel(tr("Action parameters")), GBC.eol().insets(0, 10, 0, 20));
734 actionParametersTable.getColumnModel().getColumn(0).setHeaderValue(tr("Parameter name"));
735 actionParametersTable.getColumnModel().getColumn(1).setHeaderValue(tr("Parameter value"));
736 actionParametersPanel.add(actionParametersTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
737 actionParametersPanel.add(actionParametersTable, GBC.eol().fill(GBC.BOTH).insets(0, 0, 0, 10));
738 actionParametersPanel.setVisible(false);
739
740 JPanel panel = gui.createPreferenceTab("toolbar", tr("Toolbar customization"),
741 tr("Customize the elements on the toolbar."), false);
742 panel.add(p, GBC.eol().fill(GBC.BOTH));
743 panel.add(actionParametersPanel, GBC.eol().fill(GBC.HORIZONTAL));
744 selected.removeAllElements();
745 for (ActionDefinition actionDefinition: getDefinedActions()) {
746 selected.addElement(actionDefinition);
747 }
748 }
749
750 public boolean ok() {
751 Collection<String> t = new LinkedList<String>();
752 ActionParser parser = new ActionParser(null);
753 for (int i = 0; i < selected.size(); ++i) {
754 ActionDefinition action = (ActionDefinition)selected.get(i);
755 if (action.isSeparator()) {
756 t.add("|");
757 } else {
758 String res = parser.saveAction(action);
759 if(res != null)
760 t.add(res);
761 }
762 }
763 if (t.isEmpty()) {
764 t = Collections.singletonList(EMPTY_TOOLBAR_MARKER);
765 }
766 Main.pref.putCollection("toolbar", t);
767 Main.toolbar.refreshToolbarControl();
768 return false;
769 }
770
771 }
772
773 public ToolbarPreferences() {
774 control.setFloatable(false);
775 }
776
777 private void loadAction(DefaultMutableTreeNode node, MenuElement menu) {
778 Object userObject = null;
779 MenuElement menuElement = menu;
780 if (menu.getSubElements().length > 0 &&
781 menu.getSubElements()[0] instanceof JPopupMenu) {
782 menuElement = menu.getSubElements()[0];
783 }
784 for (MenuElement item : menuElement.getSubElements()) {
785 if (item instanceof JMenuItem) {
786 JMenuItem menuItem = ((JMenuItem)item);
787 if (menuItem.getAction() != null) {
788 Action action = menuItem.getAction();
789 userObject = action;
790 String toolbar = (String) action.getValue("toolbar");
791 if(toolbar == null) {
792 System.out.println(tr("Toolbar action without name: {0}",
793 action.getClass().getName()));
794 } else {
795 Action r = actions.get(toolbar);
796 if(r != null && r != action) {
797 System.out.println(tr("Toolbar action {0} overwritten: {1} gets {2}",
798 toolbar, r.getClass().getName(), action.getClass().getName()));
799 }
800 }
801 actions.put(toolbar, action);
802 } else {
803 userObject = menuItem.getText();
804 }
805 }
806 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(userObject);
807 node.add(newNode);
808 loadAction(newNode, item);
809 }
810 }
811
812 public Action getAction(String s)
813 {
814 Action e = actions.get(s);
815 if(e == null) {
816 e = regactions.get(s);
817 }
818 return e;
819 }
820
821 private void loadActions() {
822 rootActionsNode.removeAllChildren();
823 loadAction(rootActionsNode, Main.main.menu);
824 for(Map.Entry<String, Action> a : regactions.entrySet())
825 {
826 if(actions.get(a.getKey()) == null) {
827 rootActionsNode.add(new DefaultMutableTreeNode(a.getValue()));
828 }
829 }
830 rootActionsNode.add(new DefaultMutableTreeNode(null));
831 }
832
833 private static final String[] deftoolbar = {"open", "save", "download", "upload", "|",
834 "undo", "redo", "|", "dialogs/search", "preference", "|", "splitway", "combineway",
835 "wayflip", "|", "imagery-offset", "|", "tagginggroup_Highways/Streets",
836 "tagginggroup_Highways/Ways", "tagginggroup_Highways/Waypoints",
837 "tagginggroup_Highways/Barriers", "|", "tagginggroup_Transport/Car",
838 "tagginggroup_Transport/Public Transport", "|", "tagginggroup_Facilities/Tourism",
839 "tagginggroup_Facilities/Food+Drinks", "|", "tagginggroup_Man Made/Historic Places", "|",
840 "tagginggroup_Man Made/Man Made"};
841
842 private static Collection<String> getToolString() {
843
844 Collection<String> toolStr = Main.pref.getCollection("toolbar", Arrays.asList(deftoolbar));
845 if (toolStr == null || toolStr.size() == 0) {
846 toolStr = Arrays.asList(deftoolbar);
847 }
848 return toolStr;
849 }
850
851 private Collection<ActionDefinition> getDefinedActions() {
852 loadActions();
853
854 Map<String, Action> allActions = new HashMap<String, Action>(regactions);
855 allActions.putAll(actions);
856 ActionParser actionParser = new ActionParser(allActions);
857
858 Collection<ActionDefinition> result = new ArrayList<ActionDefinition>();
859
860 for (String s : getToolString()) {
861 if (s.equals("|")) {
862 result.add(ActionDefinition.getSeparator());
863 } else {
864 ActionDefinition a = actionParser.loadAction(s);
865 if(a != null) {
866 result.add(a);
867 } else {
868 System.out.println("Could not load tool definition "+s);
869 }
870 }
871 }
872
873 return result;
874 }
875
876 /**
877 * @return The parameter (for better chaining)
878 */
879 public Action register(Action action) {
880 String toolbar = (String) action.getValue("toolbar");
881 if(toolbar == null) {
882 System.out.println(tr("Registered toolbar action without name: {0}",
883 action.getClass().getName()));
884 } else {
885 Action r = regactions.get(toolbar);
886 if(r != null) {
887 System.out.println(tr("Registered toolbar action {0} overwritten: {1} gets {2}",
888 toolbar, r.getClass().getName(), action.getClass().getName()));
889 }
890 }
891 regactions.put(toolbar, action);
892 return action;
893 }
894
895 /**
896 * Parse the toolbar preference setting and construct the toolbar GUI control.
897 *
898 * Call this, if anything has changed in the toolbar settings and you want to refresh
899 * the toolbar content (e.g. after registering actions in a plugin)
900 */
901 public void refreshToolbarControl() {
902 control.removeAll();
903
904 for (ActionDefinition action : getDefinedActions()) {
905 if (action.isSeparator()) {
906 control.addSeparator();
907 } else {
908 JButton b = control.add(action.getParametrizedAction());
909 String tt = action.getDisplayTooltip();
910 if (tt != null && !tt.isEmpty())
911 b.setToolTipText(tt);
912 Icon i = action.getDisplayIcon();
913 if (i != null)
914 b.setIcon(i);
915 }
916 }
917 control.setVisible(control.getComponentCount() != 0);
918 }
919
920 private static DataFlavor ACTION_FLAVOR = new DataFlavor(
921 ActionDefinition.class, "ActionItem");
922
923}
Note: See TracBrowser for help on using the repository browser.