예제 #1
0
/** Provides shared UI- and action-related constants. */
public interface AWTConstants {

  int MULTI_CLICK_INTERVAL = 250; // a guess
  /** Number of pixels traversed before a drag starts. */
  // OSX 10(1.3.1), 5(1.4.1)
  // Linux/X11: delay+16
  // NOTE: could maybe install a drag gesture recognizer, but that's kinda
  // complex for what you get out of it.
  int DRAG_THRESHOLD = Platform.isWindows() || Platform.isMacintosh() ? 10 : 16;

  int BUTTON_MASK = (InputEvent.BUTTON1_MASK | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK);
  int POPUP_MASK = AWT.getPopupMask();
  String POPUP_MODIFIER = AWT.getMouseModifiers(POPUP_MASK);
  boolean POPUP_ON_PRESS = AWT.getPopupOnPress();
  int TERTIARY_MASK = AWT.getTertiaryMask();
  String TERTIARY_MODIFIER = AWT.getMouseModifiers(TERTIARY_MASK);
  int MENU_SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
  String MENU_SHORTCUT_MODIFIER = AWT.getKeyModifiers(MENU_SHORTCUT_MASK);
  String MENU_SHORTCUT_STRING =
      MENU_SHORTCUT_MASK == InputEvent.ALT_MASK
          ? "alt "
          : MENU_SHORTCUT_MASK == InputEvent.META_MASK
              ? "meta "
              : MENU_SHORTCUT_MASK == InputEvent.SHIFT_MASK ? "shift " : "control ";
  String MENU_SHORTCUT_KEYCODE = AWT.getKeyCode(AWT.maskToKeyCode(MENU_SHORTCUT_MASK));
}
예제 #2
0
  /**
   * Handle an event. This can either be ignored or contribute to the recording. For a given event,
   * if no current semantic recorder is active, select one based on the event's component. If the
   * semantic recorder accepts the event, then it is used to consume each subsequent event, until
   * its recordEvent method returns true, indicating that the semantic event has completed.
   */
  protected void recordEvent(java.awt.AWTEvent event) throws RecordingFailedException {

    // Discard any key/button release events at the start of the recording.
    if (steps.size() == 0 && event.getID() == KeyEvent.KEY_RELEASED) {
      Log.log("Ignoring initial release event");
      return;
    }

    SemanticRecorder newRecorder = null;

    // Process extraneous key modifiers used to simulate mouse buttons
    // Only check events while we have no semantic recorder, though,
    // because we wish to ignore everything between the modifiers
    if (Platform.isMacintosh() && semanticRecorder == null) {
      if (pruneClickModifiers(event)) return;
    }

    if (semanticRecorder == null) {
      SemanticRecorder sr =
          (event.getSource() instanceof Component)
              ? getSemanticRecorder((Component) event.getSource())
              // Use ComponentRecorder for MenuComponents
              : getSemanticRecorder(Component.class);
      if (sr.accept(event)) {
        semanticRecorder = newRecorder = sr;
        setStatus("Recording semantic event with " + sr);
        if (event.getSource() instanceof JInternalFrame) {
          // Ideally, adding an extra listener would be done by the
          // JInternalFrameRecorder, but the object needs more state
          // than is available to the recorder (notably to be able
          // to send events to the primary recorder).  If something
          // else turns up similar to this, then the EventRecorder
          // should be made available to the semantic recorders.
          //
          // Must add a listener, since COMPONENT_HIDDEN is not sent
          // on JInternalFrame close (1.4.1).
          JInternalFrame f = (JInternalFrame) event.getSource();
          new InternalFrameWatcher(f);
        }
      }
    }

    // If we're currently recording a semantic event, continue to do so
    if (semanticRecorder != null) {
      boolean consumed = semanticRecorder.record(event);
      boolean finished = semanticRecorder.isFinished();
      if (finished) {
        Log.debug("Semantic recorder is finished");
        saveSemanticEvent();
      }
      // If not consumed, need to check for semantic recorder (again)
      // (but avoid recursing indefinitely)
      if (!consumed && newRecorder == null) {
        Log.debug("Event was not consumed, parse it again");
        recordEvent(event);
      }
    } else {
      captureRawEvent(event);
    }
  }
예제 #3
0
  /** Eliminate redundant key press/release events surrounding a keytyped event. */
  private void coalesceKeyEvents() {
    setStatus("Coalescing key events");
    for (int i = 0; i < steps.size(); i++) {
      Step step = (Step) steps.get(i);
      if (isKey(step, ANY_KEY, PRESS)) {
        // In the case of modifiers, remove only if the presence of
        // the key down/up is redundant.
        Event se = (Event) step;
        String cs = se.getAttribute(XMLConstants.TAG_KEYCODE);
        int code = AWT.getKeyCode(cs);
        // OSX option modifier should be ignored, since it is used to
        // generate input method events.
        boolean isOSXOption = Platform.isOSX() && code == KeyEvent.VK_ALT;
        if (AWT.isModifier(code) && !isOSXOption) continue;

        // In the case of non-modifier keys, walk the steps until we
        // find the key release, then optionally replace the key press
        // with a keystroke, or remove it if the keystroke was already
        // recorded.  This sorts out jumbled key press/release events.
        boolean foundKeyStroke = false;
        boolean foundRelease = false;
        for (int j = i + 1; j < steps.size(); j++) {
          Step next = (Step) steps.get(j);
          // If we find the release, remove it and this
          if (isKey(next, cs, RELEASE)) {
            foundRelease = true;
            String target = ((Event) next).getComponentID();
            steps.remove(j);
            steps.remove(i);
            // Add a keystroke only if we didn't find any key
            // input between press and release (except on OSX,
            // where the option key generates input method events
            // which aren't recorded).
            if (!foundKeyStroke && !isOSXOption) {
              String mods = se.getAttribute(XMLConstants.TAG_MODIFIERS);
              String[] args =
                  (mods == null || "0".equals(mods)
                      ? new String[] {target, cs}
                      : new String[] {target, cs, mods});
              Step typed = new Action(getResolver(), null, "actionKeyStroke", args);
              steps.add(i, typed);
              setStatus("Insert artifical " + typed);
            } else {
              setStatus("Removed redundant key events (" + cs + ")");
              --i;
            }
            break;
          } else if (isKeyStroke(next, ANY_KEY) || isKeyString(next)) {
            foundKeyStroke = true;
            // If it's a numpad keycode, use the numpad
            // keycode instead of the resulting numeric character
            // keystroke.
            if (cs.startsWith("VK_NUMPAD")) {
              foundKeyStroke = false;
              steps.remove(j--);
            }
          }
        }
        // We don't like standalone key presses
        if (!foundRelease) {
          setStatus("Removed extraneous key press (" + cs + ")");
          steps.remove(i--);
        }
      }
    }
  }