IDEA-63779 Keymap shows characters for keys only for english keyboard layout correctly

This commit is contained in:
Denis Fokin
2015-05-13 19:15:39 +04:00
parent 2df9e13506
commit 737faf33e7
7 changed files with 232 additions and 33 deletions
@@ -0,0 +1,89 @@
/*
* Copyright 2000-2015 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;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.sun.istack.internal.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
/**
* @author Denis Fokin
*/
@State(
name = "KeyboardSettings",
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/keyboard.xml")}
)
public class KeyboardSettingsExternalizable implements PersistentStateComponent<KeyboardSettingsExternalizable.OptionSet> {
private static final String [] supportedNonEnglishLanguages = {"de", "fr", "it"};
public static boolean isSupportedKeyboardLayout(@NotNull Component component) {
String keyboardLayoutLanguage = getLanguageForComponent(component);
for (String language : supportedNonEnglishLanguages) {
if (language.equals(keyboardLayoutLanguage)) {
return true;
}
}
return false;
}
public static String getLanguageForComponent(@NotNull Component component) {
return component.getInputContext().getLocale().getLanguage();
}
public static String getDisplayLanguageNameForComponent(@NotNull Component component) {
return component.getInputContext().getLocale().getDisplayLanguage();
}
public static final class OptionSet {
public boolean USE_NON_ENGLISH_KEYBOARD = false;
}
private OptionSet myOptions = new OptionSet();
public static KeyboardSettingsExternalizable getInstance() {
if (ApplicationManager.getApplication().isDisposed()) {
return new KeyboardSettingsExternalizable();
}
else {
return ServiceManager.getService(KeyboardSettingsExternalizable.class);
}
}
@Nullable
@Override
public OptionSet getState() {
return myOptions;
}
@Override
public void loadState(OptionSet state) {
myOptions = state;
}
public boolean isNonEnglishKeyboardSupportEnabled () {
return myOptions.USE_NON_ENGLISH_KEYBOARD;
}
public void setNonEnglishKeyboardSupportEnabled (boolean enabled) {
myOptions.USE_NON_ENGLISH_KEYBOARD = enabled;
}
}
@@ -29,17 +29,16 @@ import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.diagnostic.FrequentEventDetector;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.keymap.KeyboardSettingsExternalizable;
import com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher;
import com.intellij.openapi.keymap.impl.IdeMouseEventDispatcher;
import com.intellij.openapi.keymap.impl.KeyState;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.ExpirableRunnable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.util.Alarm;
import com.intellij.util.ReflectionUtil;
@@ -411,7 +410,7 @@ public class IdeEventQueue extends EventQueue {
//private static boolean altGrIsPressed = false;
private static AWTEvent fixNonEnglishKeyboardLayouts(AWTEvent e) {
if (!Registry.is("ide.non.english.keyboard.layout.fix")) return e;
if (!KeyboardSettingsExternalizable.getInstance().isNonEnglishKeyboardSupportEnabled()) return e;
if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent)e;
@@ -875,6 +875,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
private static boolean firstCharTyped = true;
private void initComponent() {
myPanel.setLayout(new BorderLayout());
@@ -930,6 +932,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
myEditorComponent.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() >= KeyEvent.VK_A && e.getKeyCode() <= KeyEvent.VK_Z) {
myCharKeyPressed = true;
}
KeyboardInternationalizationNotificationManager.showNotification();
}
@Override
public void keyTyped(@NotNull KeyEvent event) {
myNeedToSelectPreviousChar = false;
@@ -941,13 +951,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() >= KeyEvent.VK_A && e.getKeyCode() <= KeyEvent.VK_Z) {
myCharKeyPressed = true;
}
}
@Override
public void keyReleased(KeyEvent e) {
myCharKeyPressed = false;
@@ -0,0 +1,95 @@
/*
* Copyright 2000-2015 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.editor.impl;
import com.intellij.notification.*;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.keymap.KeyboardSettingsExternalizable;
import com.intellij.openapi.keymap.impl.ui.KeymapPanel;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.awt.*;
/**
* @author Denis Fokin
*/
public class KeyboardInternationalizationNotificationManager {
public static final String LOCALIZATION_GROUP_DISPLAY_ID = "Localization and Internationalization";
public static boolean notificationHasBeenShown;
private KeyboardInternationalizationNotificationManager() {
}
public static void showNotification() {
if (notificationHasBeenShown || !KeyboardSettingsExternalizable.isSupportedKeyboardLayout(WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow())) return;
MyNotificationListener listener =
new MyNotificationListener();
Notifications.Bus.notify(createNotification(LOCALIZATION_GROUP_DISPLAY_ID, listener));
notificationHasBeenShown = true;
}
public static Notification createNotification(@NotNull final String groupDisplayId, @Nullable NotificationListener listener) {
final String productName = ApplicationNamesInfo.getInstance().getProductName();
Window recentFocusedWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
String text =
"<html>We have found out that you are using a non-english keyboard layout. You can <a href='enable'>enable</a> smart layout support for " +
KeyboardSettingsExternalizable.getDisplayLanguageNameForComponent(recentFocusedWindow) + " language." +
"You can change this option in the settings of " + productName + " <a href='settings'>more...</a></html>";
String title = "Enable smart keyboard internalization for " + productName + ".";
return new Notification(groupDisplayId, title,
text,
NotificationType.INFORMATION,
listener);
}
private static class MyNotificationListener implements NotificationListener {
public MyNotificationListener() {
}
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
final String description = event.getDescription();
if ("enable".equals(description)) {
KeyboardSettingsExternalizable.getInstance().setNonEnglishKeyboardSupportEnabled(true);
}
else if ("settings".equals(description)) {
final ShowSettingsUtil util = ShowSettingsUtil.getInstance();
IdeFrame ideFrame = WindowManagerEx.getInstanceEx().findFrameFor(null);
//util.editConfigurable((JFrame)ideFrame, new StatisticsConfigurable(true));
util.showSettingsDialog(ideFrame.getProject(), KeymapPanel.class);
}
NotificationsConfiguration.getNotificationsConfiguration().changeSettings(LOCALIZATION_GROUP_DISPLAY_ID, NotificationDisplayType.NONE, false, false);
notification.expire();
}
}
}
}
@@ -26,10 +26,7 @@ import com.intellij.openapi.actionSystem.ex.QuickList;
import com.intellij.openapi.actionSystem.ex.QuickListsManager;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.keymap.KeyMapBundle;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.keymap.*;
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
import com.intellij.openapi.keymap.impl.ActionShortcutRestrictions;
import com.intellij.openapi.keymap.impl.KeymapImpl;
@@ -52,6 +49,9 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.impl.IdeFocusManagerImpl;
import com.intellij.packageDependencies.ui.TreeExpansionMonitor;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.DoubleClickListener;
@@ -91,6 +91,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
private JButton myCopyButton;
private JButton myDeleteButton;
private JButton myResetToDefault;
private JCheckBox myNonEnglishKeyboardSupportOption;
private JLabel myBaseKeymapLabel;
@@ -233,7 +234,12 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
final JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
panel.setLayout(new GridBagLayout());
myCopyButton = new JButton(KeyMapBundle.message("copy.keymap.button"));
myCopyButton = new JButton(new AbstractAction(KeyMapBundle.message("copy.keymap.button")) {
@Override
public void actionPerformed(ActionEvent e) {
copyKeymap();
}
});
Insets insets = new Insets(2, 2, 2, 2);
myCopyButton.setMargin(insets);
final GridBagConstraints gc = new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0);
@@ -241,19 +247,28 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
myResetToDefault = new JButton(CommonBundle.message("button.reset"));
myResetToDefault.setMargin(insets);
panel.add(myResetToDefault, gc);
myDeleteButton = new JButton(KeyMapBundle.message("delete.keymap.button"));
myDeleteButton = new JButton(new AbstractAction(KeyMapBundle.message("delete.keymap.button")) {
@Override
public void actionPerformed(ActionEvent e) {
deleteKeymap();
}
});
myDeleteButton.setMargin(insets);
gc.weightx = 1;
panel.add(myDeleteButton, gc);
myCopyButton.addActionListener(
new ActionListener() {
IdeFrame ideFrame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
if (ideFrame != null && KeyboardSettingsExternalizable.isSupportedKeyboardLayout( ideFrame.getComponent()))
{
String displayLanguage = ideFrame.getComponent().getInputContext().getLocale().getDisplayLanguage();
myNonEnglishKeyboardSupportOption = new JCheckBox(new AbstractAction(displayLanguage + " " + KeyMapBundle.message("use.non.english.keyboard.layout.support")) {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
copyKeymap();
public void actionPerformed(ActionEvent e) {
KeyboardSettingsExternalizable.getInstance().setNonEnglishKeyboardSupportEnabled(myNonEnglishKeyboardSupportOption.isSelected());
}
}
);
});
myNonEnglishKeyboardSupportOption.setSelected(KeyboardSettingsExternalizable.getInstance().isNonEnglishKeyboardSupportEnabled());
panel.add(myNonEnglishKeyboardSupportOption, gc);
}
myResetToDefault.addActionListener(new ActionListener() {
@Override
@@ -262,16 +277,6 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
}
});
myDeleteButton.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
deleteKeymap();
}
}
);
return panel;
}
@@ -790,6 +795,12 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
@Override
public void reset() {
if (myNonEnglishKeyboardSupportOption != null) {
KeyboardSettingsExternalizable.getInstance().setNonEnglishKeyboardSupportEnabled(false);
myNonEnglishKeyboardSupportOption.setSelected(KeyboardSettingsExternalizable.getInstance().isNonEnglishKeyboardSupportEnabled());
}
myKeymapListModel.removeAllElements();
KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx();
Keymap[] keymaps = keymapManager.getAllKeymaps();
@@ -46,6 +46,7 @@ remove.keymap.label=Remo&ve
unnamed.list.display.name=unnamed
copy.keymap.button=&Copy
delete.keymap.button=De&lete
use.non.english.keyboard.layout.support=la&yout support
parent.keymap.label=Parent keymap:
disable.mnemonic.in.menu.check.box=Disable mnemonics in &menu
@@ -292,6 +292,7 @@
serviceImplementation="com.intellij.openapi.actionSystem.impl.AbbreviationManagerImpl"/>
<applicationService serviceImplementation="com.intellij.openapi.editor.ex.EditorSettingsExternalizable"/>
<applicationService serviceImplementation="com.intellij.openapi.keymap.KeyboardSettingsExternalizable"/>
<applicationService serviceImplementation="com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider"/>
<scopeParserExtension implementation="com.intellij.psi.search.scope.packageSet.FilePackageSetParserExtension"/>