macros: keycode input if unicode characters
[fedora-idea.git] / platform / platform-impl / src / com / intellij / ide / actionMacro / ActionMacro.java
blob63a7ecc80c07dedaecca263bd0bd0f96905d119f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.ide.actionMacro;
18 import com.intellij.ide.IdeBundle;
19 import com.intellij.openapi.actionSystem.*;
20 import com.intellij.openapi.editor.Editor;
21 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
22 import com.intellij.openapi.editor.actionSystem.TypedAction;
23 import com.intellij.openapi.ui.playback.commands.KeyCodeTypeCommand;
24 import com.intellij.openapi.ui.playback.commands.TypeCommand;
25 import com.intellij.openapi.util.*;
26 import org.jdom.Element;
27 import org.jetbrains.annotations.NonNls;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Iterator;
32 import java.util.List;
34 /**
35 * @author max
37 public class ActionMacro implements JDOMExternalizable {
38 private String myName;
40 private final ArrayList<ActionDescriptor> myActions = new ArrayList<ActionDescriptor>();
41 @NonNls
42 public static final String MACRO_ACTION_PREFIX = "Macro.";
43 @NonNls
44 private static final String ATTRIBUTE_NAME = "name";
45 @NonNls
46 private static final String ELEMENT_TYPING = "typing";
48 @NonNls
49 private static final String ELEMENT_SHORTCUT = "shortuct";
50 @NonNls
51 private static final String ATTRIBUTE_TEXT = "text";
52 @NonNls
53 private static final String ATTRIBUTE_KEY_CODES = "text-keycode";
54 @NonNls
55 private static final String ELEMENT_ACTION = "action";
56 @NonNls
57 private static final String ATTRIBUTE_ID = "id";
60 public ActionMacro() {
63 public ActionMacro(String name) {
64 myName = name;
67 public String getName() {
68 return myName;
71 public void setName(String name) {
72 myName = name;
75 public ActionDescriptor[] getActions() {
76 return myActions.toArray(new ActionDescriptor[myActions.size()]);
79 public void readExternal(Element macro) throws InvalidDataException {
80 setName(macro.getAttributeValue(ATTRIBUTE_NAME));
81 List actions = macro.getChildren();
82 for (Iterator iterator = actions.iterator(); iterator.hasNext();) {
83 Element action = (Element)iterator.next();
84 if (ELEMENT_TYPING.equals(action.getName())) {
85 Pair<List<Integer>, List<Integer>> codes = parseKeyCodes(action.getAttributeValue(ATTRIBUTE_KEY_CODES));
86 myActions.add(new TypedDescriptor(action.getAttributeValue(ATTRIBUTE_TEXT), codes.getFirst(), codes.getSecond()));
88 else if (ELEMENT_ACTION.equals(action.getName())) {
89 myActions.add(new IdActionDescriptor(action.getAttributeValue(ATTRIBUTE_ID)));
90 } else if (ELEMENT_SHORTCUT.equals(action.getName())) {
91 myActions.add(new ShortcutActionDesciption(action.getAttributeValue(ATTRIBUTE_TEXT)));
96 private Pair<List<Integer>, List<Integer>> parseKeyCodes(String keyCodesText) {
97 return KeyCodeTypeCommand.parseKeyCodes(keyCodesText);
100 public String unparseKeyCodes(Pair<List<Integer>, List<Integer>> keyCodes) {
101 return KeyCodeTypeCommand.unparseKeyCodes(keyCodes);
104 public void writeExternal(Element macro) throws WriteExternalException {
105 macro.setAttribute(ATTRIBUTE_NAME, myName);
106 final ActionDescriptor[] actions = getActions();
107 for (int i = 0; i < actions.length; i++) {
108 ActionDescriptor action = actions[i];
109 Element actionNode = null;
110 if (action instanceof TypedDescriptor) {
111 actionNode = new Element(ELEMENT_TYPING);
112 TypedDescriptor typedDescriptor = (TypedDescriptor)action;
113 final String t = typedDescriptor.getText();
114 actionNode.setAttribute(ATTRIBUTE_TEXT, JDOMUtil.escapeText(t));
115 actionNode.setAttribute(ATTRIBUTE_KEY_CODES, unparseKeyCodes(new Pair<List<Integer>, List<Integer>>(typedDescriptor.getKeyCodes(), typedDescriptor.getKeyModifiers())));
117 else if (action instanceof IdActionDescriptor) {
118 actionNode = new Element(ELEMENT_ACTION);
119 actionNode.setAttribute(ATTRIBUTE_ID, ((IdActionDescriptor)action).getActionId());
120 } else if (action instanceof ShortcutActionDesciption) {
121 actionNode = new Element(ELEMENT_SHORTCUT);
122 actionNode.setAttribute(ATTRIBUTE_TEXT, ((ShortcutActionDesciption)action).getText());
126 assert actionNode != null : action;
128 macro.addContent(actionNode);
132 public String toString() {
133 return myName;
136 protected Object clone() {
137 ActionMacro copy = new ActionMacro(myName);
138 for (int i = 0; i < myActions.size(); i++) {
139 ActionDescriptor action = myActions.get(i);
140 copy.myActions.add((ActionDescriptor)action.clone());
143 return copy;
146 public boolean equals(Object o) {
147 if (this == o) return true;
148 if (!(o instanceof ActionMacro)) return false;
150 final ActionMacro actionMacro = (ActionMacro)o;
152 if (!myActions.equals(actionMacro.myActions)) return false;
153 if (!myName.equals(actionMacro.myName)) return false;
155 return true;
158 public int hashCode() {
159 int result;
160 result = myName.hashCode();
161 result = 29 * result + myActions.hashCode();
162 return result;
165 public void deleteAction(int idx) {
166 myActions.remove(idx);
169 public void appendAction(String actionId) {
170 myActions.add(new IdActionDescriptor(actionId));
173 public void appendShortuct(String text) {
174 myActions.add(new ShortcutActionDesciption(text));
177 public void appendKeytyped(char c, int keyCode, int modifiers) {
178 ActionDescriptor lastAction = myActions.size() > 0 ? myActions.get(myActions.size() - 1) : null;
179 if (lastAction instanceof TypedDescriptor) {
180 ((TypedDescriptor)lastAction).addChar(c, keyCode, modifiers);
182 else {
183 myActions.add(new TypedDescriptor(c, keyCode, modifiers));
187 public String getActionId() {
188 return MACRO_ACTION_PREFIX + myName;
191 public interface ActionDescriptor {
192 Object clone();
194 void playBack(DataContext context);
196 void generateTo(StringBuffer script);
199 public static class TypedDescriptor implements ActionDescriptor {
201 private String myText;
203 private List<Integer> myKeyCodes = new ArrayList<Integer>();
204 private List<Integer> myModifiers = new ArrayList<Integer>();
206 public TypedDescriptor(String text, List<Integer> keyCodes, List<Integer> modifiers) {
207 myText = text;
208 myKeyCodes.addAll(keyCodes);
209 myModifiers.addAll(modifiers);
211 assert myKeyCodes.size() == myModifiers.size();
214 public TypedDescriptor(char c, int keyCode, int modifiers) {
215 myText = String.valueOf(c);
216 myKeyCodes.add(keyCode);
217 myModifiers.add(modifiers);
220 public void addChar(char c, int keyCode, int modifier) {
221 myText = myText + c;
222 myKeyCodes.add(keyCode);
223 myModifiers.add(modifier);
226 public String getText() {
227 return myText;
230 public Object clone() {
231 return new TypedDescriptor(myText, myKeyCodes, myModifiers);
234 public boolean equals(Object o) {
235 if (this == o) return true;
236 if (!(o instanceof TypedDescriptor)) return false;
237 return myText.equals(((TypedDescriptor)o).myText);
240 public int hashCode() {
241 return myText.hashCode();
244 public void generateTo(StringBuffer script) {
245 if (TypeCommand.containsUnicode(myText)) {
246 script.append(KeyCodeTypeCommand.PREFIX).append(" ");
248 for (int i = 0; i < myKeyCodes.size(); i++) {
249 Integer each = myKeyCodes.get(i);
250 script.append(each.toString());
251 script.append(KeyCodeTypeCommand.MODIFIER_DELIMITER);
252 script.append(myModifiers.get(i));
253 if (i < myKeyCodes.size() - 1) {
254 script.append(KeyCodeTypeCommand.CODE_DELIMITER);
257 script.append(" ").append(myText).append("\n");
258 } else {
259 script.append(myText);
260 script.append("\n");
264 public String toString() {
265 return IdeBundle.message("action.descriptor.typing", myText);
268 public void playBack(DataContext context) {
269 Editor editor = PlatformDataKeys.EDITOR.getData(context);
270 final TypedAction typedAction = EditorActionManager.getInstance().getTypedAction();
271 char chars[] = myText.toCharArray();
272 for (int i = 0; i < chars.length; i++) {
273 typedAction.actionPerformed(editor, chars[i], context);
277 public List<Integer> getKeyCodes() {
278 return myKeyCodes;
281 public List<Integer> getKeyModifiers() {
282 return myModifiers;
286 public static class ShortcutActionDesciption implements ActionDescriptor {
288 private String myKeyStroke;
290 public ShortcutActionDesciption(String stroke) {
291 myKeyStroke = stroke;
294 public Object clone() {
295 return new ShortcutActionDesciption(myKeyStroke);
298 public void playBack(DataContext context) {
301 public void generateTo(StringBuffer script) {
302 script.append("%[").append(myKeyStroke).append("]\n");
305 public String toString() {
306 return IdeBundle.message("action.descriptor.keystroke", myKeyStroke);
309 public String getText() {
310 return myKeyStroke;
314 public static class IdActionDescriptor implements ActionDescriptor {
315 private final String actionId;
317 public IdActionDescriptor(String id) {
318 this.actionId = id;
321 public String getActionId() {
322 return actionId;
325 public String toString() {
326 return IdeBundle.message("action.descriptor.action", actionId);
329 public Object clone() {
330 return new IdActionDescriptor(actionId);
333 public boolean equals(Object o) {
334 if (this == o) return true;
335 if (!(o instanceof IdActionDescriptor)) return false;
336 return actionId.equals(((IdActionDescriptor)o).actionId);
339 public int hashCode() {
340 return actionId.hashCode();
343 public void playBack(DataContext context) {
344 AnAction action = ActionManager.getInstance().getAction(getActionId());
345 if (action == null) return;
346 Presentation presentation = (Presentation)action.getTemplatePresentation().clone();
347 AnActionEvent event = new AnActionEvent(null, context, "MACRO_PLAYBACK", presentation, ActionManager.getInstance(), 0);
348 action.beforeActionPerformedUpdate(event);
349 if (!presentation.isEnabled()) {
350 return;
352 action.actionPerformed(event);
355 public void generateTo(StringBuffer script) {
356 script.append("%action ").append(getActionId()).append("\n");