예제 #1
0
  /**
   * Retrieves the word on which the mouse pointer is present
   *
   * @param evt - the MouseEvent which triggered this method
   */
  private String fetchPhrase(MouseEvent evt) {
    Messages.log("--handle Mouse Right Click--");
    int off = xyToOffset(evt.getX(), evt.getY());
    if (off < 0) return null;
    int line = getLineOfOffset(off);
    if (line < 0) return null;
    String s = getLineText(line);
    if (s == null) return null;
    else if (s.length() == 0) return null;
    else {
      int x = xToOffset(line, evt.getX()), x2 = x + 1, x1 = x - 1;
      int xLS = off - getLineStartNonWhiteSpaceOffset(line);
      Messages.log("x=" + x);
      if (x < 0 || x >= s.length()) return null;
      String word = s.charAt(x) + "";
      if (s.charAt(x) == ' ') return null;
      if (!(Character.isLetterOrDigit(s.charAt(x)) || s.charAt(x) == '_' || s.charAt(x) == '$'))
        return null;
      int i = 0;
      while (true) {
        i++;
        if (x1 >= 0 && x1 < s.length()) {
          if (Character.isLetter(s.charAt(x1)) || s.charAt(x1) == '_') {
            word = s.charAt(x1--) + word;
            xLS--;
          } else x1 = -1;
        } else x1 = -1;

        if (x2 >= 0 && x2 < s.length()) {
          if (Character.isLetterOrDigit(s.charAt(x2)) || s.charAt(x2) == '_' || s.charAt(x2) == '$')
            word = word + s.charAt(x2++);
          else x2 = -1;
        } else x2 = -1;

        if (x1 < 0 && x2 < 0) break;
        if (i > 200) {
          // time out!
          break;
        }
      }
      if (Character.isDigit(word.charAt(0))) {
        return null;
      }
      Messages.log("Mouse click, word: " + word.trim());
      ASTGenerator astGenerator = editor.getErrorChecker().getASTGenerator();
      synchronized (astGenerator) {
        astGenerator.setLastClickedWord(line, word, xLS);
      }
      return word.trim();
    }
  }
예제 #2
0
  /**
   * Calculates location of caret and displays the suggestion popup at the location.
   *
   * @param listModel
   * @param subWord
   */
  protected void showSuggestion(DefaultListModel<CompletionCandidate> listModel, String subWord) {
    // new Exception(System.currentTimeMillis() + "").printStackTrace(System.out);
    hideSuggestion();

    if (listModel.size() == 0) {
      Messages.log("TextArea: No suggestions to show.");

    } else {
      int position = getCaretPosition();
      Point location = new Point();
      try {
        location.x = offsetToX(getCaretLine(), position - getLineStartOffset(getCaretLine()));
        location.y =
            lineToY(getCaretLine())
                + getPainter().getFontMetrics().getHeight()
                + getPainter().getFontMetrics().getDescent();
        // log("TA position: " + location);
      } catch (Exception e2) {
        e2.printStackTrace();
        return;
      }

      suggestion = new CompletionPanel(this, position, subWord, listModel, location, editor);
      requestFocusInWindow();
    }
  }
예제 #3
0
 /** Kickstart auto-complete suggestions */
 private void prepareSuggestions(final KeyEvent evt) {
   // Provide completions only if it's enabled
   if (JavaMode.codeCompletionsEnabled
       && (JavaMode.ccTriggerEnabled || (suggestion != null && suggestion.isVisible()))) {
     Messages.log("[KeyEvent]" + evt.getKeyChar() + "  |Prediction started");
     fetchPhrase();
   }
 }
