| /* |
| * Copyright 2000-2009 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.keyGestures; |
| |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.openapi.keymap.impl.ActionProcessor; |
| import com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher; |
| import com.intellij.openapi.keymap.impl.KeyState; |
| import com.intellij.openapi.util.registry.Registry; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NotNull; |
| |
| import javax.swing.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.InputEvent; |
| |
| public class KeyboardGestureProcessor { |
| |
| IdeKeyEventDispatcher myDispatcher; |
| |
| StateContext myContext = new StateContext(); |
| |
| final KeyGestureState myWaitForStart = new KeyGestureState.WaitForStart(this); |
| final KeyGestureState myModifierPressed = new KeyGestureState.ModifierPressed(this); |
| final KeyGestureState myWaitForDblClick = new KeyGestureState.WaitForDblClick(this); |
| final KeyGestureState myWaitForAction = new KeyGestureState.WaitForAction(this); |
| final KeyGestureState myWaitForActionEnd = new KeyGestureState.WaitForActionEnd(this); |
| final KeyGestureState myFinish = new KeyGestureState.ProcessFinish(this); |
| |
| KeyGestureState myState = myWaitForStart; |
| |
| |
| final Timer myHoldTimer = UIUtil.createNamedTimer("Keyboard hold",1200, new ActionListener() { |
| public void actionPerformed(final ActionEvent e) { |
| } |
| }); |
| |
| final Timer myDblClickTimer = UIUtil.createNamedTimer("Double click",Registry.intValue("actionSystem.keyGestureDblClickTime"), new ActionListener() { |
| public void actionPerformed(final ActionEvent e) { |
| myState.processDblClickTimer(); |
| } |
| }); |
| private final ActionProcessor myActionProcessor = new MyActionProcessor(); |
| |
| public KeyboardGestureProcessor(final IdeKeyEventDispatcher dispatcher) { |
| myDispatcher = dispatcher; |
| } |
| |
| public boolean process() { |
| boolean wasNotInWaitState = myState != myWaitForStart; |
| |
| if (Registry.is("ide.debugMode") && wasNotInWaitState) { |
| System.out.println("-- key gesture context: before process, state=" + myState); |
| System.out.println(myContext); |
| } |
| |
| myContext.keyToProcess = myDispatcher.getContext().getInputEvent(); |
| myContext.isModal = myDispatcher.getContext().isModalContext(); |
| myContext.dataContext = myDispatcher.getContext().getDataContext(); |
| |
| boolean result = myState.process(); |
| |
| if (Registry.is("ide.debugMode") && (wasNotInWaitState || myState != myWaitForStart)) { |
| System.out.println("-- key gesture context: after process, state=" + myState); |
| System.out.println(myContext); |
| } |
| |
| return result; |
| } |
| |
| public boolean processInitState() { |
| if (!Registry.is("actionSystem.keyGestures.enabled")) return false; |
| |
| myContext.focusOwner = myDispatcher.getContext().getFocusOwner(); |
| return process(); |
| } |
| |
| void executeAction() { |
| myDispatcher.updateCurrentContext(myContext.focusOwner, getCurrentShortcut(), myContext.isModal); |
| myDispatcher.processAction(myContext.keyToProcess, myActionProcessor); |
| } |
| |
| private Shortcut getCurrentShortcut() { |
| return KeyboardModifierGestureShortcut.newInstance(myContext.modifierType, myContext.actionShortcut); |
| } |
| |
| void setState(KeyGestureState state) { |
| final boolean isGestureProcessingState = myDispatcher.getState() == KeyState.STATE_KEY_GESTURE_PROCESSOR; |
| if (state == myWaitForStart) { |
| myContext.actionKey = null; |
| if (isGestureProcessingState) { |
| myDispatcher.setState(KeyState.STATE_INIT); |
| } |
| } else if (state == myWaitForAction) { |
| myDispatcher.setState(KeyState.STATE_KEY_GESTURE_PROCESSOR); |
| } |
| myState = state; |
| } |
| |
| private class MyActionProcessor implements ActionProcessor { |
| @NotNull |
| public AnActionEvent createEvent(final InputEvent inputEvent, @NotNull final DataContext context, @NotNull final String place, @NotNull final Presentation presentation, |
| final ActionManager manager) { |
| myContext.actionPresentation = presentation; |
| myContext.actionPlace = place; |
| return myState.createActionEvent(); |
| } |
| |
| public void onUpdatePassed(final InputEvent inputEvent, @NotNull final AnAction action, @NotNull final AnActionEvent actionEvent) { |
| } |
| |
| public void performAction(final InputEvent e, @NotNull final AnAction action, @NotNull final AnActionEvent actionEvent) { |
| final boolean isGestureAction = action instanceof KeyboardGestureAction; |
| actionEvent.accept(new AnActionEventVisitor() { |
| @Override |
| public void visitGestureInitEvent(final AnActionEvent anActionEvent) { |
| if (isGestureAction) { |
| execute(anActionEvent, action, e); |
| } |
| } |
| |
| @Override |
| public void visitGesturePerformedEvent(final AnActionEvent anActionEvent) { |
| execute(anActionEvent, action, e); |
| } |
| |
| @Override |
| public void visitGestureFinishEvent(final AnActionEvent anActionEvent) { |
| if (isGestureAction) { |
| execute(anActionEvent, action, e); |
| } |
| } |
| }); |
| } |
| |
| private void execute(final AnActionEvent anActionEvent, final AnAction action, final InputEvent e) { |
| action.actionPerformed(anActionEvent); |
| e.consume(); |
| } |
| } |
| |
| } |