private void changeCase(@NonNull Button button) {
   final boolean upperCase = button.getText().equals("↑");
   App.processViewsOfType(
       user.getKeyboard(),
       Button.class,
       new App.ViewProcessor<Button>() {
         @Override
         public void process(@Nonnull Button key) {
           final String letter = key.getText().toString();
           if (!ALPHABET.contains(letter.toLowerCase(Locale.US))) {
             return;
           }
           if (upperCase) {
             key.setText(letter.toUpperCase(Locale.US));
           } else {
             key.setText(letter.toLowerCase(Locale.US));
           }
         }
       });
   if (upperCase) {
     button.setText("↓");
   } else {
     button.setText("↑");
   }
 }
  @Nonnull
  public static Result getType(
      @Nonnull String text,
      int i,
      boolean hexMode,
      @Nonnull Result result,
      @Nonnull Engine engine) {
    if (i < 0) {
      throw new IllegalArgumentException("I must be more or equals to 0.");
    } else if (i >= text.length() && i != 0) {
      throw new IllegalArgumentException("I must be less than size of text.");
    } else if (i == 0 && text.length() == 0) {
      return result.set(MathType.text, text);
    }
    final List<MathType> mathTypes = getMathTypesByPriority();
    for (int j = 0; j < mathTypes.size(); j++) {
      final MathType mathType = mathTypes.get(j);
      final String s = App.find(mathType.getTokens(engine), text, i);
      if (s == null) {
        continue;
      }

      if (s.length() > 1) {
        if (mathType == function) {
          final int nextToken = i + s.length();
          if (nextToken < text.length()) {
            // function must have an open group symbol after its name
            if (MathType.open_group_symbol
                .getTokens()
                .contains(text.substring(nextToken, nextToken + 1))) {
              return result.set(function, s);
            }
          } else if (nextToken == text.length()) {
            // or its name should finish the expression
            return result.set(function, s);
          }
          continue;
        }
        return result.set(mathType, s);
      }

      if (hexMode || JsclMathEngine.getInstance().getNumeralBase() == NumeralBase.hex) {
        final Character ch = s.charAt(0);
        if (NumeralBase.hex.getAcceptableCharacters().contains(ch)) {
          return result.set(MathType.digit, s);
        }
      }

      if (mathType == MathType.grouping_separator) {
        if (i + 1 < text.length()
            && MathType.digit.getTokens().contains(text.substring(i + 1, i + 2))
            && i - 1 >= 0
            && MathType.digit.getTokens().contains(text.substring(i - 1, i))) {
          return result.set(mathType, s);
        }
        continue;
      }

      return result.set(mathType, s);
    }

    return result.set(MathType.text, text.substring(i));
  }