예제 #4
0
  private void processCompletionKeys(final KeyEvent event) {
    char keyChar = event.getKeyChar();
    int keyCode = event.getKeyCode();
    if (keyChar == KeyEvent.VK_ENTER
        || keyChar == KeyEvent.VK_ESCAPE
        || keyChar == KeyEvent.VK_TAB
        || (event.getID() == KeyEvent.KEY_RELEASED
            && keyCode != KeyEvent.VK_LEFT
            && keyCode != KeyEvent.VK_RIGHT)) {
      // ignore
    } else if (keyChar == ')') {
      // https://github.com/processing/processing/issues/2741
      hideSuggestion();

    } else if (keyChar == '.') {
      if (JavaMode.codeCompletionsEnabled) {
        Messages.log(
            "[KeyEvent]" + KeyEvent.getKeyText(event.getKeyCode()) + "  |Prediction started");
        fetchPhrase();
      }
    } else if (keyChar == ' ') { // Trigger on Ctrl-Space
      if (!Platform.isMacOS()
          && JavaMode.codeCompletionsEnabled
          && (event.isControlDown() || event.isMetaDown())) {
        // Provide completions only if it's enabled
        if (JavaMode.codeCompletionsEnabled) {
          // Removed for https://github.com/processing/processing/issues/3847
          // try {
          //  getDocument().remove(getCaretPosition() - 1, 1); // Remove the typed space
          Messages.log("[KeyEvent]" + event.getKeyChar() + "  |Prediction started");
          fetchPhrase();
          // } catch (BadLocationException e) {
          //  e.printStackTrace();
          // }
        }
      } else {
        hideSuggestion(); // hide on spacebar
      }
    } else {
      if (JavaMode.codeCompletionsEnabled) {
        prepareSuggestions(event);
      }
    }
  }
예제 #5
0
 // Special case for OS X, where Ctrl-Space is not detected as KEY_TYPED
 // https://github.com/processing/processing/issues/2699
 private void processControlSpace(final KeyEvent event) {
   if (event.getKeyCode() == KeyEvent.VK_SPACE && event.isControlDown()) {
     // Provide completions only if it's enabled
     if (JavaMode.codeCompletionsEnabled) {
       Messages.log(
           "[KeyEvent]" + KeyEvent.getKeyText(event.getKeyCode()) + "  |Prediction started");
       fetchPhrase();
     }
   }
 }
예제 #6
0
  public void loadSuggestionsMap() {
    File suggestionsListFile = new File(getFolder() + File.separator + suggestionsFileName);
    if (!suggestionsListFile.exists()) {
      Messages.loge("Suggestions file not found! " + suggestionsListFile.getAbsolutePath());
      return;
    }

    try {
      BufferedReader br = new BufferedReader(new FileReader(suggestionsListFile));
      while (true) {
        String line = br.readLine();
        if (line == null) {
          break;
        }
        line = line.trim();
        if (line.startsWith("#")) {
          continue;
        } else {
          if (line.contains("=")) {
            String key = line.split("=")[0];
            String val = line.split("=")[1];
            if (suggestionsMap.containsKey(key)) {
              suggestionsMap.get(key).add(val);
            } else {
              HashSet<String> set = new HashSet<>();
              set.add(val);
              suggestionsMap.put(key, set);
            }
          }
        }
      }
      br.close();
    } catch (IOException e) {
      Messages.loge(
          "IOException while reading suggestions file:" + suggestionsListFile.getAbsolutePath());
    }
  }
예제 #7
0
 public void savePreferences() {
   Messages.log("Saving PDEX prefs");
   Preferences.setBoolean(prefErrorCheck, errorCheckEnabled);
   Preferences.setBoolean(prefWarnings, warningsEnabled);
   Preferences.setBoolean(prefCodeCompletionEnabled, codeCompletionsEnabled);
   //    Preferences.setBoolean(prefDebugOP, DEBUG);
   Preferences.setBoolean(prefErrorLogs, errorLogsEnabled);
   Preferences.setInteger(prefAutoSaveInterval, autoSaveInterval);
   //    Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled);
   Preferences.setBoolean(prefAutoSave, autoSaveEnabled);
   Preferences.setBoolean(prefAutoSavePrompt, autoSavePromptEnabled);
   Preferences.setBoolean(prefDefaultAutoSave, defaultAutoSaveEnabled);
   Preferences.setBoolean(prefCCTriggerEnabled, ccTriggerEnabled);
   Preferences.setBoolean(prefImportSuggestEnabled, importSuggestEnabled);
 }
