blob: 92db22ea1f48e79f4f64ecd49584624ff9d70d02 [file] [log] [blame]
/*
* Copyright 2000-2014 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 com.intellij.openapi.keymap.impl.ui;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.MouseShortcut;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.keymap.KeyMapBundle;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.keymap.impl.ShortcutRestrictions;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.JBColor;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* @author Vladimir Kondratyev
*/
class MouseShortcutDialog extends DialogWrapper{
private final Keymap myKeymap;
private final String myActionId;
private final Group myMainGroup;
private final JRadioButton myRbSingleClick;
private final JRadioButton myRbDoubleClick;
private final JLabel myLblPreview;
private final MyClickPad myClickPad;
private final JTextArea myTarConflicts;
private int myButton;
@JdkConstants.InputEventMask private int myModifiers;
/**
* @param shortcut dialog will be initialized with this <code>shortcut</code>. It can be <code>null</code>
* if dialog is used to create new mouse shortcut.
*/
public MouseShortcutDialog(
JComponent parentComponent,
MouseShortcut shortcut,
@NotNull Keymap keymap,
@NotNull String actiondId,
@NotNull Group mainGroup,
@NotNull ShortcutRestrictions restrictions
){
super(parentComponent,true);
setTitle(KeyMapBundle.message("mouse.shortcut.dialog.title"));
myKeymap=keymap;
myActionId=actiondId;
myMainGroup=mainGroup;
myRbSingleClick=new JRadioButton(KeyMapBundle.message("mouse.shortcut.dialog.single.click.radio"));
myRbDoubleClick=new JRadioButton(KeyMapBundle.message("mouse.shortcut.dialog.double.click.radio"));
ButtonGroup buttonGroup=new ButtonGroup();
buttonGroup.add(myRbSingleClick);
buttonGroup.add(myRbDoubleClick);
myLblPreview=new JLabel(" ");
myClickPad=new MyClickPad();
myTarConflicts=new JTextArea();
myTarConflicts.setFocusable(false);
myTarConflicts.setEditable(false);
myTarConflicts.setBackground(UIUtil.getPanelBackground());
myTarConflicts.setLineWrap(true);
myTarConflicts.setWrapStyleWord(true);
if(shortcut!=null){
if(shortcut.getClickCount()==1){
myRbSingleClick.setSelected(true);
}else{
myRbDoubleClick.setSelected(true);
}
myButton=shortcut.getButton();
myModifiers=shortcut.getModifiers();
}else{
myRbSingleClick.setSelected(true);
myButton=-1;
myModifiers=-1;
}
myRbDoubleClick.setEnabled(restrictions.allowMouseDoubleClick);
updatePreviewAndConflicts();
init();
}
/**
* @return created/edited shortcut. Returns <code>null</code> if shortcut is invalid.
*/
public MouseShortcut getMouseShortcut(){
if (myButton > 3 && getClickCount() == 2) {
return null;
}
if(myButton!=-1 && myModifiers!=-1){
return new MouseShortcut(myButton,myModifiers,getClickCount());
}else{
return null;
}
}
@Override
protected String getHelpId() {
return "preferences.mouse.shortcut";
}
protected JComponent createCenterPanel(){
JPanel panel=new JPanel(new GridBagLayout());
// Single/Double click
JPanel clickCountPanel=new JPanel(new GridBagLayout());
clickCountPanel.setBorder(IdeBorderFactory.createTitledBorder(
KeyMapBundle.message("mouse.shortcut.dialog.click.count.border"), true));
panel.add(
clickCountPanel,
new GridBagConstraints(0,0,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,new Insets(0,0,0,0),0,0)
);
clickCountPanel.add(
myRbSingleClick,
new GridBagConstraints(0,0,1,1,1,0,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(0,0,0,10),0,0)
);
clickCountPanel.add(
myRbDoubleClick,
new GridBagConstraints(1,0,1,1,1,0,GridBagConstraints.EAST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0)
);
ActionListener listener=new ActionListener(){
public void actionPerformed(ActionEvent e){
updatePreviewAndConflicts();
}
};
myRbSingleClick.addActionListener(listener);
myRbDoubleClick.addActionListener(listener);
// Click pad
JPanel clickPadPanel=new JPanel(new BorderLayout());
panel.add(
clickPadPanel,
new GridBagConstraints(0,1,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,4,0),0,0)
);
clickPadPanel.setBorder(IdeBorderFactory.createTitledBorder(
KeyMapBundle.message("mouse.shortcut.dialog.click.pad.border"), true));
myClickPad.setPreferredSize(new Dimension(260,60));
clickPadPanel.add(myClickPad,BorderLayout.CENTER);
// Shortcut preview
JPanel previewPanel=new JPanel(new GridBagLayout());
previewPanel.setBorder(IdeBorderFactory.createTitledBorder(
KeyMapBundle.message("mouse.shortcut.dialog.shortcut.preview.border"), true));
panel.add(
previewPanel,
new GridBagConstraints(0,2,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,4,0),0,0)
);
previewPanel.add(
myLblPreview,
new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(2,2,2,2),0,0)
);
// Conflicts panel
JPanel conflictsPanel=new JPanel(new GridBagLayout());
conflictsPanel.setBorder(IdeBorderFactory.createTitledBorder(
KeyMapBundle.message("mouse.shortcut.dialog.conflicts.border"), true));
panel.add(
conflictsPanel,
new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)
);
myTarConflicts.setPreferredSize(new Dimension(260,60));
JScrollPane scrollPane= ScrollPaneFactory.createScrollPane(myTarConflicts);
scrollPane.setBorder(null);
conflictsPanel.add(
scrollPane,
new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0)
);
return panel;
}
private int getClickCount() {
return myRbSingleClick.isSelected() ? 1 : 2;
}
/**
* Updates all UI controls
*/
private void updatePreviewAndConflicts(){
if(myButton==-1||myModifiers==-1){
return;
}
myTarConflicts.setText(null);
// Set text into preview area
// empty string should have same height
myLblPreview.setText(KeymapUtil.getMouseShortcutText(myButton,myModifiers,getClickCount()) + " ");
// Detect conflicts
final MouseShortcut mouseShortcut=new MouseShortcut(myButton,myModifiers,getClickCount());
if (myButton > 3 && getClickCount() == 2) {
myTarConflicts.setForeground(JBColor.RED);
myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.side.buttons.with.double.click", myButton));
return;
}
StringBuilder buffer = new StringBuilder();
String[] actionIds = myKeymap.getActionIds(mouseShortcut);
for (String actionId : actionIds) {
if (actionId.equals(myActionId)) {
continue;
}
String actionPath = myMainGroup.getActionQualifiedPath(actionId);
// actionPath == null for editor actions having corresponding $-actions
if (actionPath == null) {
continue;
}
Shortcut[] shortcuts = myKeymap.getShortcuts(actionId);
for (Shortcut shortcut1 : shortcuts) {
if (!(shortcut1 instanceof MouseShortcut)) {
continue;
}
MouseShortcut shortcut = (MouseShortcut)shortcut1;
if (shortcut.getButton() != mouseShortcut.getButton() || shortcut.getModifiers() != mouseShortcut.getModifiers()) {
continue;
}
if (buffer.length() > 1) {
buffer.append('\n');
}
buffer.append('[');
buffer.append(actionPath);
buffer.append(']');
break;
}
}
if (buffer.length() == 0) {
myTarConflicts.setForeground(UIUtil.getTextAreaForeground());
myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.no.conflicts.area"));
}
else {
myTarConflicts.setForeground(JBColor.RED);
myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.assigned.to.area", buffer.toString()));
}
}
private class MyClickPad extends JLabel{
public MyClickPad(){
super(
KeyMapBundle.message("mouse.shortcut.label"),
AllIcons.General.Mouse, SwingConstants.CENTER
);
// It's very imporatant that MouseListener is added to the Dialog. If you add
// the same listener, for example, into the MyClickPad component you get fake
// Alt and Meta modifiers. I means that pressing of middle button causes
// Alt+Button2 event.
// See bug ID 4109826 on Sun's bug parade.
//cast is needed in order to compile with mustang
MouseShortcutDialog.this.addMouseListener((MouseListener)new MouseAdapter(){
public void mouseReleased(MouseEvent e){
Component component= SwingUtilities.getDeepestComponentAt(e.getComponent(),e.getX(),e.getY());
if(component== MyClickPad.this){
e.consume();
myButton=e.getButton();
myModifiers=e.getModifiersEx();
updatePreviewAndConflicts();
}
}
});
}
}
}