示例#1
0
  // helper method to find which cell a point maps to
  private Cell checkForNewHit(float x, float y) {

    final int rowHit = getRowHit(y);
    if (rowHit < 0) {
      return null;
    }
    final int columnHit = getColumnHit(x);
    if (columnHit < 0) {
      return null;
    }

    if (cellManager.isDrawn(rowHit, columnHit)) {
      return null;
    }
    return cellManager.get(rowHit, columnHit);
  }
示例#2
0
 /** Clear the pattern lookup table. */
 private void clearPatternDrawLookup() {
   for (int i = 0; i < gridSize; i++) {
     for (int j = 0; j < gridSize; j++) {
       cellManager.clearDrawing();
     }
   }
 }
示例#3
0
  /**
   * Set the pattern explicitly (rather than waiting for the user to input a pattern).
   *
   * @param displayMode How to display the pattern.
   * @param pattern The pattern.
   */
  public void setPattern(final DisplayMode displayMode, final List<Cell> pattern) {
    mPattern.clear();
    mPattern.addAll(pattern);
    clearPatternDrawLookup();
    for (Cell cell : pattern) {
      cellManager.draw(cell, true);
    }

    setDisplayMode(displayMode);
  }
示例#4
0
  /**
   * Determines whether the point x, y will add a new point to the current pattern (in addition to
   * finding the cell, also makes heuristic choices such as filling in gaps based on current
   * pattern).
   *
   * @param x The x coordinate.
   * @param y The y coordinate.
   */
  private Cell detectAndAddHit(float x, float y) {
    final Cell cell = checkForNewHit(x, y);
    if (cell != null) {

      // check for gaps in existing pattern
      // Cell fillInGapCelal = null;
      final ArrayList<Cell> newCells = new ArrayList<>();
      if (!mPattern.isEmpty()) {
        final Cell lastCell = mPattern.get(mPattern.size() - 1);
        int dRow = cell.getRow() - lastCell.getRow();
        int dCol = cell.getColumn() - lastCell.getColumn();
        int rsign = dRow > 0 ? 1 : -1;
        int csign = dCol > 0 ? 1 : -1;

        if (dRow == 0) {
          for (int i = 1; i < Math.abs(dCol); i++) {
            newCells.add(new Cell(lastCell.getRow(), lastCell.getColumn() + i * csign));
          }
        } else if (dCol == 0) {
          for (int i = 1; i < Math.abs(dRow); i++) {
            newCells.add(new Cell(lastCell.getRow() + i * rsign, lastCell.getColumn()));
          }
        } else if (Math.abs(dCol) == Math.abs(dRow)) {
          for (int i = 1; i < Math.abs(dRow); i++) {
            newCells.add(new Cell(lastCell.getRow() + i * rsign, lastCell.getColumn() + i * csign));
          }
        }
      }
      for (Cell fillInGapCell : newCells) {
        if (fillInGapCell != null && !cellManager.isDrawn(fillInGapCell)) {
          addCellToPattern(fillInGapCell);
        }
      }
      addCellToPattern(cell);
      if (enableHapticFeedback) {
        performHapticFeedback(
            HapticFeedbackConstants.VIRTUAL_KEY,
            HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
                | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
      }
      return cell;
    }
    return null;
  }
示例#5
0
  @Override
  protected void onDraw(Canvas canvas) {
    final ArrayList<Cell> pattern = mPattern;
    final int count = pattern.size();

    if (patternDisplayMode == DisplayMode.Animate) {

      final int oneCycle = (count + 1) * MILLIS_PER_CIRCLE_ANIMATING;
      final int spotInCycle =
          (int) (SystemClock.elapsedRealtime() - animatingPeriodStart) % oneCycle;
      final int numCircles = spotInCycle / MILLIS_PER_CIRCLE_ANIMATING;

      clearPatternDrawLookup();
      for (int i = 0; i < numCircles; i++) {
        final Cell cell = pattern.get(i);
        cellManager.draw(cell, true);
      }

      final boolean needToUpdateInProgressPoint = numCircles > 0 && numCircles < count;

      if (needToUpdateInProgressPoint) {
        final float percentageOfNextCircle =
            ((float) (spotInCycle % MILLIS_PER_CIRCLE_ANIMATING)) / MILLIS_PER_CIRCLE_ANIMATING;

        final Cell currentCell = pattern.get(numCircles - 1);
        final float centerX = getCenterXForColumn(currentCell.getColumn());
        final float centerY = getCenterYForRow(currentCell.getRow());

        final Cell nextCell = pattern.get(numCircles);
        final float dx =
            percentageOfNextCircle * (getCenterXForColumn(nextCell.getColumn()) - centerX);
        final float dy = percentageOfNextCircle * (getCenterYForRow(nextCell.getRow()) - centerY);
        inProgressX = centerX + dx;
        inProgressY = centerY + dy;
      }
      invalidate();
    }

    final float squareWidth = this.squareWidth;
    final float squareHeight = this.squareHeight;

    float radius = (squareWidth * diameterFactor * 0.5f);
    pathPaint.setStrokeWidth(radius);

    final Path currentPath = this.currentPath;
    currentPath.rewind();

    // draw the circles
    final int paddingTop = this.paddingTop;
    final int paddingLeft = this.paddingLeft;

    for (int i = 0; i < gridSize; i++) {
      float topY = paddingTop + i * squareHeight;
      for (int j = 0; j < gridSize; j++) {
        float leftX = paddingLeft + j * squareWidth;
        drawCircle(canvas, (int) leftX, (int) topY, cellManager.isDrawn(i, j));
      }
    }

    // only the last segment of the path should be computed here
    // draw the path of the pattern (unless the user is in progress, and
    // we are in stealth mode)
    final boolean drawPath =
        (!inStealthMode && patternDisplayMode == DisplayMode.Correct
            || !inErrorStealthMode && patternDisplayMode == DisplayMode.Wrong);

    // draw the arrows associated with the path (unless the user is in
    // progress, and
    // we are in stealth mode)
    boolean oldFlag = (circlePaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
    circlePaint.setFilterBitmap(true);

    if (drawPath) {
      boolean anyCircles = false;
      for (int i = 0; i < count; i++) {
        Cell cell = pattern.get(i);

        // only draw the part of the pattern stored in
        // the lookup table (this is only different in the case
        // of animation).
        if (!cellManager.isDrawn(cell)) {
          break;
        }
        anyCircles = true;

        float centerX = getCenterXForColumn(cell.getColumn());
        float centerY = getCenterYForRow(cell.getRow());
        if (i == 0) {
          currentPath.moveTo(centerX, centerY);
        } else {
          currentPath.lineTo(centerX, centerY);
        }
      }

      // add last in progress section
      if ((patternInProgress || patternDisplayMode == DisplayMode.Animate)
          && anyCircles
          && count > 1) {
        currentPath.lineTo(inProgressX, inProgressY);
      }
      canvas.drawPath(currentPath, pathPaint);
    }

    circlePaint.setFilterBitmap(oldFlag); // restore default flag
  }
示例#6
0
 private void addCellToPattern(Cell newCell) {
   cellManager.draw(newCell, true);
   mPattern.add(newCell);
   notifyCellAdded();
 }
示例#7
0
 private void init() {
   cellManager = new CellManager(gridSize, gridSize);
   final int matrixSize = cellManager.getSize();
   mPattern = new ArrayList<>(matrixSize);
 }