예제 #8
0
 public void loadPreferences() {
   Messages.log("Load PDEX prefs");
   ensurePrefsExist();
   errorCheckEnabled = Preferences.getBoolean(prefErrorCheck);
   warningsEnabled = Preferences.getBoolean(prefWarnings);
   codeCompletionsEnabled = Preferences.getBoolean(prefCodeCompletionEnabled);
   //    DEBUG = Preferences.getBoolean(prefDebugOP);
   errorLogsEnabled = Preferences.getBoolean(prefErrorLogs);
   autoSaveInterval = Preferences.getInteger(prefAutoSaveInterval);
   //    untitledAutoSaveEnabled = Preferences.getBoolean(prefUntitledAutoSave);
   autoSaveEnabled = Preferences.getBoolean(prefAutoSave);
   autoSavePromptEnabled = Preferences.getBoolean(prefAutoSavePrompt);
   defaultAutoSaveEnabled = Preferences.getBoolean(prefDefaultAutoSave);
   ccTriggerEnabled = Preferences.getBoolean(prefCCTriggerEnabled);
   importSuggestEnabled = Preferences.getBoolean(prefImportSuggestEnabled);
   loadSuggestionsMap();
 }
  /** Build the sketch and run it on a device with the debugger connected. */
  public void handleRunDevice() {
    if (Platform.isWindows() && !Preferences.getBoolean("usbDriverWarningShown")) {
      Preferences.setBoolean("usbDriverWarningShown", true);

      String message = "";
      File usbDriverFile =
          new File(
              ((AndroidMode) sketch.getMode()).getSDK().getSdkFolder(), "extras/google/usb_driver");
      if (usbDriverFile.exists()) {
        message =
            "<html><body>"
                + "You might need to install Google USB Driver to run the sketch on your device.<br>"
                + "Please follow the guide at <a href='http://developer.android.com/tools/extras/oem-usb.html#InstallingDriver'>http://developer.android.com/tools/extras/oem-usb.html#InstallingDriver</a> to install the driver.<br>"
                + "For your reference, the driver is located in: "
                + usbDriverFile.getAbsolutePath();
      } else {
        message =
            "<html><body>"
                + "You might need to install Google USB Driver to run the sketch on your device.<br>"
                + "Please follow the guide at <a href='http://developer.android.com/tools/extras/oem-usb.html#InstallingDriver'>http://developer.android.com/tools/extras/oem-usb.html#InstallingDriver</a> to install the driver.<br>"
                + "You will also need to download the driver from <a href='http://developer.android.com/sdk/win-usb.html'>http://developer.android.com/sdk/win-usb.html</a>";
      }
      Messages.showWarning("USB Driver warning", message);

    } else {
      new Thread() {
        public void run() {
          toolbar.activateRun();
          //          toolbar.activate(AndroidToolbar.RUN);
          startIndeterminate();
          prepareRun();
          try {
            androidMode.handleRunDevice(sketch, AndroidEditor.this);
          } catch (SketchException e) {
            statusError(e);
          } catch (IOException e) {
            statusError(e);
          }
          stopIndeterminate();
        }
      }.start();
    }
  }
