Changeset 3175 in josm for trunk/src/org


Ignore:
Timestamp:
2010-04-11T12:08:22+02:00 (14 years ago)
Author:
jttt
Message:

Allow to set parameters for actions on toolbar. Used by SearchAction to set searching expression (see #4546)

Location:
trunk/src/org/openstreetmap/josm
Files:
3 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java

    r3102 r3175  
    1616import java.util.LinkedList;
    1717import java.util.List;
     18import java.util.Map;
    1819
    1920import javax.swing.ButtonGroup;
     
    2526
    2627import org.openstreetmap.josm.Main;
     28import org.openstreetmap.josm.actions.ActionParameter;
    2729import org.openstreetmap.josm.actions.JosmAction;
     30import org.openstreetmap.josm.actions.ParameterizedAction;
     31import org.openstreetmap.josm.actions.ActionParameter.SearchSettingsActionParameter;
    2832import org.openstreetmap.josm.data.osm.DataSet;
    2933import org.openstreetmap.josm.data.osm.Filter;
     
    3438import org.openstreetmap.josm.tools.Shortcut;
    3539
    36 public class SearchAction extends JosmAction{
     40public class SearchAction extends JosmAction implements ParameterizedAction {
    3741
    3842    public static final int DEFAULT_SEARCH_HISTORY_SIZE = 10;
    3943
     44    private static final String SEARCH_EXPRESSION = "searchExpression";
     45
    4046    public static enum SearchMode {
    41         replace, add, remove, in_selection
     47        replace('R'), add('A'), remove('D'), in_selection('S');
     48
     49        private final char code;
     50
     51        SearchMode(char code) {
     52            this.code = code;
     53        }
     54
     55        public char getCode() {
     56            return code;
     57        }
     58
     59        public static SearchMode fromCode(char code) {
     60            for (SearchMode mode: values()) {
     61                if (mode.getCode() == code)
     62                    return mode;
     63            }
     64            return null;
     65        }
    4266    }
    4367
     
    5680            return;
    5781        search();
     82    }
     83
     84    public void actionPerformed(ActionEvent e, Map<String, Object> parameters) {
     85        if (parameters.get(SEARCH_EXPRESSION) == null) {
     86            actionPerformed(e);
     87        } else {
     88            searchWithoutHistory((SearchSetting) parameters.get(SEARCH_EXPRESSION));
     89        }
    5890    }
    5991
     
    349381            return text.hashCode();
    350382        }
     383
     384        public static SearchSetting readFromString(String s) {
     385            if (s.length() == 0)
     386                return null;
     387
     388            SearchSetting result = new SearchSetting();
     389
     390            int index = 1;
     391
     392            result.mode = SearchMode.fromCode(s.charAt(0));
     393            if (result.mode == null) {
     394                result.mode = SearchMode.replace;
     395                index = 0;
     396            }
     397
     398            while (index < s.length()) {
     399                if (s.charAt(index) == 'C') {
     400                    result.caseSensitive = true;
     401                } else if (s.charAt(index) == 'R') {
     402                    result.regexSearch = true;
     403                } else if (s.charAt(index) == ' ') {
     404                    break;
     405                } else {
     406                    System.out.println("Uknown char in SearchSettings: " + s);
     407                    break;
     408                }
     409                index++;
     410            }
     411
     412            if (index < s.length() && s.charAt(index) == ' ') {
     413                index++;
     414            }
     415
     416            result.text = s.substring(index);
     417
     418            return result;
     419        }
     420
     421        public String writeToString() {
     422            if (text == null || text.length() == 0)
     423                return "";
     424
     425            StringBuilder result = new StringBuilder();
     426            result.append(mode.getCode());
     427            if (caseSensitive) {
     428                result.append('C');
     429            }
     430            if (regexSearch) {
     431                result.append('R');
     432            }
     433            result.append(' ');
     434            result.append(text);
     435            return result.toString();
     436        }
    351437    }
    352438
     
    359445        setEnabled(getEditLayer() != null);
    360446    }
     447
     448    public List<ActionParameter<?>> getActionParameters() {
     449        return Collections.<ActionParameter<?>>singletonList(new SearchSettingsActionParameter(SEARCH_EXPRESSION));
     450    }
    361451}
  • trunk/src/org/openstreetmap/josm/gui/preferences/ToolbarPreferences.java

    r3059 r3175  
    1818import java.awt.event.InputEvent;
    1919import java.io.IOException;
     20import java.util.ArrayList;
    2021import java.util.Arrays;
    2122import java.util.Collection;
     
    2526import java.util.Map;
    2627
    27 import javax.swing.AbstractAction;
    2828import javax.swing.Action;
    2929import javax.swing.DefaultListCellRenderer;
     
    3838import javax.swing.JPopupMenu;
    3939import javax.swing.JScrollPane;
     40import javax.swing.JTable;
    4041import javax.swing.JToolBar;
    4142import javax.swing.JTree;
     
    4546import javax.swing.event.ListSelectionEvent;
    4647import javax.swing.event.ListSelectionListener;
     48import javax.swing.table.AbstractTableModel;
    4749import javax.swing.tree.DefaultMutableTreeNode;
    4850import javax.swing.tree.DefaultTreeCellRenderer;
     
    5153
    5254import org.openstreetmap.josm.Main;
     55import org.openstreetmap.josm.actions.ActionParameter;
     56import org.openstreetmap.josm.actions.ParameterizedAction;
     57import org.openstreetmap.josm.actions.ParameterizedActionDecorator;
    5358import org.openstreetmap.josm.gui.tagging.TaggingPreset;
    5459import org.openstreetmap.josm.tools.GBC;
     
    5661
    5762public class ToolbarPreferences implements PreferenceSettingFactory {
     63
     64    public static class ActionDefinition {
     65
     66        public static ActionDefinition SEPARATOR = new ActionDefinition(null);
     67
     68        private final Action action;
     69        private final Map<String, Object> parameters = new HashMap<String, Object>();
     70
     71        public ActionDefinition(Action action) {
     72            this.action = action;
     73        }
     74
     75        public Map<String, Object> getParameters() {
     76            return parameters;
     77        }
     78
     79        public Action getParametrizedAction() {
     80            if (getAction() instanceof ParameterizedAction)
     81                return new ParameterizedActionDecorator((ParameterizedAction) getAction(), parameters);
     82            else
     83                return getAction();
     84        }
     85
     86        public Action getAction() {
     87            return action;
     88        }
     89
     90    }
     91
     92    public static class ActionParser {
     93        private final Map<String, Action> actions;
     94        private final StringBuilder result = new StringBuilder();
     95        private int index;
     96        private char[] s;
     97
     98        public ActionParser(Map<String, Action> actions) {
     99            this.actions = actions;
     100        }
     101
     102        private String readTillChar(char ch1, char ch2) {
     103            result.setLength(0);
     104            while (index < s.length && s[index] != ch1 && s[index] != ch2) {
     105                if (s[index] == '\\') {
     106                    index++;
     107                    if (index >= s.length) {
     108                        break;
     109                    }
     110                }
     111                result.append(s[index]);
     112                index++;
     113            }
     114            return result.toString();
     115        }
     116
     117        private void skip(char ch) {
     118            if (index < s.length && s[index] == ch) {
     119                index++;
     120            }
     121        }
     122
     123        public ActionDefinition loadAction(String actionName) {
     124            index = 0;
     125            this.s = actionName.toCharArray();
     126
     127            String name = readTillChar('(', '(');
     128            Action action = actions.get(name);
     129
     130            if (action == null)
     131                return null;
     132
     133            ActionDefinition result = new ActionDefinition(action);
     134
     135            if (action instanceof ParameterizedAction) {
     136                skip('(');
     137
     138                ParameterizedAction parametrizedAction = (ParameterizedAction)action;
     139                Map<String, ActionParameter<?>> actionParams = new HashMap<String, ActionParameter<?>>();
     140                for (ActionParameter<?> param: parametrizedAction.getActionParameters()) {
     141                    actionParams.put(param.getName(), param);
     142                }
     143
     144                do {
     145                    String paramName = readTillChar('=', '=');
     146                    skip('=');
     147                    String paramValue = readTillChar(',',')');
     148                    if (paramName.length() > 0) {
     149                        ActionParameter<?> actionParam = actionParams.get(paramName);
     150                        if (actionParam != null) {
     151                            result.getParameters().put(paramName, actionParam.readFromString(paramValue));
     152                        }
     153                    }
     154                    skip(',');
     155                } while (index < s.length && s[index] != ')');
     156            }
     157
     158            return result;
     159        }
     160
     161        private void escape(String s) {
     162            for (int i=0; i<s.length(); i++) {
     163                char ch = s.charAt(i);
     164                if (ch == '\\' || ch == '(' || ch == ',' || ch == ')' || ch == '=') {
     165                    result.append('\\');
     166                    result.append(ch);
     167                } else {
     168                    result.append(ch);
     169                }
     170            }
     171        }
     172
     173        @SuppressWarnings("unchecked")
     174        public String saveAction(ActionDefinition action) {
     175            result.setLength(0);
     176
     177            escape((String) action.getAction().getValue("toolbar"));
     178            if (action.getAction() instanceof ParameterizedAction) {
     179                result.append('(');
     180                List<ActionParameter<?>> params = ((ParameterizedAction)action.getAction()).getActionParameters();
     181                for (int i=0; i<params.size(); i++) {
     182                    ActionParameter<Object> param = (ActionParameter<Object>)params.get(i);
     183                    escape(param.getName());
     184                    result.append('=');
     185                    Object value = action.getParameters().get(param.getName());
     186                    if (value != null) {
     187                        escape(param.writeToString(value));
     188                    }
     189                    if (i < params.size() - 1) {
     190                        result.append(',');
     191                    } else {
     192                        result.append(')');
     193                    }
     194                }
     195            }
     196
     197            return result.toString();
     198        }
     199    }
     200
     201    private static class ActionParametersTableModel extends AbstractTableModel {
     202
     203        private ActionDefinition currentAction = ActionDefinition.SEPARATOR;
     204
     205        public int getColumnCount() {
     206            return 2;
     207        }
     208
     209        public int getRowCount() {
     210            if (currentAction == ActionDefinition.SEPARATOR || !(currentAction.getAction() instanceof ParameterizedAction))
     211                return 0;
     212            ParameterizedAction pa = (ParameterizedAction)currentAction.getAction();
     213            return pa.getActionParameters().size();
     214        }
     215
     216        @SuppressWarnings("unchecked")
     217        private ActionParameter<Object> getParam(int index) {
     218            ParameterizedAction pa = (ParameterizedAction)currentAction.getAction();
     219            return (ActionParameter<Object>) pa.getActionParameters().get(index);
     220        }
     221
     222        public Object getValueAt(int rowIndex, int columnIndex) {
     223            ActionParameter<Object> param = getParam(rowIndex);
     224            switch (columnIndex) {
     225            case 0:
     226                return param.getName();
     227            case 1:
     228                return param.writeToString(currentAction.getParameters().get(param.getName()));
     229            default:
     230                return null;
     231            }
     232        }
     233
     234        @Override
     235        public boolean isCellEditable(int row, int column) {
     236            return column == 1;
     237        }
     238
     239        @Override
     240        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
     241            ActionParameter<Object> param = getParam(rowIndex);
     242            currentAction.getParameters().put(param.getName(), param.readFromString((String)aValue));
     243        }
     244
     245
     246        public void setCurrentAction(ActionDefinition currentAction) {
     247            this.currentAction = currentAction;
     248            fireTableDataChanged();
     249        }
     250
     251    }
    58252
    59253    /**
     
    72266    }
    73267
    74     public static class Settings implements PreferenceSetting {
     268    public class Settings implements PreferenceSetting {
    75269
    76270        private final class Move implements ActionListener {
     
    85279                    for (TreePath selectedAction : actionsTree.getSelectionPaths()) {
    86280                        DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectedAction.getLastPathComponent();
    87                         if (node.getUserObject() == null)
    88                             selected.add(leadItem++, null);
    89                         else if (node.getUserObject() == null || node.getUserObject() instanceof Action)
    90                             selected.add(leadItem++, ((Action)node.getUserObject()).getValue("toolbar"));
     281                        if (node.getUserObject() == null) {
     282                            selected.add(leadItem++, ActionDefinition.SEPARATOR);
     283                        } else if (node.getUserObject() instanceof Action) {
     284                            selected.add(leadItem++, new ActionDefinition((Action)node.getUserObject()));
     285                        }
    91286                    }
    92287                } else if (e.getActionCommand().equals(">") && selectedList.getSelectedIndex() != -1) {
     
    114309        }
    115310
    116         private static class ActionTransferable implements Transferable {
     311        private class ActionTransferable implements Transferable {
    117312
    118313            private DataFlavor[] flavors = new DataFlavor[] { ACTION_FLAVOR };
    119314
    120             private Object[] actions;
    121 
    122             public ActionTransferable(Action action) {
    123                 this.actions = new Action[] { action };
    124             }
    125 
    126             public ActionTransferable(Object[] actions) {
     315            private final List<ActionDefinition> actions;
     316
     317            public ActionTransferable(List<ActionDefinition> actions) {
    127318                this.actions = actions;
    128319            }
     
    148339        private final DefaultTreeModel actionsTreeModel;
    149340        private final JTree actionsTree;
     341
     342        private final ActionParametersTableModel actionParametersModel = new ActionParametersTableModel();
     343        private final JTable actionParametersTable = new JTable(actionParametersModel);
     344        private JPanel actionParametersPanel;
    150345
    151346        private JButton upButton;
     
    161356        private JButton createButton(String name) {
    162357            JButton b = new JButton();
    163             if (name.equals("up"))
     358            if (name.equals("up")) {
    164359                b.setIcon(ImageProvider.get("dialogs", "up"));
    165             else if (name.equals("down"))
     360            } else if (name.equals("down")) {
    166361                b.setIcon(ImageProvider.get("dialogs", "down"));
    167             else
     362            } else {
    168363                b.setText(name);
     364            }
    169365            b.addActionListener(moveAction);
    170366            b.setActionCommand(name);
     
    197393                    String s;
    198394                    Icon i;
    199                     if (value != null) {
    200                         Action action = Main.toolbar.getAction((String)value);
    201                         s = (String) action.getValue(Action.NAME);
    202                         i = (Icon) action.getValue(Action.SMALL_ICON);
     395                    if (value != ActionDefinition.SEPARATOR) {
     396                        ActionDefinition action = (ActionDefinition)value;
     397                        s = (String) action.getAction().getValue(Action.NAME);
     398                        i = (Icon) action.getAction().getValue(Action.SMALL_ICON);
    203399                    } else {
    204400                        i = ImageProvider.get("preferences/separator");
     
    214410                public void valueChanged(ListSelectionEvent e) {
    215411                    boolean sel = selectedList.getSelectedIndex() != -1;
    216                     if (sel)
     412                    if (sel) {
    217413                        actionsTree.clearSelection();
     414                        ActionDefinition action = (ActionDefinition) selected.get(selectedList.getSelectedIndex());
     415                        actionParametersModel.setCurrentAction(action);
     416                        actionParametersPanel.setVisible(actionParametersModel.getRowCount() > 0);
     417                    }
    218418                    upButton.setEnabled(sel);
    219419                    downButton.setEnabled(sel);
     
    225425                @Override
    226426                protected Transferable createTransferable(JComponent c) {
    227                     return new ActionTransferable(((JList)c).getSelectedValues());
     427                    List<ActionDefinition> actions = new ArrayList<ActionDefinition>();
     428                    for (Object o: ((JList)c).getSelectedValues()) {
     429                        actions.add((ActionDefinition)o);
     430                    }
     431                    return new ActionTransferable(actions);
    228432                }
    229433
     
    236440                public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
    237441                    for (DataFlavor f : transferFlavors) {
    238                         if (ACTION_FLAVOR.equals(f)) {
     442                        if (ACTION_FLAVOR.equals(f))
    239443                            return true;
    240                         }
    241444                    }
    242445                    return false;
     
    253456                    try {
    254457                        int dropIndex = selectedList.locationToIndex(selectedList.getMousePosition(true));
    255                         Object[] draggedData = (Object[]) t.getTransferData(ACTION_FLAVOR);
     458                        List<?> draggedData = (List<?>) t.getTransferData(ACTION_FLAVOR);
    256459
    257460                        Object leadItem = dropIndex >= 0 ? selected.elementAt(dropIndex) : null;
    258                         int dataLength = draggedData.length;
    259 
    260                         if (leadItem != null)
    261                             for (int i = 0; i < dataLength; i++)
    262                                 if (leadItem.equals(draggedData[i]))
     461                        int dataLength = draggedData.size();
     462
     463                        if (leadItem != null) {
     464                            for (Object o: draggedData) {
     465                                if (leadItem.equals(o))
    263466                                    return false;
     467                            }
     468                        }
    264469
    265470                        int dragLeadIndex = -1;
     
    267472
    268473                        if (localDrop) {
    269                             dragLeadIndex = selected.indexOf(draggedData[0]);
    270                             for (int i = 0; i < dataLength; i++)
    271                                 selected.removeElement(draggedData[i]);
     474                            dragLeadIndex = selected.indexOf(draggedData.get(0));
     475                            for (Object o: draggedData) {
     476                                selected.removeElement(o);
     477                            }
    272478                        }
    273479                        int[] indices = new int[dataLength];
     
    277483                            int insertionAdjustment = dragLeadIndex <= adjustedLeadIndex ? 1 : 0;
    278484                            for (int i = 0; i < dataLength; i++) {
    279                                 selected.insertElementAt(draggedData[i], adjustedLeadIndex + insertionAdjustment + i);
     485                                selected.insertElementAt(draggedData.get(i), adjustedLeadIndex + insertionAdjustment + i);
    280486                                indices[i] = adjustedLeadIndex + insertionAdjustment + i;
    281487                            }
    282488                        } else {
    283489                            for (int i = 0; i < dataLength; i++) {
    284                                 selected.add(dropIndex, draggedData[i]);
     490                                selected.add(dropIndex, draggedData.get(i));
    285491                                indices[i] = dropIndex + i;
    286492                            }
     
    300506                    if (movingComponent.equals("list")) {
    301507                        try {
    302                             Object[] draggedData = (Object[]) data.getTransferData(ACTION_FLAVOR);
    303                             boolean localDrop = selected.contains(draggedData[0]);
     508                            List<?> draggedData = (List<?>) data.getTransferData(ACTION_FLAVOR);
     509                            boolean localDrop = selected.contains(draggedData.get(0));
    304510                            if (localDrop) {
    305511                                int[] indices = selectedList.getSelectedIndices();
     
    332538                protected Transferable createTransferable(JComponent c) {
    333539                    TreePath[] paths = actionsTree.getSelectionPaths();
    334                     List<String> dragActions = new LinkedList<String>();
     540                    List<ActionDefinition> dragActions = new ArrayList<ActionDefinition>();
    335541                    for (TreePath path : paths) {
    336542                        DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
    337543                        Object obj = node.getUserObject();
    338544                        if (obj == null) {
    339                             dragActions.add(null);
     545                            dragActions.add(ActionDefinition.SEPARATOR);
    340546                        }
    341547                        else if (obj instanceof Action) {
    342                             dragActions.add((String) ((Action) obj).getValue("toolbar"));
     548                            dragActions.add(new ActionDefinition((Action) obj));
    343549                        }
    344550                    }
    345                     return new ActionTransferable(dragActions.toArray());
     551                    return new ActionTransferable(dragActions);
    346552                }
    347553            });
     
    392598            p.add(right);
    393599
     600            actionParametersPanel = new JPanel(new GridBagLayout());
     601            actionParametersPanel.add(new JLabel(tr("Action parameters")), GBC.eol().insets(0, 10, 0, 20));
     602            actionParametersTable.getColumnModel().getColumn(0).setHeaderValue(tr("Parameter name"));
     603            actionParametersTable.getColumnModel().getColumn(1).setHeaderValue(tr("Parameter value"));
     604            actionParametersPanel.add(actionParametersTable.getTableHeader(), GBC.eol().fill(GBC.HORIZONTAL));
     605            actionParametersPanel.add(actionParametersTable, GBC.eol().fill(GBC.BOTH).insets(0, 0, 0, 10));
     606            actionParametersPanel.setVisible(false);
     607
    394608            JPanel panel = gui.createPreferenceTab("toolbar", tr("Toolbar customization"),
    395609                    tr("Customize the elements on the toolbar."), false);
    396610            panel.add(p, GBC.eol().fill(GBC.BOTH));
    397 
     611            panel.add(actionParametersPanel, GBC.eol().fill(GBC.HORIZONTAL));
    398612            selected.removeAllElements();
    399             for (String s : getToolString()) {
    400                 if (s.equals("|"))
    401                     selected.addElement(null);
    402                 else if (Main.toolbar.getAction(s) != null)
    403                     selected.addElement(s);
     613            for (ActionDefinition actionDefinition: getDefinedActions()) {
     614                selected.addElement(actionDefinition);
    404615            }
    405616        }
     
    407618        public boolean ok() {
    408619            Collection<String> t = new LinkedList<String>();
     620            ActionParser parser = new ActionParser(null);
    409621            for (int i = 0; i < selected.size(); ++i) {
    410                 if (selected.get(i) == null)
     622                if (selected.get(i) == ActionDefinition.SEPARATOR) {
    411623                    t.add("|");
    412                 else
    413                     t.add((String)((Main.toolbar.getAction((String)selected.get(i))).getValue("toolbar")));
     624                } else {
     625                    t.add(parser.saveAction((ActionDefinition)(selected.get(i))));
     626                }
    414627            }
    415628            Main.pref.putCollection("toolbar", t);
     
    451664    {
    452665        Action e = actions.get(s);
    453         if(e == null)
     666        if(e == null) {
    454667            e = regactions.get(s);
     668        }
    455669        return e;
    456670    }
     
    461675        for(Map.Entry<String, Action> a : regactions.entrySet())
    462676        {
    463             if(actions.get(a.getKey()) == null)
     677            if(actions.get(a.getKey()) == null) {
    464678                rootActionsNode.add(new DefaultMutableTreeNode(a.getValue()));
     679            }
    465680        }
    466681        rootActionsNode.add(new DefaultMutableTreeNode(null));
     
    471686    private static Collection<String> getToolString() {
    472687        return Main.pref.getCollection("toolbar", Arrays.asList(deftoolbar));
     688    }
     689
     690    private Collection<ActionDefinition> getDefinedActions() {
     691        loadActions();
     692
     693        Map<String, Action> allActions = new HashMap<String, Action>(regactions);
     694        allActions.putAll(actions);
     695        ActionParser actionParser = new ActionParser(allActions);
     696
     697        Collection<ActionDefinition> result = new ArrayList<ActionDefinition>();
     698
     699        for (String s : getToolString()) {
     700            if (s.equals("|")) {
     701                result.add(ActionDefinition.SEPARATOR);
     702            } else {
     703                ActionDefinition a = actionParser.loadAction(s);
     704                if(a != null) {
     705                    result.add(a);
     706                }
     707            }
     708        }
     709
     710        return result;
    473711    }
    474712
     
    488726     */
    489727    public void refreshToolbarControl() {
    490         loadActions();
    491728        control.removeAll();
    492         for (String s : getToolString()) {
    493             if (s.equals("|"))
     729
     730        for (ActionDefinition action : getDefinedActions()) {
     731            if (action == ActionDefinition.SEPARATOR) {
    494732                control.addSeparator();
    495             else {
    496                 Action a = getAction(s);
    497                 if(a != null)
    498                 {
    499                     JButton b = control.add(a);
    500                     Object tt = a.getValue(TaggingPreset.OPTIONAL_TOOLTIP_TEXT);
    501                     if (tt != null)
    502                         b.setToolTipText((String)tt);
     733            } else {
     734                Action a = action.getParametrizedAction();
     735                JButton b = control.add(a);
     736                Object tt = a.getValue(TaggingPreset.OPTIONAL_TOOLTIP_TEXT);
     737                if (tt != null) {
     738                    b.setToolTipText((String)tt);
    503739                }
    504740            }
     
    508744
    509745    private static DataFlavor ACTION_FLAVOR = new DataFlavor(
    510             AbstractAction.class, "ActionItem");
     746            ActionDefinition.class, "ActionItem");
    511747
    512748}
Note: See TracChangeset for help on using the changeset viewer.