blob: 779929ceb8184565e000ee44793a3fe3c2b53159 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.devkit.actions;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiNameHelper;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ListSpeedSearch;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.DevKitBundle;
import org.jetbrains.idea.devkit.util.ActionData;
import org.jetbrains.idea.devkit.util.ActionType;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author yole
*/
public class NewActionDialog extends DialogWrapper implements ActionData {
private JPanel myRootPanel;
private JList myGroupList;
private JList myActionList;
private JTextField myActionNameEdit;
private JTextField myActionIdEdit;
private JTextField myActionTextEdit;
private JTextField myActionDescriptionEdit;
private JRadioButton myAnchorFirstRadio;
private JRadioButton myAnchorLastRadio;
private JRadioButton myAnchorBeforeRadio;
private JRadioButton myAnchorAfterRadio;
private JPanel myShortcutPanel;
private JPanel myFirstKeystrokeEditPlaceholder;
private JPanel mySecondKeystrokeEditPlaceholder;
private JButton myClearFirstKeystroke;
private JButton myClearSecondKeystroke;
private ShortcutTextField myFirstKeystrokeEdit;
private ShortcutTextField mySecondKeystrokeEdit;
private TextFieldWithBrowseButton myIconEdit;
private Project myProject;
private ButtonGroup myAnchorButtonGroup;
public NewActionDialog(PsiClass actionClass) {
this(actionClass.getProject());
myActionNameEdit.setText(actionClass.getQualifiedName());
myActionNameEdit.setEditable(false);
myActionIdEdit.setText(actionClass.getQualifiedName());
if (ActionType.GROUP.isOfType(actionClass)) {
myShortcutPanel.setVisible(false);
}
}
protected NewActionDialog(final Project project) {
super(project, false);
myProject = project;
init();
setTitle(DevKitBundle.message("new.action.dialog.title"));
final ActionManager actionManager = ActionManager.getInstance();
final String[] actionIds = actionManager.getActionIds("");
Arrays.sort(actionIds);
final List<ActionGroup> actionGroups = new ArrayList<ActionGroup>();
for(String actionId: actionIds) {
if (actionManager.isGroup(actionId)) {
final AnAction anAction = actionManager.getAction(actionId);
if (anAction instanceof DefaultActionGroup) {
actionGroups.add((ActionGroup) anAction);
}
}
}
myGroupList.setListData(actionGroups.toArray());
myGroupList.setCellRenderer(new MyActionRenderer());
myGroupList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ActionGroup group = (ActionGroup) myGroupList.getSelectedValue();
if (group == null) {
myActionList.setListData(ArrayUtil.EMPTY_OBJECT_ARRAY);
}
else {
final AnAction[] actions = group.getChildren(null);
// filter out actions that don't have IDs - they can't be used for anchoring in plugin.xml
List<AnAction> realActions = new ArrayList<AnAction>();
for(AnAction action: actions) {
if (actionManager.getId(action) != null) {
realActions.add(action);
}
}
myActionList.setListData(realActions.toArray());
}
}
});
new ListSpeedSearch(myGroupList, new Function<Object, String>() {
public String fun(final Object o) {
return ActionManager.getInstance().getId((AnAction) o);
}
});
myActionList.setCellRenderer(new MyActionRenderer());
myActionList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
updateControls();
}
});
final MyDocumentListener listener = new MyDocumentListener();
myActionIdEdit.getDocument().addDocumentListener(listener);
myActionNameEdit.getDocument().addDocumentListener(listener);
myActionTextEdit.getDocument().addDocumentListener(listener);
myAnchorButtonGroup.setSelected(myAnchorFirstRadio.getModel(), true);
myFirstKeystrokeEdit = new ShortcutTextField();
myFirstKeystrokeEditPlaceholder.setLayout(new BorderLayout());
myFirstKeystrokeEditPlaceholder.add(myFirstKeystrokeEdit, BorderLayout.CENTER);
myClearFirstKeystroke.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myFirstKeystrokeEdit.setKeyStroke(null);
}
});
myFirstKeystrokeEdit.getDocument().addDocumentListener(listener);
myClearFirstKeystroke.setText(null);
final Icon icon = AllIcons.Actions.Cancel;
final Dimension size = new Dimension(icon.getIconWidth(), icon.getIconHeight());
myClearFirstKeystroke.setIcon(icon);
myClearFirstKeystroke.setPreferredSize(size);
myClearFirstKeystroke.setMaximumSize(size);
mySecondKeystrokeEdit = new ShortcutTextField();
mySecondKeystrokeEditPlaceholder.setLayout(new BorderLayout());
mySecondKeystrokeEditPlaceholder.add(mySecondKeystrokeEdit, BorderLayout.CENTER);
myClearSecondKeystroke.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mySecondKeystrokeEdit.setKeyStroke(null);
}
});
mySecondKeystrokeEdit.getDocument().addDocumentListener(listener);
myClearSecondKeystroke.setText(null);
myClearSecondKeystroke.setIcon(icon);
myClearSecondKeystroke.setPreferredSize(size);
myClearSecondKeystroke.setMaximumSize(size);
updateControls();
}
protected JComponent createCenterPanel() {
return myRootPanel;
}
@Override public JComponent getPreferredFocusedComponent() {
return myActionIdEdit;
}
@NotNull
public String getActionId() {
return myActionIdEdit.getText();
}
public String getActionName() {
return myActionNameEdit.getText();
}
@NotNull
public String getActionText() {
return myActionTextEdit.getText();
}
public String getActionDescription() {
return myActionDescriptionEdit.getText();
}
@Nullable
public String getSelectedGroupId() {
ActionGroup group = (ActionGroup) myGroupList.getSelectedValue();
return group == null ? null : ActionManager.getInstance().getId(group);
}
@Nullable
public String getSelectedActionId() {
AnAction action = (AnAction) myActionList.getSelectedValue();
return action == null ? null : ActionManager.getInstance().getId(action);
}
@NonNls
public String getSelectedAnchor() {
ButtonModel selection = myAnchorButtonGroup.getSelection();
if (selection == myAnchorFirstRadio.getModel()) return "first";
if (selection == myAnchorLastRadio.getModel()) return "last";
if (selection == myAnchorBeforeRadio.getModel()) return "before";
if (selection == myAnchorAfterRadio.getModel()) return "after";
return null;
}
public String getFirstKeyStroke() {
return getKeystrokeText(myFirstKeystrokeEdit.getKeyStroke());
}
public String getSecondKeyStroke() {
return getKeystrokeText(mySecondKeystrokeEdit.getKeyStroke());
}
private static String getKeystrokeText(KeyStroke keyStroke) {
//noinspection HardCodedStringLiteral
return keyStroke != null ?
keyStroke.toString().replaceAll("pressed ", "").replaceAll("released ", "") :
null;
}
private void updateControls() {
setOKActionEnabled(myActionIdEdit.getText().length() > 0 &&
myActionNameEdit.getText().length() > 0 &&
myActionTextEdit.getText().length() > 0 &&
(!myActionNameEdit.isEditable() || PsiNameHelper.getInstance(myProject).isIdentifier(myActionNameEdit.getText())));
myAnchorBeforeRadio.setEnabled(myActionList.getSelectedValue() != null);
myAnchorAfterRadio.setEnabled(myActionList.getSelectedValue() != null);
boolean enabled = myFirstKeystrokeEdit.getDocument().getLength() > 0;
myClearFirstKeystroke.setEnabled(enabled);
mySecondKeystrokeEdit.setEnabled(enabled);
myClearSecondKeystroke.setEnabled(enabled);
enabled = enabled && mySecondKeystrokeEdit.getDocument().getLength() > 0;
myClearSecondKeystroke.setEnabled(enabled);
}
private static class MyActionRenderer extends ColoredListCellRenderer {
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
AnAction group = (AnAction) value;
append(ActionManager.getInstance().getId(group), SimpleTextAttributes.REGULAR_ATTRIBUTES);
final String text = group.getTemplatePresentation().getText();
if (text != null) {
append(" (" + text + ")", SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
}
private class MyDocumentListener implements DocumentListener {
public void insertUpdate(DocumentEvent e) {
updateControls();
}
public void removeUpdate(DocumentEvent e) {
updateControls();
}
public void changedUpdate(DocumentEvent e) {
updateControls();
}
}
private static class ShortcutTextField extends JTextField {
private KeyStroke myKeyStroke;
public ShortcutTextField() {
enableEvents(AWTEvent.KEY_EVENT_MASK);
setFocusTraversalKeysEnabled(false);
}
protected void processKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
int keyCode = e.getKeyCode();
if (
keyCode == KeyEvent.VK_SHIFT ||
keyCode == KeyEvent.VK_ALT ||
keyCode == KeyEvent.VK_CONTROL ||
keyCode == KeyEvent.VK_ALT_GRAPH ||
keyCode == KeyEvent.VK_META
){
return;
}
setKeyStroke(KeyStroke.getKeyStroke(keyCode, e.getModifiers()));
}
}
public void setKeyStroke(KeyStroke keyStroke) {
myKeyStroke = keyStroke;
if (keyStroke == null) {
setText("");
}
else {
setText(KeymapUtil.getKeystrokeText(keyStroke));
}
}
public KeyStroke getKeyStroke() {
return myKeyStroke;
}
}
@Override
protected String getHelpId() {
return "reference.new.action.dialog";
}
}