예제 #10
0
  protected static String parsePhrase(final String lineText) {

    boolean overloading = false;

    { // Check if we can provide suggestions for this phrase ending
      String trimmedLineText = lineText.trim();
      if (trimmedLineText.length() == 0) return null;

      char lastChar = trimmedLineText.charAt(trimmedLineText.length() - 1);
      if (lastChar == '.') {
        trimmedLineText = trimmedLineText.substring(0, trimmedLineText.length() - 1).trim();
        if (trimmedLineText.length() == 0) return null;
        lastChar = trimmedLineText.charAt(trimmedLineText.length() - 1);
        switch (lastChar) {
          case ')':
          case ']':
          case '"':
            break; // We can suggest for these
          default:
            if (!Character.isJavaIdentifierPart(lastChar)) {
              return null; // Not something we can suggest
            }
            break;
        }
      } else if (lastChar == '(') {
        overloading = true; // We can suggest overloaded methods
      } else if (!Character.isJavaIdentifierPart(lastChar)) {
        return null; // Not something we can suggest
      }
    }

    final int currentCharIndex = lineText.length() - 1;

    { // Check if the caret is in the comment
      int commentStart = lineText.indexOf("//", 0);
      if (commentStart >= 0 && currentCharIndex > commentStart) {
        return null;
      }
    }

    // Index the line
    BitSet isInLiteral = new BitSet(lineText.length());
    BitSet isInBrackets = new BitSet(lineText.length());

    { // Mark parts in literals
      boolean inString = false;
      boolean inChar = false;
      boolean inEscaped = false;

      for (int i = 0; i < lineText.length(); i++) {
        if (!inEscaped) {
          switch (lineText.charAt(i)) {
            case '\"':
              if (!inChar) inString = !inString;
              break;
            case '\'':
              if (!inString) inChar = !inChar;
              break;
            case '\\':
              if (inString || inChar) {
                inEscaped = true;
              }
              break;
          }
        } else {
          inEscaped = false;
        }
        isInLiteral.set(i, inString || inChar);
      }
    }

    if (isInLiteral.get(currentCharIndex)) return null;

    { // Mark parts in top level brackets
      int depth = overloading ? 1 : 0;
      int bracketStart = overloading ? lineText.length() : 0;
      int squareDepth = 0;
      int squareBracketStart = 0;

      bracketLoop:
      for (int i = lineText.length() - 1; i >= 0; i--) {
        if (!isInLiteral.get(i)) {
          switch (lineText.charAt(i)) {
            case ')':
              if (depth == 0) bracketStart = i;
              depth++;
              break;
            case '(':
              depth--;
              if (depth == 0) {
                isInBrackets.set(i, bracketStart);
              } else if (depth < 0) {
                break bracketLoop;
              }
              break;
            case ']':
              if (squareDepth == 0) squareBracketStart = i;
              squareDepth++;
              break;
            case '[':
              squareDepth--;
              if (squareDepth == 0) {
                isInBrackets.set(i, squareBracketStart);
              } else if (squareDepth < 0) {
                break bracketLoop;
              }
              break;
          }
        }
      }

      if (depth > 0) isInBrackets.set(0, bracketStart);
      if (squareDepth > 0) isInBrackets.set(0, squareBracketStart);
    }

    // Walk the line from the end while it makes sense
    int position = currentCharIndex;
    parseLoop:
    while (position >= 0) {
      int currChar = lineText.charAt(position);
      switch (currChar) {
        case '.': // Grab it
          position--;
          break;
        case '[':
          break parseLoop; // End of scope
        case ']': // Grab the whole region in square brackets
          position = isInBrackets.previousClearBit(position - 1);
          break;
        case '(':
          if (isInBrackets.get(position)) {
            position--; // This checks for first bracket while overloading
            break;
          }
          break parseLoop; // End of scope
        case ')': // Grab the whole region in brackets
          position = isInBrackets.previousClearBit(position - 1);
          break;
        case '"': // Grab the whole literal and quit
          position = isInLiteral.previousClearBit(position - 1);
          break parseLoop;
        default:
          if (Character.isJavaIdentifierPart(currChar)) {
            position--; // Grab the identifier
          } else if (Character.isWhitespace(currChar)) {
            position--; // Grab whitespace too
          } else {
            break parseLoop; // Got a char ending the phrase
          }
          break;
      }
    }

    position++;

    // Extract phrase
    String phrase = lineText.substring(position, lineText.length()).trim();
    Messages.log(phrase);

    if (phrase.length() == 0 || Character.isDigit(phrase.charAt(0))) {
      return null; // Can't suggest for numbers or empty phrases
    }

    return phrase;
  }
