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 org
.jetbrains
.idea
.devkit
.actions
;
18 import com
.intellij
.openapi
.actionSystem
.ActionGroup
;
19 import com
.intellij
.openapi
.actionSystem
.ActionManager
;
20 import com
.intellij
.openapi
.actionSystem
.AnAction
;
21 import com
.intellij
.openapi
.actionSystem
.DefaultActionGroup
;
22 import com
.intellij
.openapi
.keymap
.KeymapUtil
;
23 import com
.intellij
.openapi
.project
.Project
;
24 import com
.intellij
.openapi
.ui
.DialogWrapper
;
25 import com
.intellij
.openapi
.ui
.TextFieldWithBrowseButton
;
26 import com
.intellij
.openapi
.util
.IconLoader
;
27 import com
.intellij
.peer
.PeerFactory
;
28 import com
.intellij
.psi
.JavaPsiFacade
;
29 import com
.intellij
.psi
.PsiClass
;
30 import com
.intellij
.ui
.ColoredListCellRenderer
;
31 import com
.intellij
.ui
.SimpleTextAttributes
;
32 import com
.intellij
.util
.ArrayUtil
;
33 import com
.intellij
.util
.Function
;
34 import org
.jetbrains
.annotations
.NonNls
;
35 import org
.jetbrains
.annotations
.NotNull
;
36 import org
.jetbrains
.annotations
.Nullable
;
37 import org
.jetbrains
.idea
.devkit
.DevKitBundle
;
38 import org
.jetbrains
.idea
.devkit
.util
.ActionData
;
39 import org
.jetbrains
.idea
.devkit
.util
.ActionType
;
42 import javax
.swing
.event
.DocumentEvent
;
43 import javax
.swing
.event
.DocumentListener
;
44 import javax
.swing
.event
.ListSelectionEvent
;
45 import javax
.swing
.event
.ListSelectionListener
;
47 import java
.awt
.event
.ActionEvent
;
48 import java
.awt
.event
.ActionListener
;
49 import java
.awt
.event
.KeyEvent
;
50 import java
.util
.ArrayList
;
51 import java
.util
.Arrays
;
52 import java
.util
.List
;
57 public class NewActionDialog
extends DialogWrapper
implements ActionData
{
58 private JPanel myRootPanel
;
59 private JList myGroupList
;
60 private JList myActionList
;
61 private JTextField myActionNameEdit
;
62 private JTextField myActionIdEdit
;
63 private JTextField myActionTextEdit
;
64 private JTextField myActionDescriptionEdit
;
65 private JRadioButton myAnchorFirstRadio
;
66 private JRadioButton myAnchorLastRadio
;
67 private JRadioButton myAnchorBeforeRadio
;
68 private JRadioButton myAnchorAfterRadio
;
69 private JPanel myShortcutPanel
;
70 private JPanel myFirstKeystrokeEditPlaceholder
;
71 private JPanel mySecondKeystrokeEditPlaceholder
;
72 private JButton myClearFirstKeystroke
;
73 private JButton myClearSecondKeystroke
;
74 private ShortcutTextField myFirstKeystrokeEdit
;
75 private ShortcutTextField mySecondKeystrokeEdit
;
76 private TextFieldWithBrowseButton myIconEdit
;
77 private Project myProject
;
78 private ButtonGroup myAnchorButtonGroup
;
80 public NewActionDialog(PsiClass actionClass
) {
81 this(actionClass
.getProject());
83 myActionNameEdit
.setText(actionClass
.getQualifiedName());
84 myActionNameEdit
.setEditable(false);
85 myActionIdEdit
.setText(actionClass
.getQualifiedName());
86 if (ActionType
.GROUP
.isOfType(actionClass
)) {
87 myShortcutPanel
.setVisible(false);
91 protected NewActionDialog(final Project project
) {
92 super(project
, false);
95 setTitle(DevKitBundle
.message("new.action.dialog.title"));
96 final ActionManager actionManager
= ActionManager
.getInstance();
97 final String
[] actionIds
= actionManager
.getActionIds("");
98 Arrays
.sort(actionIds
);
99 final List
<ActionGroup
> actionGroups
= new ArrayList
<ActionGroup
>();
100 for(String actionId
: actionIds
) {
101 if (actionManager
.isGroup(actionId
)) {
102 final AnAction anAction
= actionManager
.getAction(actionId
);
103 if (anAction
instanceof DefaultActionGroup
) {
104 actionGroups
.add((ActionGroup
) anAction
);
108 myGroupList
.setListData(actionGroups
.toArray());
109 myGroupList
.setCellRenderer(new MyActionRenderer());
110 myGroupList
.addListSelectionListener(new ListSelectionListener() {
111 public void valueChanged(ListSelectionEvent e
) {
112 ActionGroup group
= (ActionGroup
) myGroupList
.getSelectedValue();
114 myActionList
.setListData(ArrayUtil
.EMPTY_OBJECT_ARRAY
);
117 final AnAction
[] actions
= group
.getChildren(null);
118 // filter out actions that don't have IDs - they can't be used for anchoring in plugin.xml
119 List
<AnAction
> realActions
= new ArrayList
<AnAction
>();
120 for(AnAction action
: actions
) {
121 if (actionManager
.getId(action
) != null) {
122 realActions
.add(action
);
125 myActionList
.setListData(realActions
.toArray());
129 PeerFactory
.getInstance().getUIHelper().installListSpeedSearch(myGroupList
, new Function
<Object
, String
>() {
130 public String
fun(final Object o
) {
131 return ActionManager
.getInstance().getId((AnAction
) o
);
135 myActionList
.setCellRenderer(new MyActionRenderer());
136 myActionList
.addListSelectionListener(new ListSelectionListener() {
137 public void valueChanged(ListSelectionEvent e
) {
142 final MyDocumentListener listener
= new MyDocumentListener();
143 myActionIdEdit
.getDocument().addDocumentListener(listener
);
144 myActionNameEdit
.getDocument().addDocumentListener(listener
);
145 myActionTextEdit
.getDocument().addDocumentListener(listener
);
147 myAnchorButtonGroup
.setSelected(myAnchorFirstRadio
.getModel(), true);
149 myFirstKeystrokeEdit
= new ShortcutTextField();
150 myFirstKeystrokeEditPlaceholder
.setLayout(new BorderLayout());
151 myFirstKeystrokeEditPlaceholder
.add(myFirstKeystrokeEdit
, BorderLayout
.CENTER
);
152 myClearFirstKeystroke
.addActionListener(new ActionListener() {
153 public void actionPerformed(ActionEvent e
) {
154 myFirstKeystrokeEdit
.setKeyStroke(null);
157 myFirstKeystrokeEdit
.getDocument().addDocumentListener(listener
);
158 myClearFirstKeystroke
.setText(null);
160 final Icon icon
= IconLoader
.getIcon("/actions/cancel.png");
161 final Dimension size
= new Dimension(icon
.getIconWidth(), icon
.getIconHeight());
162 myClearFirstKeystroke
.setIcon(icon
);
163 myClearFirstKeystroke
.setPreferredSize(size
);
164 myClearFirstKeystroke
.setMaximumSize(size
);
166 mySecondKeystrokeEdit
= new ShortcutTextField();
167 mySecondKeystrokeEditPlaceholder
.setLayout(new BorderLayout());
168 mySecondKeystrokeEditPlaceholder
.add(mySecondKeystrokeEdit
, BorderLayout
.CENTER
);
169 myClearSecondKeystroke
.addActionListener(new ActionListener() {
170 public void actionPerformed(ActionEvent e
) {
171 mySecondKeystrokeEdit
.setKeyStroke(null);
174 mySecondKeystrokeEdit
.getDocument().addDocumentListener(listener
);
175 myClearSecondKeystroke
.setText(null);
176 myClearSecondKeystroke
.setIcon(icon
);
177 myClearSecondKeystroke
.setPreferredSize(size
);
178 myClearSecondKeystroke
.setMaximumSize(size
);
183 protected JComponent
createCenterPanel() {
187 @Override public JComponent
getPreferredFocusedComponent() {
188 return myActionIdEdit
;
192 public String
getActionId() {
193 return myActionIdEdit
.getText();
196 public String
getActionName() {
197 return myActionNameEdit
.getText();
201 public String
getActionText() {
202 return myActionTextEdit
.getText();
205 public String
getActionDescription() {
206 return myActionDescriptionEdit
.getText();
210 public String
getSelectedGroupId() {
211 ActionGroup group
= (ActionGroup
) myGroupList
.getSelectedValue();
212 return group
== null ?
null : ActionManager
.getInstance().getId(group
);
216 public String
getSelectedActionId() {
217 AnAction action
= (AnAction
) myActionList
.getSelectedValue();
218 return action
== null ?
null : ActionManager
.getInstance().getId(action
);
222 public String
getSelectedAnchor() {
223 ButtonModel selection
= myAnchorButtonGroup
.getSelection();
224 if (selection
== myAnchorFirstRadio
.getModel()) return "first";
225 if (selection
== myAnchorLastRadio
.getModel()) return "last";
226 if (selection
== myAnchorBeforeRadio
.getModel()) return "before";
227 if (selection
== myAnchorAfterRadio
.getModel()) return "after";
231 public String
getFirstKeyStroke() {
232 return getKeystrokeText(myFirstKeystrokeEdit
.getKeyStroke());
235 public String
getSecondKeyStroke() {
236 return getKeystrokeText(mySecondKeystrokeEdit
.getKeyStroke());
239 private static String
getKeystrokeText(KeyStroke keyStroke
) {
240 //noinspection HardCodedStringLiteral
241 return keyStroke
!= null ?
242 keyStroke
.toString().replaceAll("pressed ", "").replaceAll("released ", "") :
246 private void updateControls() {
247 setOKActionEnabled(myActionIdEdit
.getText().length() > 0 &&
248 myActionNameEdit
.getText().length() > 0 &&
249 myActionTextEdit
.getText().length() > 0 &&
250 (!myActionNameEdit
.isEditable() || JavaPsiFacade
.getInstance(myProject
).getNameHelper().isIdentifier(myActionNameEdit
.getText())));
252 myAnchorBeforeRadio
.setEnabled(myActionList
.getSelectedValue() != null);
253 myAnchorAfterRadio
.setEnabled(myActionList
.getSelectedValue() != null);
255 boolean enabled
= myFirstKeystrokeEdit
.getDocument().getLength() > 0;
256 myClearFirstKeystroke
.setEnabled(enabled
);
257 mySecondKeystrokeEdit
.setEnabled(enabled
);
258 myClearSecondKeystroke
.setEnabled(enabled
);
260 enabled
= enabled
&& mySecondKeystrokeEdit
.getDocument().getLength() > 0;
261 myClearSecondKeystroke
.setEnabled(enabled
);
264 private static class MyActionRenderer
extends ColoredListCellRenderer
{
265 protected void customizeCellRenderer(JList list
, Object value
, int index
, boolean selected
, boolean hasFocus
) {
266 AnAction group
= (AnAction
) value
;
267 append(ActionManager
.getInstance().getId(group
), SimpleTextAttributes
.REGULAR_ATTRIBUTES
);
268 final String text
= group
.getTemplatePresentation().getText();
270 append(" (" + text
+ ")", SimpleTextAttributes
.REGULAR_ATTRIBUTES
);
275 private class MyDocumentListener
implements DocumentListener
{
276 public void insertUpdate(DocumentEvent e
) {
280 public void removeUpdate(DocumentEvent e
) {
284 public void changedUpdate(DocumentEvent e
) {
289 private static class ShortcutTextField
extends JTextField
{
290 private KeyStroke myKeyStroke
;
292 public ShortcutTextField() {
293 enableEvents(KeyEvent
.KEY_EVENT_MASK
);
294 setFocusTraversalKeysEnabled(false);
297 protected void processKeyEvent(KeyEvent e
) {
298 if (e
.getID() == KeyEvent
.KEY_PRESSED
) {
299 int keyCode
= e
.getKeyCode();
301 keyCode
== KeyEvent
.VK_SHIFT
||
302 keyCode
== KeyEvent
.VK_ALT
||
303 keyCode
== KeyEvent
.VK_CONTROL
||
304 keyCode
== KeyEvent
.VK_ALT_GRAPH
||
305 keyCode
== KeyEvent
.VK_META
310 setKeyStroke(KeyStroke
.getKeyStroke(keyCode
, e
.getModifiers()));
314 public void setKeyStroke(KeyStroke keyStroke
) {
315 myKeyStroke
= keyStroke
;
316 if (keyStroke
== null) {
320 setText(KeymapUtil
.getKeystrokeText(keyStroke
));
324 public KeyStroke
getKeyStroke() {