mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ui: remove SwitchManager
* it is a dead code * even while disabled, it registers actions and sets their shortcuts in runtime (making impossible removing these shortcuts in Keymap)
This commit is contained in:
committed by
Aleksey Pivovarov
parent
91f0a7f567
commit
66273cebf3
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.ui.switcher;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ApplySwitchAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
Project project = getEventProject(e);
|
||||
if (project == null) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
SwitchManager mgr = SwitchManager.getInstance(project);
|
||||
|
||||
boolean switchActionActive = mgr != null && mgr.isSessionActive();
|
||||
if (switchActionActive && mgr.isSelectionWasMoved()) {
|
||||
e.getPresentation().setEnabled(true);
|
||||
} else {
|
||||
QuickActionProvider quickActionProvider = QuickActionProvider.KEY.getData(e.getDataContext());
|
||||
if (quickActionProvider == null) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
} else {
|
||||
List<AnAction> actions = quickActionProvider.getActions(true);
|
||||
e.getPresentation().setEnabled(actions != null && !actions.isEmpty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
Project project = getEventProject(e);
|
||||
|
||||
SwitchManager switchManager = SwitchManager.getInstance(project);
|
||||
if (switchManager.canApplySwitch()) {
|
||||
switchManager.applySwitch();
|
||||
} else {
|
||||
switchManager.disposeCurrentSession(false);
|
||||
QuickActionManager.getInstance(project).showQuickActions();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* 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.ui.switcher;
|
||||
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.openapi.util.registry.RegistryValueListener;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Set;
|
||||
|
||||
public class QuickAccessSettings {
|
||||
private final Set<Integer> myModifierVks = new THashSet<>();
|
||||
@NonNls public static final String SWITCH_UP = "SwitchUp";
|
||||
@NonNls public static final String SWITCH_DOWN = "SwitchDown";
|
||||
@NonNls public static final String SWITCH_LEFT = "SwitchLeft";
|
||||
@NonNls public static final String SWITCH_RIGHT = "SwitchRight";
|
||||
@NonNls public static final String SWITCH_APPLY = "SwitchApply";
|
||||
private RegistryValue myModifiersValue;
|
||||
|
||||
public QuickAccessSettings() {
|
||||
myModifiersValue = Registry.get("actionSystem.quickAccessModifiers");
|
||||
myModifiersValue.addListener(new RegistryValueListener.Adapter() {
|
||||
@Override
|
||||
public void afterValueChanged(RegistryValue value) {
|
||||
applyModifiersFromRegistry();
|
||||
}
|
||||
}, ApplicationManager.getApplication());
|
||||
|
||||
applyModifiersFromRegistry();
|
||||
}
|
||||
|
||||
Keymap getKeymap() {
|
||||
return KeymapManager.getInstance().getActiveKeymap();
|
||||
}
|
||||
|
||||
void saveModifiersToRegistry(Set<String> codeTexts) {
|
||||
StringBuilder value = new StringBuilder();
|
||||
for (String each : codeTexts) {
|
||||
if (value.length() > 0) {
|
||||
value.append(" ");
|
||||
}
|
||||
value.append(each);
|
||||
}
|
||||
myModifiersValue.setValue(value.toString());
|
||||
}
|
||||
|
||||
private void applyModifiersFromRegistry() {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (app != null && app.isUnitTestMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> vksSet = new THashSet<>();
|
||||
ContainerUtil.addAll(vksSet, getModifierRegistryValue().split(" "));
|
||||
myModifierVks.clear();
|
||||
int mask = getModifierMask(vksSet);
|
||||
myModifierVks.addAll(getModifiersVKs(mask));
|
||||
|
||||
reassignActionShortcut(SWITCH_UP, mask, KeyEvent.VK_UP);
|
||||
reassignActionShortcut(SWITCH_DOWN, mask, KeyEvent.VK_DOWN);
|
||||
reassignActionShortcut(SWITCH_LEFT, mask, KeyEvent.VK_LEFT);
|
||||
reassignActionShortcut(SWITCH_RIGHT, mask, KeyEvent.VK_RIGHT);
|
||||
reassignActionShortcut(SWITCH_APPLY, mask, KeyEvent.VK_ENTER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getModifierRegistryValue() {
|
||||
String value = myModifiersValue.asString().trim();
|
||||
if (value.length() > 0) {
|
||||
return value;
|
||||
}
|
||||
return SystemInfo.isMac ? "control alt" : "shift alt";
|
||||
}
|
||||
|
||||
private void reassignActionShortcut(String actionId, @JdkConstants.InputEventMask int modifiers, int actionCode) {
|
||||
removeShortcuts(actionId);
|
||||
if (modifiers > 0) {
|
||||
getKeymap().addShortcut(actionId, new KeyboardShortcut(KeyStroke.getKeyStroke(actionCode, modifiers), null));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeShortcuts(String actionId) {
|
||||
Shortcut[] shortcuts = getKeymap().getShortcuts(actionId);
|
||||
for (Shortcut each : shortcuts) {
|
||||
if (each instanceof KeyboardShortcut) {
|
||||
getKeymap().removeShortcut(actionId, each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JdkConstants.InputEventMask
|
||||
int getModifierMask(Set<String> codeTexts) {
|
||||
int mask = 0;
|
||||
for (String each : codeTexts) {
|
||||
if ("control".equals(each)) {
|
||||
mask |= InputEvent.CTRL_MASK;
|
||||
}
|
||||
else if ("shift".equals(each)) {
|
||||
mask |= InputEvent.SHIFT_MASK;
|
||||
}
|
||||
else if ("alt".equals(each)) {
|
||||
mask |= InputEvent.ALT_MASK;
|
||||
}
|
||||
else if ("meta".equals(each)) {
|
||||
mask |= InputEvent.META_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Set<Integer> getModifiersVKs(int mask) {
|
||||
Set<Integer> codes = new THashSet<>();
|
||||
if ((mask & InputEvent.SHIFT_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_SHIFT);
|
||||
}
|
||||
if ((mask & InputEvent.CTRL_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_CONTROL);
|
||||
}
|
||||
|
||||
if ((mask & InputEvent.META_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_META);
|
||||
}
|
||||
|
||||
if ((mask & InputEvent.ALT_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_ALT);
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
public static QuickAccessSettings getInstance() {
|
||||
return ApplicationManager.getApplication().getComponent(QuickAccessSettings.class);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return Registry.is("actionSystem.quickAccessEnabled");
|
||||
}
|
||||
|
||||
public Set<Integer> getModiferCodes() {
|
||||
return myModifierVks;
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.ui.switcher;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class QuickActionManager implements ProjectComponent {
|
||||
|
||||
private SwitchProvider myActiveProvider;
|
||||
|
||||
public void projectOpened() {
|
||||
}
|
||||
|
||||
public void projectClosed() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return "QuickActionsManager";
|
||||
}
|
||||
|
||||
public void initComponent() {
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
}
|
||||
|
||||
public static QuickActionManager getInstance(Project project) {
|
||||
return project != null ? project.getComponent(QuickActionManager.class) : null;
|
||||
}
|
||||
|
||||
public void showQuickActions() {
|
||||
if (isActive()) return;
|
||||
|
||||
showActionsPopup();
|
||||
}
|
||||
|
||||
private void showActionsPopup() {
|
||||
DataManager.getInstance().getDataContextFromFocus().doWhenDone(new Consumer<DataContext>() {
|
||||
public void consume(DataContext context) {
|
||||
QuickActionProvider provider = QuickActionProvider.KEY.getData(context);
|
||||
if (provider == null) return;
|
||||
|
||||
List<AnAction> actions = provider.getActions(true);
|
||||
if (actions != null && actions.size() > 0) {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
for (AnAction each : actions) {
|
||||
group.add(each);
|
||||
}
|
||||
|
||||
boolean firstParent = true;
|
||||
Component eachParent = provider.getComponent().getParent();
|
||||
while (eachParent != null) {
|
||||
if (eachParent instanceof QuickActionProvider) {
|
||||
QuickActionProvider eachProvider = (QuickActionProvider)eachParent;
|
||||
if (firstParent) {
|
||||
group.addSeparator();
|
||||
firstParent = false;
|
||||
}
|
||||
List<AnAction> eachActionList = eachProvider.getActions(false);
|
||||
if (eachActionList.size() > 0) {
|
||||
group.add(new Group(eachActionList, eachProvider.getName()));
|
||||
}
|
||||
if (eachProvider.isCycleRoot()) break;
|
||||
|
||||
}
|
||||
eachParent = eachParent.getParent();
|
||||
}
|
||||
|
||||
JBPopupFactory.getInstance()
|
||||
.createActionGroupPopup(null, group, context, JBPopupFactory.ActionSelectionAid.ALPHA_NUMBERING, true,
|
||||
() -> myActiveProvider = null, -1).showInBestPositionFor(context);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private class Group extends DefaultActionGroup implements DumbAware {
|
||||
private String myTitle;
|
||||
|
||||
private Group(List<AnAction> actions, String title) {
|
||||
setPopup(true);
|
||||
for (AnAction each : actions) {
|
||||
add(each);
|
||||
}
|
||||
myTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setText(myTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return myActiveProvider != null;
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* 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.ui.switcher;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import gnu.trove.THashSet;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Set;
|
||||
|
||||
public class SwitchManager {
|
||||
private final Project myProject;
|
||||
private final QuickAccessSettings myQa;
|
||||
|
||||
private SwitchingSession mySession;
|
||||
|
||||
private boolean myWaitingForAutoInitSession;
|
||||
private final Alarm myInitSessionAlarm = new Alarm();
|
||||
private KeyEvent myAutoInitSessionEvent;
|
||||
|
||||
private final Set<SwitchingSession> myFadingAway = new THashSet<>();
|
||||
|
||||
public SwitchManager(@NotNull Project project, QuickAccessSettings quickAccess) {
|
||||
myProject = project;
|
||||
myQa = quickAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* internal use only
|
||||
*/
|
||||
public boolean dispatchKeyEvent(@NotNull KeyEvent e) {
|
||||
if (isSessionActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.getID() != KeyEvent.KEY_PRESSED) {
|
||||
if (myWaitingForAutoInitSession) {
|
||||
cancelWaitingForAutoInit();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myQa.getModiferCodes().contains(e.getKeyCode())) {
|
||||
if (areAllModifiersPressed(e.getModifiers(), myQa.getModiferCodes())) {
|
||||
myWaitingForAutoInitSession = true;
|
||||
myAutoInitSessionEvent = e;
|
||||
Runnable initRunnable = () -> IdeFocusManager.getInstance(myProject).doWhenFocusSettlesDown(() -> {
|
||||
if (myWaitingForAutoInitSession) {
|
||||
tryToInitSessionFromFocus(null, false);
|
||||
}
|
||||
});
|
||||
if (myFadingAway.isEmpty()) {
|
||||
myInitSessionAlarm.addRequest(initRunnable, Registry.intValue("actionSystem.keyGestureHoldTime"));
|
||||
}
|
||||
else {
|
||||
initRunnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myWaitingForAutoInitSession) {
|
||||
cancelWaitingForAutoInit();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private ActionCallback tryToInitSessionFromFocus(@Nullable SwitchTarget preselected, boolean showSpots) {
|
||||
if (isSessionActive()) {
|
||||
return ActionCallback.REJECTED;
|
||||
}
|
||||
|
||||
Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
SwitchProvider provider = SwitchProvider.KEY.getData(DataManager.getInstance().getDataContext(owner));
|
||||
if (provider != null) {
|
||||
return initSession(new SwitchingSession(this, provider, myAutoInitSessionEvent, preselected, showSpots));
|
||||
}
|
||||
|
||||
return ActionCallback.REJECTED;
|
||||
}
|
||||
|
||||
private void cancelWaitingForAutoInit() {
|
||||
myWaitingForAutoInitSession = false;
|
||||
myInitSessionAlarm.cancelAllRequests();
|
||||
}
|
||||
|
||||
public static boolean areAllModifiersPressed(@JdkConstants.InputEventMask int modifiers, Set<Integer> modifierCodes) {
|
||||
int mask = 0;
|
||||
for (Integer each : modifierCodes) {
|
||||
if (each == KeyEvent.VK_SHIFT) {
|
||||
mask |= InputEvent.SHIFT_MASK;
|
||||
}
|
||||
|
||||
if (each == KeyEvent.VK_CONTROL) {
|
||||
mask |= InputEvent.CTRL_MASK;
|
||||
}
|
||||
|
||||
if (each == KeyEvent.VK_META) {
|
||||
mask |= InputEvent.META_MASK;
|
||||
}
|
||||
|
||||
if (each == KeyEvent.VK_ALT) {
|
||||
mask |= InputEvent.ALT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return (modifiers ^ mask) == 0;
|
||||
}
|
||||
|
||||
public static SwitchManager getInstance(Project project) {
|
||||
return project != null ? ServiceManager.getService(project, SwitchManager.class) : null;
|
||||
}
|
||||
|
||||
public SwitchingSession getSession() {
|
||||
return mySession;
|
||||
}
|
||||
|
||||
public ActionCallback initSession(SwitchingSession session) {
|
||||
cancelWaitingForAutoInit();
|
||||
|
||||
disposeCurrentSession(false);
|
||||
mySession = session;
|
||||
return ActionCallback.DONE;
|
||||
}
|
||||
|
||||
public void disposeCurrentSession(boolean fadeAway) {
|
||||
if (mySession != null) {
|
||||
mySession.setFadeaway(fadeAway);
|
||||
Disposer.dispose(mySession);
|
||||
mySession = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSessionActive() {
|
||||
return mySession != null && !mySession.isFinished();
|
||||
}
|
||||
|
||||
public ActionCallback applySwitch() {
|
||||
final ActionCallback result = new ActionCallback();
|
||||
if (isSessionActive()) {
|
||||
final boolean showSpots = mySession.isShowspots();
|
||||
mySession.finish(false).doWhenDone(new Consumer<SwitchTarget>() {
|
||||
@Override
|
||||
public void consume(final SwitchTarget switchTarget) {
|
||||
mySession = null;
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(
|
||||
() -> tryToInitSessionFromFocus(switchTarget, showSpots).doWhenProcessed(result.createSetDoneRunnable()));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
result.setDone();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean canApplySwitch() {
|
||||
return isSessionActive() && mySession.isSelectionWasMoved();
|
||||
}
|
||||
|
||||
public boolean isSelectionWasMoved() {
|
||||
return isSessionActive() && mySession.isSelectionWasMoved();
|
||||
}
|
||||
|
||||
public void addFadingAway(SwitchingSession session) {
|
||||
myFadingAway.add(session);
|
||||
}
|
||||
|
||||
public void removeFadingAway(SwitchingSession session) {
|
||||
myFadingAway.remove(session);
|
||||
}
|
||||
}
|
||||
@@ -1,484 +0,0 @@
|
||||
/*
|
||||
* 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 com.intellij.ui.switcher;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.ui.AbstractPainter;
|
||||
import com.intellij.openapi.ui.GraphicsConfig;
|
||||
import com.intellij.openapi.util.AsyncResult;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.IdeGlassPane;
|
||||
import com.intellij.openapi.wm.IdeGlassPaneUtil;
|
||||
import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
import com.intellij.util.Alarm;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.sqrt;
|
||||
|
||||
public class SwitchingSession implements KeyEventDispatcher, Disposable {
|
||||
|
||||
private SwitchProvider myProvider;
|
||||
private KeyEvent myInitialEvent;
|
||||
private boolean myFinished;
|
||||
private LinkedHashSet<SwitchTarget> myTargets = new LinkedHashSet<>();
|
||||
private IdeGlassPane myGlassPane;
|
||||
|
||||
private Component myRootComponent;
|
||||
|
||||
private SwitchTarget mySelection;
|
||||
private SwitchTarget myStartSelection;
|
||||
|
||||
private boolean mySelectionWasMoved;
|
||||
|
||||
private Alarm myAlarm = new Alarm();
|
||||
private Runnable myAutoApplyRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (myManager.canApplySwitch()) {
|
||||
myManager.applySwitch();
|
||||
}
|
||||
}
|
||||
};
|
||||
private SwitchManager myManager;
|
||||
private Spotlight mySpotlight;
|
||||
|
||||
private boolean myShowspots;
|
||||
private Alarm myShowspotsAlarm;
|
||||
private Runnable myShowspotsRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (!myShowspots) {
|
||||
setShowspots(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean myFadingAway;
|
||||
private Disposable myPainterDisposable = Disposer.newDisposable();
|
||||
|
||||
public SwitchingSession(SwitchManager mgr, SwitchProvider provider, KeyEvent e, @Nullable SwitchTarget preselected, boolean showSpots) {
|
||||
myManager = mgr;
|
||||
myProvider = provider;
|
||||
myInitialEvent = e;
|
||||
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
|
||||
|
||||
|
||||
myTargets.addAll(myProvider.getTargets(true, true));
|
||||
|
||||
Component eachParent = myProvider.getComponent();
|
||||
eachParent = eachParent.getParent();
|
||||
while (eachParent != null) {
|
||||
if (eachParent instanceof SwitchProvider) {
|
||||
SwitchProvider eachProvider = (SwitchProvider)eachParent;
|
||||
myTargets.addAll(eachProvider.getTargets(true, false));
|
||||
if (eachProvider.isCycleRoot()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eachParent = eachParent.getParent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (myTargets.size() == 0) {
|
||||
Disposer.dispose(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mySelection = myProvider.getCurrentTarget();
|
||||
if (myTargets.contains(preselected)) {
|
||||
mySelection = preselected;
|
||||
}
|
||||
|
||||
myStartSelection = mySelection;
|
||||
|
||||
myGlassPane = IdeGlassPaneUtil.find(myProvider.getComponent());
|
||||
myRootComponent = myProvider.getComponent().getRootPane();
|
||||
mySpotlight = new Spotlight(myRootComponent);
|
||||
myGlassPane.addPainter(myRootComponent, mySpotlight, myPainterDisposable);
|
||||
|
||||
myShowspotsAlarm = new Alarm(this);
|
||||
restartShowspotsAlarm();
|
||||
|
||||
myShowspots = showSpots;
|
||||
mySpotlight.setNeedsRepaint(true);
|
||||
}
|
||||
|
||||
public void setFadeaway(boolean fadeAway) {
|
||||
myFadingAway = fadeAway;
|
||||
}
|
||||
|
||||
|
||||
private class Spotlight extends AbstractPainter {
|
||||
|
||||
private Component myRoot;
|
||||
|
||||
private Area myArea;
|
||||
|
||||
private BufferedImage myBackground;
|
||||
|
||||
private Spotlight(Component root) {
|
||||
myRoot = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRepaint() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePaint(Component component, Graphics2D g) {
|
||||
int inset = -1;
|
||||
int selectedInset = -8;
|
||||
|
||||
Set<Area> shapes = new HashSet<>();
|
||||
Area selected = null;
|
||||
|
||||
boolean hasIntersections = false;
|
||||
|
||||
Rectangle clip = g.getClipBounds();
|
||||
myArea = new Area(clip);
|
||||
|
||||
for (SwitchTarget each : myTargets) {
|
||||
RelativeRectangle eachSimpleRec = each.getRectangle();
|
||||
if (eachSimpleRec == null) continue;
|
||||
|
||||
boolean isSelected = each.equals(mySelection);
|
||||
|
||||
Rectangle eachBaseRec = eachSimpleRec.getRectangleOn(myRoot);
|
||||
Rectangle eachShape;
|
||||
if (isSelected) {
|
||||
eachShape = new Rectangle(eachBaseRec.x + selectedInset,
|
||||
eachBaseRec.y + selectedInset,
|
||||
eachBaseRec.width - selectedInset -selectedInset,
|
||||
eachBaseRec.height - selectedInset -selectedInset);
|
||||
} else {
|
||||
eachShape = new Rectangle(eachBaseRec.x + inset,
|
||||
eachBaseRec.y + inset,
|
||||
eachBaseRec.width - inset -inset,
|
||||
eachBaseRec.height - inset -inset);
|
||||
}
|
||||
|
||||
if (!hasIntersections) {
|
||||
hasIntersections = clip.contains(eachShape) || clip.intersects(eachShape);
|
||||
}
|
||||
|
||||
Area eachArea = new Area(new RoundRectangle2D.Double(eachShape.x, eachShape.y, eachShape.width, eachShape.height, 6, 6));
|
||||
shapes.add(eachArea);
|
||||
if (isSelected) {
|
||||
selected = eachArea;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Color fillColor = new Color(0f, 0f, 0f, 0.25f);
|
||||
if (!hasIntersections && myShowspots) {
|
||||
g.setColor(fillColor);
|
||||
g.fillRect(clip.x, clip.y, clip.width, clip.height);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Area each : shapes) {
|
||||
myArea.subtract(each);
|
||||
if (each != selected) {
|
||||
each.subtract(selected);
|
||||
}
|
||||
}
|
||||
|
||||
GraphicsConfig cfg = new GraphicsConfig(g);
|
||||
cfg.setAntialiasing(true);
|
||||
|
||||
if (myShowspots) {
|
||||
g.setColor(fillColor);
|
||||
g.fill(myArea);
|
||||
|
||||
g.setColor(Color.lightGray);
|
||||
for (Shape each : shapes) {
|
||||
if (each != selected) {
|
||||
g.draw(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected != null) {
|
||||
Color bg = Color.darkGray;
|
||||
g.setColor(ColorUtil.toAlpha(bg, 180));
|
||||
g.setStroke(new BasicStroke(3));
|
||||
g.draw(selected);
|
||||
}
|
||||
|
||||
cfg.restore();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dispatchKeyEvent(KeyEvent e) {
|
||||
if (myFadingAway) {
|
||||
_dispose();
|
||||
} else {
|
||||
KeyEvent event = myInitialEvent;
|
||||
if (event == null || ((e.getModifiers() & event.getModifiers()) == 0)) {
|
||||
finish(!isSelectionWasMoved());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private SwitchTarget getSelection() {
|
||||
return mySelection;
|
||||
}
|
||||
|
||||
public boolean isSelectionWasMoved() {
|
||||
return mySelectionWasMoved;
|
||||
}
|
||||
|
||||
private enum Direction {
|
||||
up, down, left, right
|
||||
}
|
||||
|
||||
public void up() {
|
||||
setSelection(getNextTarget(Direction.up));
|
||||
}
|
||||
|
||||
public void down() {
|
||||
setSelection(getNextTarget(Direction.down));
|
||||
}
|
||||
|
||||
public void left() {
|
||||
setSelection(getNextTarget(Direction.left));
|
||||
}
|
||||
|
||||
public void right() {
|
||||
setSelection(getNextTarget(Direction.right));
|
||||
}
|
||||
|
||||
private void setSelection(SwitchTarget target) {
|
||||
if (target == null) return;
|
||||
|
||||
mySelection = target;
|
||||
|
||||
mySelectionWasMoved |= !mySelection.equals(myStartSelection);
|
||||
|
||||
mySpotlight.setNeedsRepaint(true);
|
||||
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(myAutoApplyRunnable, Registry.intValue("actionSystem.autoSelectTimeout"));
|
||||
|
||||
restartShowspotsAlarm();
|
||||
}
|
||||
|
||||
private SwitchTarget getNextTarget(Direction direction) {
|
||||
if (myTargets.size() == 1) {
|
||||
return getSelection();
|
||||
}
|
||||
|
||||
List<Point> points = new ArrayList<>();
|
||||
Point selected = null;
|
||||
Map<SwitchTarget, Point> target2Point = new HashMap<>();
|
||||
for (SwitchTarget each : myTargets) {
|
||||
RelativeRectangle rectangle = each.getRectangle();
|
||||
if (rectangle == null) continue;
|
||||
Rectangle eachRec = rectangle.getRectangleOn(myRootComponent);
|
||||
Point eachPoint = null;
|
||||
switch (direction) {
|
||||
case up:
|
||||
eachPoint = new Point(eachRec.x + eachRec.width / 2, eachRec.y + eachRec.height);
|
||||
break;
|
||||
case down:
|
||||
eachPoint = new Point(eachRec.x + eachRec.width /2, eachRec.y);
|
||||
break;
|
||||
case left:
|
||||
eachPoint = new Point(eachRec.x + eachRec.width, eachRec.y + eachRec.height / 2);
|
||||
break;
|
||||
case right:
|
||||
eachPoint = new Point(eachRec.x, eachRec.y + eachRec.height / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (each.equals(mySelection)) {
|
||||
switch (direction) {
|
||||
case up:
|
||||
selected = new Point(eachRec.x + eachRec.width / 2, eachRec.y);
|
||||
break;
|
||||
case down:
|
||||
selected = new Point(eachRec.x + eachRec.width / 2, eachRec.y + eachRec.height);
|
||||
break;
|
||||
case left:
|
||||
selected = new Point(eachRec.x, eachRec.y + eachRec.height / 2);
|
||||
break;
|
||||
case right:
|
||||
selected = new Point(eachRec.x + eachRec.width, eachRec.y + eachRec.height / 2);
|
||||
break;
|
||||
}
|
||||
points.add(selected);
|
||||
target2Point.put(each, selected);
|
||||
}
|
||||
else {
|
||||
points.add(eachPoint);
|
||||
target2Point.put(each, eachPoint);
|
||||
}
|
||||
}
|
||||
|
||||
TreeMap<Integer, SwitchTarget> distance = new TreeMap<>();
|
||||
for (SwitchTarget eachTarget : myTargets) {
|
||||
Point eachPoint = target2Point.get(eachTarget);
|
||||
if (eachPoint == null || selected == null) continue;
|
||||
if (selected == eachPoint) continue;
|
||||
|
||||
double eachDistance = sqrt(abs(eachPoint.getX() - selected.getX())) + sqrt(abs(eachPoint.getY() - selected.getY()));
|
||||
distance.put((int)eachDistance, eachTarget);
|
||||
}
|
||||
|
||||
|
||||
Integer[] distancesArray = distance.keySet().toArray(new Integer[distance.size()]);
|
||||
for (Integer eachDistance : distancesArray) {
|
||||
SwitchTarget eachTarget = distance.get(eachDistance);
|
||||
Point eachPoint = target2Point.get(eachTarget);
|
||||
if (eachPoint == null || selected == null) continue;
|
||||
switch (direction) {
|
||||
case up:
|
||||
if (eachPoint.y <= selected.y) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
case down:
|
||||
if (eachPoint.y >= selected.y) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
case left:
|
||||
if (eachPoint.x <= selected.x) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
case right:
|
||||
if (eachPoint.x >= selected.x) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = distancesArray.length - 1; i >= 0; i--) {
|
||||
SwitchTarget eachTarget = distance.get(distancesArray[i]);
|
||||
Point eachPoint = target2Point.get(eachTarget);
|
||||
if (eachPoint == null || selected == null) continue;
|
||||
switch (direction) {
|
||||
case up:
|
||||
if (eachPoint.y >= selected.y) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
case down:
|
||||
if (eachPoint.y <= selected.y) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
case left:
|
||||
if (eachPoint.x >= selected.x) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
case right:
|
||||
if (eachPoint.x <= selected.x) {
|
||||
return eachTarget;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (myTargets.size() == 0) return null;
|
||||
|
||||
List<SwitchTarget> all = Arrays.asList(myTargets.toArray(new SwitchTarget[myTargets.size()]));
|
||||
int index = all.indexOf(getSelection());
|
||||
if (index + 1 < myTargets.size()) {
|
||||
return all.get(index + 1);
|
||||
}
|
||||
else {
|
||||
return all.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myFinished = true;
|
||||
|
||||
if (myFadingAway) {
|
||||
myManager.addFadingAway(this);
|
||||
myAlarm.addRequest(() -> _dispose(), Registry.intValue("actionSystem.keyGestureDblClickTime"));
|
||||
} else {
|
||||
_dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void _dispose() {
|
||||
myFadingAway = false;
|
||||
myManager.removeFadingAway(this);
|
||||
Disposer.dispose(myPainterDisposable);
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this);
|
||||
}
|
||||
|
||||
public AsyncResult<SwitchTarget> finish(final boolean fadeAway) {
|
||||
myAlarm.cancelAllRequests();
|
||||
|
||||
final AsyncResult<SwitchTarget> result = new AsyncResult<>();
|
||||
final SwitchTarget selection = getSelection();
|
||||
if (selection != null) {
|
||||
selection.switchTo(true).doWhenDone(() -> {
|
||||
myManager.disposeCurrentSession(fadeAway);
|
||||
result.setDone(selection);
|
||||
}).notifyWhenRejected(result);
|
||||
} else {
|
||||
Disposer.dispose(this);
|
||||
result.setDone();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return myFinished;
|
||||
}
|
||||
|
||||
public void setShowspots(boolean showspots) {
|
||||
if (myShowspots != showspots) {
|
||||
myShowspots = showspots;
|
||||
mySpotlight.setNeedsRepaint(true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isShowspots() {
|
||||
return myShowspots;
|
||||
}
|
||||
|
||||
private void restartShowspotsAlarm() {
|
||||
myShowspotsAlarm.cancelAllRequests();
|
||||
myShowspotsAlarm.addRequest(myShowspotsRunnable, Registry.intValue("actionSystem.quickAccessShowSpotsTime"));
|
||||
}
|
||||
}
|
||||
@@ -56,14 +56,14 @@ import com.intellij.openapi.wm.impl.commands.*;
|
||||
import com.intellij.ui.BalloonImpl;
|
||||
import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.switcher.QuickAccessSettings;
|
||||
import com.intellij.ui.switcher.SwitchManager;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.EdtInvocationManager;
|
||||
import com.intellij.util.ui.PositionTracker;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.update.UiNotifyConnector;
|
||||
import gnu.trove.THashSet;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -264,7 +264,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
|
||||
int mouseMask = InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON2_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK;
|
||||
if ((e.getModifiersEx() & mouseMask) == 0) {
|
||||
if (SwitchManager.areAllModifiersPressed(modifiers, vks) || !pressed) {
|
||||
if (areAllModifiersPressed(modifiers, vks) || !pressed) {
|
||||
processState(pressed);
|
||||
}
|
||||
else {
|
||||
@@ -277,6 +277,29 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean areAllModifiersPressed(@JdkConstants.InputEventMask int modifiers, Set<Integer> modifierCodes) {
|
||||
int mask = 0;
|
||||
for (Integer each : modifierCodes) {
|
||||
if (each == KeyEvent.VK_SHIFT) {
|
||||
mask |= InputEvent.SHIFT_MASK;
|
||||
}
|
||||
|
||||
if (each == KeyEvent.VK_CONTROL) {
|
||||
mask |= InputEvent.CTRL_MASK;
|
||||
}
|
||||
|
||||
if (each == KeyEvent.VK_META) {
|
||||
mask |= InputEvent.META_MASK;
|
||||
}
|
||||
|
||||
if (each == KeyEvent.VK_ALT) {
|
||||
mask |= InputEvent.ALT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return (modifiers ^ mask) == 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<Integer> getActivateToolWindowVKs() {
|
||||
if (ApplicationManager.getApplication() == null) return new HashSet<>();
|
||||
@@ -293,7 +316,28 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
}
|
||||
}
|
||||
}
|
||||
return QuickAccessSettings.getModifiersVKs(baseModifiers);
|
||||
return getModifiersVKs(baseModifiers);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<Integer> getModifiersVKs(int mask) {
|
||||
Set<Integer> codes = new THashSet<>();
|
||||
if ((mask & InputEvent.SHIFT_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_SHIFT);
|
||||
}
|
||||
if ((mask & InputEvent.CTRL_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_CONTROL);
|
||||
}
|
||||
|
||||
if ((mask & InputEvent.META_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_META);
|
||||
}
|
||||
|
||||
if ((mask & InputEvent.ALT_MASK) > 0) {
|
||||
codes.add(KeyEvent.VK_ALT);
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
private void resetHoldState() {
|
||||
|
||||
@@ -1,335 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.ui.switcher;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.SeparatorWithText;
|
||||
import com.intellij.ui.components.panels.VerticalBox;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class QuickAccessConfigurable extends JPanel implements SearchableConfigurable {
|
||||
private Set<String> myModifiers = new HashSet<>();
|
||||
private boolean myQaEnabled;
|
||||
private int myDelay;
|
||||
private JCheckBox myEnabled;
|
||||
private ModifierBox myCtrl;
|
||||
private ModifierBox myAlt;
|
||||
private ModifierBox myShift;
|
||||
private ModifierBox myMeta;
|
||||
private JPanel myConflicts;
|
||||
private JFormattedTextField myHoldTime;
|
||||
private QuickAccessSettings myQuickAccessSettings;
|
||||
|
||||
public QuickAccessConfigurable(QuickAccessSettings quickAccessSettings) {
|
||||
myQuickAccessSettings = quickAccessSettings;
|
||||
JPanel north = new JPanel(new BorderLayout());
|
||||
VerticalBox box = new VerticalBox();
|
||||
north.add(box, BorderLayout.NORTH);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(north, BorderLayout.WEST);
|
||||
|
||||
myEnabled = new JCheckBox("Enable Quick Access");
|
||||
myEnabled.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
myQaEnabled = myEnabled.isSelected();
|
||||
processEnabled();
|
||||
}
|
||||
});
|
||||
box.add(myEnabled);
|
||||
|
||||
VerticalBox kbConfig = new VerticalBox();
|
||||
|
||||
JPanel modifiers = new JPanel(new FlowLayout(FlowLayout.CENTER)) {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = super.getPreferredSize();
|
||||
size.width *= 1.5;
|
||||
return size;
|
||||
}
|
||||
};
|
||||
myCtrl = new ModifierBox("control", KeyEvent.getKeyModifiersText(KeyEvent.CTRL_MASK));
|
||||
myAlt = new ModifierBox("alt", KeyEvent.getKeyModifiersText(KeyEvent.ALT_MASK));
|
||||
myShift = new ModifierBox("shift", KeyEvent.getKeyModifiersText(KeyEvent.SHIFT_MASK));
|
||||
myMeta = new ModifierBox("meta", KeyEvent.getKeyModifiersText(KeyEvent.META_MASK));
|
||||
|
||||
modifiers.add(new JLabel("Modifiers:"));
|
||||
modifiers.add(myCtrl);
|
||||
modifiers.add(myAlt);
|
||||
modifiers.add(myShift);
|
||||
if (SystemInfo.isMac) {
|
||||
modifiers.add(myMeta);
|
||||
}
|
||||
|
||||
JPanel hold = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||
hold.add(new JLabel("Hold time:"));
|
||||
myHoldTime = new JFormattedTextField(NumberFormat.getIntegerInstance());
|
||||
myHoldTime.setColumns(5);
|
||||
myHoldTime.setHorizontalAlignment(JTextField.RIGHT);
|
||||
myHoldTime.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
String txt = myHoldTime.getText();
|
||||
if (txt != null) {
|
||||
try {
|
||||
Integer value = Integer.valueOf(txt);
|
||||
myDelay = value.intValue();
|
||||
}
|
||||
catch (NumberFormatException e1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
hold.add(myHoldTime);
|
||||
hold.add(new JLabel("ms"));
|
||||
|
||||
kbConfig.add(modifiers);
|
||||
kbConfig.add(hold);
|
||||
|
||||
kbConfig.setBorder(IdeBorderFactory.createTitledBorder("Keyboard Configuration", true));
|
||||
|
||||
box.add(kbConfig);
|
||||
|
||||
myConflicts = new JPanel();
|
||||
|
||||
box.add(myConflicts);
|
||||
|
||||
updateConflicts();
|
||||
}
|
||||
|
||||
private Set<String> getModifierTexts() {
|
||||
HashSet<String> result = new HashSet<>();
|
||||
|
||||
for (Integer each : myQuickAccessSettings.getModiferCodes()) {
|
||||
if (each == KeyEvent.VK_SHIFT) {
|
||||
result.add("shift");
|
||||
}
|
||||
else if (each == KeyEvent.VK_CONTROL) {
|
||||
result.add("control");
|
||||
}
|
||||
else if (each == KeyEvent.VK_ALT) {
|
||||
result.add("alt");
|
||||
}
|
||||
else if (each == KeyEvent.VK_META) {
|
||||
result.add("meta");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void updateConflicts() {
|
||||
myConflicts.removeAll();
|
||||
myConflicts.setBorder(null);
|
||||
|
||||
if (!myQaEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myModifiers.size() == 0) {
|
||||
myConflicts.setLayout(new BorderLayout());
|
||||
myConflicts.add(getSmallLabel("Without assigning modifier keys Quick Access will not function"), BorderLayout.NORTH);
|
||||
return;
|
||||
}
|
||||
|
||||
myConflicts.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.insets = new Insets(0, 4, 0, 4);
|
||||
|
||||
boolean hasConflicts = printConflict(c, KeyEvent.VK_UP, QuickAccessSettings.SWITCH_UP);
|
||||
hasConflicts |= printConflict(c, KeyEvent.VK_DOWN, QuickAccessSettings.SWITCH_DOWN);
|
||||
hasConflicts |= printConflict(c, KeyEvent.VK_LEFT, QuickAccessSettings.SWITCH_LEFT);
|
||||
hasConflicts |= printConflict(c, KeyEvent.VK_RIGHT, QuickAccessSettings.SWITCH_RIGHT);
|
||||
hasConflicts |= printConflict(c, KeyEvent.VK_ENTER, QuickAccessSettings.SWITCH_APPLY);
|
||||
|
||||
if (hasConflicts) {
|
||||
myConflicts.setBorder(IdeBorderFactory.createTitledBorder("Conflicts", true));
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
c.gridwidth = 2;
|
||||
myConflicts.add(new SeparatorWithText(), c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
myConflicts.add(getSmallLabel("These conflicting actions may be not what you use a lot"), c);
|
||||
}
|
||||
}
|
||||
|
||||
private static JLabel getSmallLabel(final String text) {
|
||||
JLabel message = new JLabel(text, null, JLabel.CENTER);
|
||||
message.setFont(message.getFont().deriveFont(message.getFont().getStyle(), message.getFont().getSize() - 2));
|
||||
return message;
|
||||
}
|
||||
|
||||
private boolean printConflict(GridBagConstraints c, int actionKey, String actionId) {
|
||||
boolean hasConflicts = false;
|
||||
|
||||
int mask = myQuickAccessSettings.getModifierMask(myModifiers);
|
||||
|
||||
KeyboardShortcut sc = new KeyboardShortcut(KeyStroke.getKeyStroke(actionKey, mask), null);
|
||||
|
||||
Map<String,ArrayList<KeyboardShortcut>> conflictMap = myQuickAccessSettings.getKeymap().getConflicts(actionId, sc);
|
||||
if (conflictMap.size() > 0) {
|
||||
hasConflicts = true;
|
||||
|
||||
JLabel scText = new JLabel(sc.toString());
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
myConflicts.add(scText, c);
|
||||
|
||||
Iterator<String> actions = conflictMap.keySet().iterator();
|
||||
while (actions.hasNext()) {
|
||||
String each = actions.next();
|
||||
AnAction eachAnAction = ActionManager.getInstance().getAction(each);
|
||||
if (eachAnAction != null) {
|
||||
String text = eachAnAction.getTemplatePresentation().getText();
|
||||
JLabel eachAction = new JLabel(text != null && text.length() > 0 ? text : each);
|
||||
c.gridx = 1;
|
||||
myConflicts.add(eachAction, c);
|
||||
c.gridy++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridwidth = 2;
|
||||
c.gridy++;
|
||||
|
||||
myConflicts.add(new SeparatorWithText(), c);
|
||||
c.gridwidth = 1;
|
||||
|
||||
return hasConflicts;
|
||||
|
||||
}
|
||||
|
||||
@Nls
|
||||
public String getDisplayName() {
|
||||
return "Quick Access";
|
||||
}
|
||||
|
||||
public String getHelpTopic() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JComponent createComponent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getId() {
|
||||
return "QuickAccess";
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return !myModifiers.equals(getModifierTexts())
|
||||
|| myQuickAccessSettings.isEnabled() != myEnabled.isSelected()
|
||||
|| getHoldTime() != myDelay;
|
||||
}
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
Registry.get("actionSystem.quickAccessEnabled").setValue(myEnabled.isSelected());
|
||||
myQuickAccessSettings.saveModifiersToRegistry(myModifiers);
|
||||
Registry.get("actionSystem.keyGestureHoldTime").setValue(myDelay);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
int delay = getHoldTime();
|
||||
myQaEnabled = myQuickAccessSettings.isEnabled();
|
||||
myModifiers.clear();
|
||||
myModifiers.addAll(getModifierTexts());
|
||||
myDelay = delay;
|
||||
|
||||
myEnabled.setSelected(myQaEnabled);
|
||||
myCtrl.readMask();
|
||||
myAlt.readMask();
|
||||
myShift.readMask();
|
||||
myMeta.readMask();
|
||||
|
||||
myHoldTime.setText(String.valueOf(delay));
|
||||
|
||||
processEnabled();
|
||||
|
||||
updateConflicts();
|
||||
}
|
||||
|
||||
private static int getHoldTime() {
|
||||
return Registry.intValue("actionSystem.keyGestureHoldTime");
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
}
|
||||
|
||||
private void processEnabled() {
|
||||
for (Component component : UIUtil.uiTraverser(this)) {
|
||||
if (component != myEnabled) {
|
||||
component.setEnabled(myQaEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ModifierBox extends JCheckBox {
|
||||
|
||||
private String myModifierText;
|
||||
|
||||
private ModifierBox(String modifierText, String text) {
|
||||
setText(text);
|
||||
myModifierText = modifierText;
|
||||
addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
applyMask();
|
||||
updateConflicts();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void applyMask() {
|
||||
if (isSelected()) {
|
||||
myModifiers.add(myModifierText);
|
||||
}
|
||||
else {
|
||||
myModifiers.remove(myModifierText);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean readMask() {
|
||||
boolean selected = myModifiers.contains(myModifierText);
|
||||
setSelected(selected);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.ui.switcher;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public abstract class SwitchAction extends AnAction implements DumbAware {
|
||||
|
||||
protected SwitchAction() {
|
||||
setEnabledInModalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
if (!getSettings().isEnabled()) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
SwitchingSession session = getSession(e);
|
||||
e.getPresentation().setEnabled(session != null && !session.isFinished() || getProvider(e) != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
SwitchingSession session = getSession(e);
|
||||
if (session == null || session.isFinished()) {
|
||||
SwitchProvider provider = getProvider(e);
|
||||
session = new SwitchingSession(getManager(e), provider, (KeyEvent)e.getInputEvent(), null, false);
|
||||
initSession(e, session);
|
||||
}
|
||||
|
||||
move(session);
|
||||
}
|
||||
|
||||
protected static QuickAccessSettings getSettings() {
|
||||
return QuickAccessSettings.getInstance();
|
||||
}
|
||||
|
||||
private static SwitchProvider getProvider(AnActionEvent e) {
|
||||
return e.getData(SwitchProvider.KEY);
|
||||
}
|
||||
|
||||
private static SwitchingSession getSession(AnActionEvent e) {
|
||||
return getManager(e).getSession();
|
||||
}
|
||||
|
||||
private static SwitchManager getManager(AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
return SwitchManager.getInstance(project);
|
||||
}
|
||||
|
||||
private static void initSession(AnActionEvent e, SwitchingSession session) {
|
||||
getManager(e).initSession(session);
|
||||
}
|
||||
|
||||
protected abstract void move(SwitchingSession session);
|
||||
|
||||
public static class Up extends SwitchAction {
|
||||
@Override
|
||||
protected void move(SwitchingSession session) {
|
||||
session.up();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Down extends SwitchAction {
|
||||
@Override
|
||||
protected void move(SwitchingSession session) {
|
||||
session.down();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Left extends SwitchAction {
|
||||
@Override
|
||||
protected void move(SwitchingSession session) {
|
||||
session.left();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Right extends SwitchAction {
|
||||
@Override
|
||||
protected void move(SwitchingSession session) {
|
||||
session.right();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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.ui.switcher;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.ex.AnActionListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Set;
|
||||
|
||||
final class SwitchManagerAppComponent extends AnActionListener.Adapter implements KeyEventDispatcher {
|
||||
private final Set<AnAction> switchActions = new THashSet<>();
|
||||
|
||||
public SwitchManagerAppComponent(@NotNull ActionManager actionManager) {
|
||||
switchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_UP));
|
||||
switchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_DOWN));
|
||||
switchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_LEFT));
|
||||
switchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_RIGHT));
|
||||
switchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_APPLY));
|
||||
|
||||
actionManager.addAnActionListener(this);
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
|
||||
Project project = event.getProject();
|
||||
if (project != null && !project.isDisposed() && !project.isDefault() && !switchActions.contains(action)) {
|
||||
SwitchManager.getInstance(project).disposeCurrentSession(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(@NotNull KeyEvent e) {
|
||||
if (!QuickAccessSettings.getInstance().isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Component frame = UIUtil.findUltimateParent(e.getComponent());
|
||||
if (frame instanceof IdeFrame) {
|
||||
Project project = ((IdeFrame)frame).getProject();
|
||||
if (project != null && !project.isDefault()) {
|
||||
return SwitchManager.getInstance(project).dispatchKeyEvent(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -305,7 +305,6 @@
|
||||
<actionFromOptionDescriptorProvider implementation="com.intellij.ide.plugins.InstalledPluginsManagerMain$PluginsActionFromOptionDescriptorProvider"/>
|
||||
<applicationConfigurable parentId="preferences.general" instance="com.intellij.util.net.HttpProxyConfigurable" id="http.proxy" displayName="HTTP Proxy"/>
|
||||
<applicationConfigurable groupId="tools" displayName="Server Certificates" id="http.certificates" instance="com.intellij.util.net.ssl.CertificateConfigurable"/>
|
||||
<!--<applicationConfigurable instance="com.intellij.ui.switcher.QuickAccessConfigurable"/>-->
|
||||
|
||||
<fileTypeFactory implementation="com.intellij.openapi.fileTypes.impl.PlatformFileTypeFactory"/>
|
||||
<fileTypeFactory implementation="com.intellij.openapi.fileTypes.impl.InternalFileTypeFactory"/>
|
||||
@@ -335,8 +334,6 @@
|
||||
|
||||
<applicationService serviceImplementation="com.intellij.ide.RemoteDesktopDetector"/>
|
||||
|
||||
<projectService serviceImplementation="com.intellij.ui.switcher.SwitchManager"/>
|
||||
|
||||
<fileEditorProvider implementation="com.intellij.openapi.fileEditor.impl.http.HttpFileEditorProvider"/>
|
||||
<editorActionHandler action="EditorEscape" implementationClass="com.intellij.codeInsight.hint.EscapeHandler" id="hide-hints"/>
|
||||
|
||||
|
||||
@@ -45,22 +45,10 @@
|
||||
<component>
|
||||
<implementation-class>com.intellij.ide.MacOSApplicationProvider</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>com.intellij.ui.switcher.QuickAccessSettings</implementation-class>
|
||||
</component>
|
||||
|
||||
<component>
|
||||
<implementation-class>com.intellij.openapi.updateSettings.impl.UpdateCheckerComponent</implementation-class>
|
||||
<headless-implementation-class/>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>com.intellij.ui.switcher.SwitchManagerAppComponent</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>com.intellij.ui.switcher.QuickActionManager</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -15,15 +15,6 @@
|
||||
-->
|
||||
<idea-plugin>
|
||||
<actions>
|
||||
|
||||
<group id="SwitchViewActions">
|
||||
<action id="SwitchUp" text="Switching Up" class="com.intellij.ui.switcher.SwitchAction$Up"/>
|
||||
<action id="SwitchDown" text="Switching Down" class="com.intellij.ui.switcher.SwitchAction$Down"/>
|
||||
<action id="SwitchLeft" text="Switching Left" class="com.intellij.ui.switcher.SwitchAction$Left"/>
|
||||
<action id="SwitchRight" text="Switching Right" class="com.intellij.ui.switcher.SwitchAction$Right"/>
|
||||
<action id="SwitchApply" text="Switching Apply" class="com.intellij.ui.switcher.ApplySwitchAction"/>
|
||||
</group>
|
||||
|
||||
<group id="ScrollPaneActions">
|
||||
<action id="ScrollPane-scrollHome" text="Scroll Home" class="com.intellij.ui.ScrollPaneActions$Home"/>
|
||||
<action id="ScrollPane-scrollEnd" text="Scroll End" class="com.intellij.ui.ScrollPaneActions$End"/>
|
||||
|
||||
@@ -30,11 +30,6 @@ actionSystem.noContextComponentWhileFocusTransfer=true
|
||||
actionSystem.secondKeystrokeTimeout=2000
|
||||
actionSystem.secondKeystrokeAutoPopupEnabled=false
|
||||
actionSystem.secondKeystrokePopupTimeout=500
|
||||
actionSystem.keyGestureHoldTime=400
|
||||
actionSystem.autoSelectTimeout=1000
|
||||
actionSystem.quickAccessEnabled=false
|
||||
actionSystem.quickAccessModifiers=
|
||||
actionSystem.quickAccessShowSpotsTime=1500
|
||||
actionSystem.win.suppressAlt=true
|
||||
|
||||
actionSystem.win.suppressAlt.new=true
|
||||
|
||||
Reference in New Issue
Block a user