예제 #11
0
  /** Handles KeyEvents for TextArea (code completion begins from here). */
  public void processKeyEvent(KeyEvent evt) {
    if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
      if (suggestion != null) {
        if (suggestion.isVisible()) {
          Messages.log("esc key");
          hideSuggestion();
          evt.consume();
          return;
        }
      }

    } else if (evt.getKeyCode() == KeyEvent.VK_ENTER && evt.getID() == KeyEvent.KEY_PRESSED) {
      if (suggestion != null
          && suggestion.isVisible()
          && suggestion.insertSelection(CompletionPanel.KEYBOARD_COMPLETION)) {
        evt.consume();
        // Still try to show suggestions after inserting if it's
        // the case of overloaded methods. See #2755
        if (suggestion.isVisible()) {
          prepareSuggestions(evt);
        }
        return;
      }
    }

    if (evt.getID() == KeyEvent.KEY_PRESSED) {
      switch (evt.getKeyCode()) {
        case KeyEvent.VK_DOWN:
          if (suggestion != null)
            if (suggestion.isVisible()) {
              // log("KeyDown");
              suggestion.moveDown();
              return;
            }
          break;
        case KeyEvent.VK_UP:
          if (suggestion != null)
            if (suggestion.isVisible()) {
              // log("KeyUp");
              suggestion.moveUp();
              return;
            }
          break;
        case KeyEvent.VK_BACK_SPACE:
          Messages.log("BK Key");
          break;
        case KeyEvent.VK_SPACE:
          if (suggestion != null) {
            if (suggestion.isVisible()) {
              Messages.log("Space bar, hide completion list");
              suggestion.setInvisible();
            }
          }
          break;
      }
    }
    super.processKeyEvent(evt);

    // code completion disabled if Java tabs present
    if (!editor.hasJavaTabs()) {
      if (evt.getID() == KeyEvent.KEY_TYPED) {
        processCompletionKeys(evt);
      } else if (!Platform.isMacOS() && evt.getID() == KeyEvent.KEY_RELEASED) {
        processCompletionKeys(evt);
      } else if (Platform.isMacOS() && evt.getID() == KeyEvent.KEY_RELEASED) {
        processControlSpace(evt);
      }
    }
  }
예제 #12
0
  /** Start a sketch in tweak mode */
  public Runner handleTweak(Sketch sketch, RunnerListener listener, final boolean present)
      throws SketchException {
    final JavaEditor editor = (JavaEditor) listener;

    if (isSketchModified(sketch)) {
      editor.deactivateRun();
      Messages.showMessage(
          Language.text("menu.file.save"), Language.text("tweak_mode.save_before_tweak"));
      return null;
    }

    // first try to build the unmodified code
    JavaBuild build = new JavaBuild(sketch);
    //    String appletClassName = build.build(false);
    String appletClassName = build.build(true);
    if (appletClassName == null) {
      // unmodified build failed, so fail
      return null;
    }

    // if compilation passed, modify the code and build again
    // save the original sketch code of the user
    editor.initBaseCode();
    // check for "// tweak" comment in the sketch
    boolean requiresTweak = SketchParser.containsTweakComment(editor.baseCode);
    // parse the saved sketch to get all (or only with "//tweak" comment) numbers
    final SketchParser parser = new SketchParser(editor.baseCode, requiresTweak);

    // add our code to the sketch
    final boolean launchInteractive = editor.automateSketch(sketch, parser);

    build = new JavaBuild(sketch);
    appletClassName = build.build(false);

    if (appletClassName != null) {
      final Runner runtime = new Runner(build, listener);
      new Thread(
              new Runnable() {
                public void run() {
                  // these block until finished
                  if (present) {
                    runtime.present(null);
                  } else {
                    runtime.launch(null);
                  }
                  // next lines are executed when the sketch quits
                  if (launchInteractive) {
                    editor.initEditorCode(parser.allHandles, false);
                    editor.stopTweakMode(parser.allHandles);
                  }
                }
              })
          .start();

      if (launchInteractive) {
        // replace editor code with baseCode
        editor.initEditorCode(parser.allHandles, false);
        editor.updateInterface(parser.allHandles, parser.colorBoxes);
        editor.startTweakMode();
      }
      return runtime;
    }
    return null;
  }