IDEA-241893: National keyboard support options

GitOrigin-RevId: 81fa6a32e6cba07a3fcb2ffde0da5295b470c3f1
This commit is contained in:
Denis Konoplev
2020-06-08 19:10:13 +03:00
committed by intellij-monorepo-bot
parent 45ffc1259a
commit 72c73b07df
6 changed files with 146 additions and 201 deletions
@@ -41,7 +41,8 @@ add.keymap.label=A&dd
remove.keymap.label=Remo&ve
unnamed.list.display.name=unnamed
prefer.key.position=Prefer key position over key char with national layout
use.national.layouts.for.shortcuts=Use national layouts for shortcuts
use.us.non.alpha.num.keys=Use US non alpha numerical keys for shortcuts
disable.mnemonic.in.menu.check.box=Disable mnemonics in &menu
add.keyboard.shortcut.button=Add &Keyboard Shortcut...
@@ -1,95 +0,0 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.keymap;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import org.cef.OS;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.im.InputContext;
import java.util.Locale;
/**
* @author Denis Fokin
*/
@State(name = "KeyboardSettings", storages = @Storage("keyboard.xml"))
public class KeyboardSettingsExternalizable implements PersistentStateComponent<KeyboardSettingsExternalizable.OptionSet> {
private static final String [] supportedNonEnglishLanguages = {"de", "fr", "it", "uk"};
public static final String VMOption = "com.sun.awt.use.national.layouts";
public static boolean isSupportedKeyboardLayout(@NotNull Component component) {
String keyboardLayoutLanguage = getLanguageForComponent(component);
for (String language : supportedNonEnglishLanguages) {
if (language.equals(keyboardLayoutLanguage)) {
return true;
}
}
// linux have poor support of locales so lets show this option every on linux system
return OS.isLinux();
}
@Nullable
public static String getLanguageForComponent(@NotNull Component component) {
final Locale locale = getLocaleForComponent(component);
return locale == null ? null : locale.getLanguage();
}
@Nullable
protected static Locale getLocaleForComponent(@NotNull Component component) {
final InputContext context = component.getInputContext();
return context == null ? null : context.getLocale();
}
@Nullable
public static String getDisplayLanguageNameForComponent(@NotNull Component component) {
final Locale locale = getLocaleForComponent(component);
return locale == null ? null : locale.getDisplayLanguage();
}
public static final class OptionSet {
public boolean PREFER_KEY_POSITION_OVER_CHAR_OPTION
= "true".equals(System.getProperty("com.jetbrains.use.old.keyevent.processing"));
}
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(@NotNull OptionSet state) {
state.PREFER_KEY_POSITION_OVER_CHAR_OPTION
= state.PREFER_KEY_POSITION_OVER_CHAR_OPTION
|| "true".equals(System.getProperty("com.jetbrains.use.old.keyevent.processing"));
myOptions = state;
}
public boolean isPreferKeyPositionOverCharOption () {
return myOptions.PREFER_KEY_POSITION_OVER_CHAR_OPTION;
}
public void setPreferKeyPositionOverCharOption (boolean enabled) {
myOptions.PREFER_KEY_POSITION_OVER_CHAR_OPTION = enabled;
}
}
@@ -0,0 +1,123 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.keymap;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.im.InputContext;
import java.util.Locale;
@State(name = "KeyboardSettings", storages = @Storage("keyboard.xml"))
public class NationalKeyboardSupport implements PersistentStateComponent<NationalKeyboardSupport.OptionSet> {
private static final String[] MAC_SUPPORTED_LOCALES = {"de", "fr", "it", "no"};
private static final String[] WIN_SUPPORTED_LOCALES = {"be", "ru", "uk", "bg", "sr"};
public static final String VMOption = getVMOption();
public static boolean isSupportedKeyboardLayout(@NotNull Component component) {
if (SystemInfo.isLinux) {
return true;
}
String[] supportedNonEnglishLanguages;
if (SystemInfo.isMac) {
supportedNonEnglishLanguages = MAC_SUPPORTED_LOCALES;
}
else if (SystemInfo.isWindows) {
supportedNonEnglishLanguages = WIN_SUPPORTED_LOCALES;
}
else {
return false;
}
String keyboardLayoutLanguage = getLanguageForComponent(component);
for (String language : supportedNonEnglishLanguages) {
if (language.equals(keyboardLayoutLanguage)) {
return true;
}
}
return false;
}
public static @NotNull String getVMOption() {
if (SystemInfo.isMac || SystemInfo.isLinux) {
return "com.sun.awt.use.national.layouts";
}
return "com.sun.awt.useLatinNonAlphaNumKeycodes";
}
public static @NotNull String getKeymapBundleKey() {
if (SystemInfo.isMac || SystemInfo.isLinux) {
return "use.national.layouts.for.shortcuts";
}
return "use.us.non.alpha.num.keys";
}
@Nullable
public static String getLanguageForComponent(@NotNull Component component) {
final Locale locale = getLocaleForComponent(component);
return locale == null ? null : locale.getLanguage();
}
@Nullable
protected static Locale getLocaleForComponent(@NotNull Component component) {
final InputContext context = component.getInputContext();
return context == null ? null : context.getLocale();
}
public static final class OptionSet {
public boolean enabled = "true".equals(System.getProperty(VMOption));
}
private OptionSet myOptions = new OptionSet();
public static NationalKeyboardSupport getInstance() {
if (ApplicationManager.getApplication().isDisposed()) {
return new NationalKeyboardSupport();
}
else {
return ServiceManager.getService(NationalKeyboardSupport.class);
}
}
@Nullable
@Override
public OptionSet getState() {
return myOptions;
}
@Override
public void loadState(@NotNull OptionSet state) {
state.enabled
= state.enabled || "true".equals(System.getProperty(VMOption));
myOptions = state;
}
@Override
public void noStateLoaded() {
// on MacOS national keymap support is turned on by default
if (SystemInfo.isMac) {
myOptions.enabled = "true".equals(System.getProperty(VMOption, "true"));
}
}
public boolean getEnabled() {
return myOptions.enabled;
}
public void setEnabled(boolean enabled) {
myOptions.enabled = enabled;
}
}
@@ -1,86 +0,0 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.editor.impl;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationsConfiguration;
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 javax.swing.event.HyperlinkEvent;
/**
* @author Denis Fokin
*/
public final class KeyboardInternationalizationNotificationManager {
public static final String LOCALIZATION_GROUP_DISPLAY_ID = "Localization and Internationalization";
public static boolean notificationHasBeenShown;
private KeyboardInternationalizationNotificationManager() {
}
/* public static void showNotification() {
Window mostRecentFocusedWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
if (notificationHasBeenShown || (mostRecentFocusedWindow != null && !KeyboardSettingsExternalizable.isSupportedKeyboardLayout(mostRecentFocusedWindow))) 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) {
Window recentFocusedWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
if (recentFocusedWindow == null) {
recentFocusedWindow = Window.getWindows()[0];
}
final String productName = ApplicationNamesInfo.getInstance().getProductName();
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 internationalization for " + productName + ".";
return new Notification(groupDisplayId, title,
text,
NotificationType.INFORMATION,
listener);
}*/
private static class MyNotificationListener implements NotificationListener {
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().setPreferKeyPositionOverCharOption(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();
}
}
}
}
@@ -68,7 +68,7 @@ import java.util.Map;
import static com.intellij.openapi.actionSystem.impl.ActionToolbarImpl.updateAllToolbarsImmediately;
public class KeymapPanel extends JPanel implements SearchableConfigurable, Configurable.NoScroll, KeymapListener, Disposable {
private JCheckBox preferKeyPositionOverCharOption;
private JCheckBox nationalKeyboardsSupport;
private final KeymapSelector myKeymapSelector = new KeymapSelector(this::currentKeymapChanged);
private final KeymapSchemeManager myManager = myKeymapSelector.getManager();
@@ -96,21 +96,23 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
keymapPanel.add(createKeymapSettingsPanel(), BorderLayout.CENTER);
IdeFrame ideFrame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
if (ideFrame != null && KeyboardSettingsExternalizable.isSupportedKeyboardLayout(ideFrame.getComponent())) {
preferKeyPositionOverCharOption = new JCheckBox(new AbstractAction(KeyMapBundle.message("prefer.key.position")) {
@Override
public void actionPerformed(ActionEvent e) {
KeyboardSettingsExternalizable.getInstance().setPreferKeyPositionOverCharOption(preferKeyPositionOverCharOption.isSelected());
VMOptions.writeOption(KeyboardSettingsExternalizable.VMOption, "=",
Boolean.toString(!KeyboardSettingsExternalizable.getInstance().isPreferKeyPositionOverCharOption()));
ApplicationManager.getApplication().invokeLater(
() -> ApplicationManager.getApplication().restart(),
ModalityState.NON_MODAL
);
}
});
preferKeyPositionOverCharOption.setBorder(JBUI.Borders.empty());
keymapPanel.add(preferKeyPositionOverCharOption, BorderLayout.SOUTH);
if (ideFrame != null && NationalKeyboardSupport.isSupportedKeyboardLayout(ideFrame.getComponent())) {
nationalKeyboardsSupport = new JCheckBox(
new AbstractAction(KeyMapBundle.message(NationalKeyboardSupport.getKeymapBundleKey())) {
@Override
public void actionPerformed(ActionEvent e) {
NationalKeyboardSupport.getInstance().setEnabled(nationalKeyboardsSupport.isSelected());
VMOptions.writeOption(NationalKeyboardSupport.getVMOption(), "=",
Boolean.toString(NationalKeyboardSupport.getInstance().getEnabled()));
ApplicationManager.getApplication().invokeLater(
() -> ApplicationManager.getApplication().restart(),
ModalityState.NON_MODAL
);
}
});
nationalKeyboardsSupport.setSelected(NationalKeyboardSupport.getInstance().getEnabled());
nationalKeyboardsSupport.setBorder(JBUI.Borders.empty());
keymapPanel.add(nationalKeyboardsSupport, BorderLayout.SOUTH);
}
add(keymapPanel, BorderLayout.CENTER);
@@ -555,8 +557,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
@Override
public void reset() {
if (preferKeyPositionOverCharOption != null) {
preferKeyPositionOverCharOption.setSelected(KeyboardSettingsExternalizable.getInstance().isPreferKeyPositionOverCharOption());
if (nationalKeyboardsSupport != null) {
nationalKeyboardsSupport.setSelected(NationalKeyboardSupport.getInstance().getEnabled());
}
myManager.reset();
}
@@ -543,7 +543,7 @@
/>
<applicationService serviceImplementation="com.intellij.codeInsight.hints.settings.ParameterNameHintsSettings"/>
<applicationService serviceImplementation="com.intellij.openapi.keymap.KeyboardSettingsExternalizable"/>
<applicationService serviceImplementation="com.intellij.openapi.keymap.NationalKeyboardSupport"/>
<applicationService serviceImplementation="com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider"/>
<scopeParserExtension implementation="com.intellij.psi.search.scope.packageSet.FilePackageSetParserExtension"/>