Android Open Source - opensudoku Sudoku Board View






From Project

Back to project page opensudoku.

License

The source code is released under:

GNU General Public License

If you think the Android project opensudoku listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* 
 * Copyright (C) 2009 Roman Masek/* www.j a va 2 s  .co  m*/
 * 
 * This file is part of OpenSudoku.
 * 
 * OpenSudoku is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * OpenSudoku is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with OpenSudoku.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package org.moire.opensudoku.gui;

import java.util.Collection;

import org.moire.opensudoku.R;
import org.moire.opensudoku.game.Cell;
import org.moire.opensudoku.game.CellCollection;
import org.moire.opensudoku.game.CellNote;
import org.moire.opensudoku.game.SudokuGame;
import org.moire.opensudoku.game.CellCollection.OnChangeListener;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

/**
 * Sudoku board widget.
 *
 * @author romario
 */
public class SudokuBoardView extends View {

  public static final int DEFAULT_BOARD_SIZE = 100;

  /**
   * "Color not set" value. (In relation to {@link Color}, it is in fact black color with
   * alpha channel set to 0 => that means it is completely transparent).
   */
  private static final int NO_COLOR = 0;

  private float mCellWidth;
  private float mCellHeight;

  private Cell mTouchedCell;
  // TODO: should I synchronize access to mSelectedCell?
  private Cell mSelectedCell;
  private boolean mReadonly = false;
  private boolean mHighlightWrongVals = true;
  private boolean mHighlightTouchedCell = true;
  private boolean mAutoHideTouchedCellHint = true;

  private SudokuGame mGame;
  private CellCollection mCells;

  private OnCellTappedListener mOnCellTappedListener;
  private OnCellSelectedListener mOnCellSelectedListener;

  private Paint mLinePaint;
  private Paint mSectorLinePaint;
  private Paint mCellValuePaint;
  private Paint mCellValueReadonlyPaint;
  private Paint mCellNotePaint;
  private int mNumberLeft;
  private int mNumberTop;
  private float mNoteTop;
  private int mSectorLineWidth;
  private Paint mBackgroundColorSecondary;
  private Paint mBackgroundColorReadOnly;
  private Paint mBackgroundColorTouched;
  private Paint mBackgroundColorSelected;

  private Paint mCellValueInvalidPaint;

  public SudokuBoardView(Context context) {
    this(context, null);
  }

  //  public SudokuBoardView(Context context, AttributeSet attrs) {
  //    this(context, attrs, R.attr.sudokuBoardViewStyle);
  //  }

  // TODO: do I need an defStyle?
  public SudokuBoardView(Context context, AttributeSet attrs/*, int defStyle*/) {
    super(context, attrs/*, defStyle*/);

    setFocusable(true);
    setFocusableInTouchMode(true);

    mLinePaint = new Paint();
    mSectorLinePaint = new Paint();
    mCellValuePaint = new Paint();
    mCellValueReadonlyPaint = new Paint();
    mCellValueInvalidPaint = new Paint();
    mCellNotePaint = new Paint();
    mBackgroundColorSecondary = new Paint();
    mBackgroundColorReadOnly = new Paint();
    mBackgroundColorTouched = new Paint();
    mBackgroundColorSelected = new Paint();

    mCellValuePaint.setAntiAlias(true);
    mCellValueReadonlyPaint.setAntiAlias(true);
    mCellValueInvalidPaint.setAntiAlias(true);
    mCellNotePaint.setAntiAlias(true);
    mCellValueInvalidPaint.setColor(Color.RED);

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SudokuBoardView/*, defStyle, 0*/);

    setLineColor(a.getColor(R.styleable.SudokuBoardView_lineColor, Color.BLACK));
    setSectorLineColor(a.getColor(R.styleable.SudokuBoardView_sectorLineColor, Color.BLACK));
    setTextColor(a.getColor(R.styleable.SudokuBoardView_textColor, Color.BLACK));
    setTextColorReadOnly(a.getColor(R.styleable.SudokuBoardView_textColorReadOnly, Color.BLACK));
    setTextColorNote(a.getColor(R.styleable.SudokuBoardView_textColorNote, Color.BLACK));
    setBackgroundColor(a.getColor(R.styleable.SudokuBoardView_backgroundColor, Color.WHITE));
    setBackgroundColorSecondary(a.getColor(R.styleable.SudokuBoardView_backgroundColorSecondary, NO_COLOR));
    setBackgroundColorReadOnly(a.getColor(R.styleable.SudokuBoardView_backgroundColorReadOnly, NO_COLOR));
    setBackgroundColorTouched(a.getColor(R.styleable.SudokuBoardView_backgroundColorTouched, Color.rgb(50, 50, 255)));
    setBackgroundColorSelected(a.getColor(R.styleable.SudokuBoardView_backgroundColorSelected, Color.YELLOW));

    a.recycle();
  }

  public int getLineColor() {
    return mLinePaint.getColor();
  }

  public void setLineColor(int color) {
    mLinePaint.setColor(color);
  }

  public int getSectorLineColor() {
    return mSectorLinePaint.getColor();
  }

  public void setSectorLineColor(int color) {
    mSectorLinePaint.setColor(color);
  }

  public int getTextColor() {
    return mCellValuePaint.getColor();
  }

  public void setTextColor(int color) {
    mCellValuePaint.setColor(color);
  }

  public int getTextColorReadOnly() {
    return mCellValueReadonlyPaint.getColor();
  }

  public void setTextColorReadOnly(int color) {
    mCellValueReadonlyPaint.setColor(color);
  }

  public int getTextColorNote() {
    return mCellNotePaint.getColor();
  }

  public void setTextColorNote(int color) {
    mCellNotePaint.setColor(color);
  }

  public int getBackgroundColorSecondary() {
    return mBackgroundColorSecondary.getColor();
  }

  public void setBackgroundColorSecondary(int color) {
    mBackgroundColorSecondary.setColor(color);
  }

  public int getBackgroundColorReadOnly() {
    return mBackgroundColorReadOnly.getColor();
  }

  public void setBackgroundColorReadOnly(int color) {
    mBackgroundColorReadOnly.setColor(color);
  }

  public int getBackgroundColorTouched() {
    return mBackgroundColorTouched.getColor();
  }

  public void setBackgroundColorTouched(int color) {
    mBackgroundColorTouched.setColor(color);
    mBackgroundColorTouched.setAlpha(100);
  }

  public int getBackgroundColorSelected() {
    return mBackgroundColorSelected.getColor();
  }

  public void setBackgroundColorSelected(int color) {
    mBackgroundColorSelected.setColor(color);
    mBackgroundColorSelected.setAlpha(100);
  }

  public void setGame(SudokuGame game) {
    mGame = game;
    setCells(game.getCells());
  }

  public void setCells(CellCollection cells) {
    mCells = cells;

    if (mCells != null) {
      if (!mReadonly) {
        mSelectedCell = mCells.getCell(0, 0); // first cell will be selected by default
        onCellSelected(mSelectedCell);
      }

      mCells.addOnChangeListener(new OnChangeListener() {
        @Override
        public void onChange() {
          postInvalidate();
        }
      });
    }

    postInvalidate();
  }

  public CellCollection getCells() {
    return mCells;
  }

  public Cell getSelectedCell() {
    return mSelectedCell;
  }

  public void setReadOnly(boolean readonly) {
    mReadonly = readonly;
    postInvalidate();
  }

  public boolean isReadOnly() {
    return mReadonly;
  }

  public void setHighlightWrongVals(boolean highlightWrongVals) {
    mHighlightWrongVals = highlightWrongVals;
    postInvalidate();
  }

  public boolean getHighlightWrongVals() {
    return mHighlightWrongVals;
  }

  public void setHighlightTouchedCell(boolean highlightTouchedCell) {
    mHighlightTouchedCell = highlightTouchedCell;
  }

  public boolean getHighlightTouchedCell() {
    return mHighlightTouchedCell;
  }

  public void setAutoHideTouchedCellHint(boolean autoHideTouchedCellHint) {
    mAutoHideTouchedCellHint = autoHideTouchedCellHint;
  }

  public boolean getAutoHideTouchedCellHint() {
    return mAutoHideTouchedCellHint;
  }

  /**
   * Registers callback which will be invoked when user taps the cell.
   *
   * @param l
   */
  public void setOnCellTappedListener(OnCellTappedListener l) {
    mOnCellTappedListener = l;
  }

  protected void onCellTapped(Cell cell) {
    if (mOnCellTappedListener != null) {
      mOnCellTappedListener.onCellTapped(cell);
    }
  }

  /**
   * Registers callback which will be invoked when cell is selected. Cell selection
   * can change without user interaction.
   *
   * @param l
   */
  public void setOnCellSelectedListener(OnCellSelectedListener l) {
    mOnCellSelectedListener = l;
  }

  public void hideTouchedCellHint() {
    mTouchedCell = null;
    postInvalidate();
  }


  protected void onCellSelected(Cell cell) {
    if (mOnCellSelectedListener != null) {
      mOnCellSelectedListener.onCellSelected(cell);
    }
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);


//        Log.d(TAG, "widthMode=" + getMeasureSpecModeString(widthMode));
//        Log.d(TAG, "widthSize=" + widthSize);
//        Log.d(TAG, "heightMode=" + getMeasureSpecModeString(heightMode));
//        Log.d(TAG, "heightSize=" + heightSize);

    int width = -1, height = -1;
    if (widthMode == MeasureSpec.EXACTLY) {
      width = widthSize;
    } else {
      width = DEFAULT_BOARD_SIZE;
      if (widthMode == MeasureSpec.AT_MOST && width > widthSize) {
        width = widthSize;
      }
    }
    if (heightMode == MeasureSpec.EXACTLY) {
      height = heightSize;
    } else {
      height = DEFAULT_BOARD_SIZE;
      if (heightMode == MeasureSpec.AT_MOST && height > heightSize) {
        height = heightSize;
      }
    }

    if (widthMode != MeasureSpec.EXACTLY) {
      width = height;
    }

    if (heightMode != MeasureSpec.EXACTLY) {
      height = width;
    }

    if (widthMode == MeasureSpec.AT_MOST && width > widthSize) {
      width = widthSize;
    }
    if (heightMode == MeasureSpec.AT_MOST && height > heightSize) {
      height = heightSize;
    }

    mCellWidth = (width - getPaddingLeft() - getPaddingRight()) / 9.0f;
    mCellHeight = (height - getPaddingTop() - getPaddingBottom()) / 9.0f;

    setMeasuredDimension(width, height);

    float cellTextSize = mCellHeight * 0.75f;
    mCellValuePaint.setTextSize(cellTextSize);
    mCellValueReadonlyPaint.setTextSize(cellTextSize);
    mCellValueInvalidPaint.setTextSize(cellTextSize);
    mCellNotePaint.setTextSize(mCellHeight / 3.0f);
    // compute offsets in each cell to center the rendered number
    mNumberLeft = (int) ((mCellWidth - mCellValuePaint.measureText("9")) / 2);
    mNumberTop = (int) ((mCellHeight - mCellValuePaint.getTextSize()) / 2);

    // add some offset because in some resolutions notes are cut-off in the top
    mNoteTop = mCellHeight / 50.0f;

    computeSectorLineWidth(width, height);
  }

  private void computeSectorLineWidth(int widthInPx, int heightInPx) {
    int sizeInPx = widthInPx < heightInPx ? widthInPx : heightInPx;
    float dipScale = getContext().getResources().getDisplayMetrics().density;
    float sizeInDip = sizeInPx / dipScale;

    float sectorLineWidthInDip = 2.0f;

    if (sizeInDip > 150) {
      sectorLineWidthInDip = 3.0f;
    }

    mSectorLineWidth = (int) (sectorLineWidthInDip * dipScale);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // some notes:
    // Drawable has its own draw() method that takes your Canvas as an arguement

    // TODO: I don't get this, why do I need to substract padding only from one side?
    int width = getWidth() - getPaddingRight();
    int height = getHeight() - getPaddingBottom();

    int paddingLeft = getPaddingLeft();
    int paddingTop = getPaddingTop();

    // draw secondary background
    if (mBackgroundColorSecondary.getColor() != NO_COLOR) {
      canvas.drawRect(3 * mCellWidth, 0, 6 * mCellWidth, 3 * mCellWidth, mBackgroundColorSecondary);
      canvas.drawRect(0, 3 * mCellWidth, 3 * mCellWidth, 6 * mCellWidth, mBackgroundColorSecondary);
      canvas.drawRect(6 * mCellWidth, 3 * mCellWidth, 9 * mCellWidth, 6 * mCellWidth, mBackgroundColorSecondary);
      canvas.drawRect(3 * mCellWidth, 6 * mCellWidth, 6 * mCellWidth, 9 * mCellWidth, mBackgroundColorSecondary);
    }

    // draw cells
    int cellLeft, cellTop;
    if (mCells != null) {

      boolean hasBackgroundColorReadOnly = mBackgroundColorReadOnly.getColor() != NO_COLOR;

      float numberAscent = mCellValuePaint.ascent();
      float noteAscent = mCellNotePaint.ascent();
      float noteWidth = mCellWidth / 3f;
      for (int row = 0; row < 9; row++) {
        for (int col = 0; col < 9; col++) {
          Cell cell = mCells.getCell(row, col);

          cellLeft = Math.round((col * mCellWidth) + paddingLeft);
          cellTop = Math.round((row * mCellHeight) + paddingTop);

          // draw read-only field background
          if (!cell.isEditable() && hasBackgroundColorReadOnly) {
            if (mBackgroundColorReadOnly.getColor() != NO_COLOR) {
              canvas.drawRect(
                  cellLeft, cellTop,
                  cellLeft + mCellWidth, cellTop + mCellHeight,
                  mBackgroundColorReadOnly);
            }
          }

          // draw cell Text
          int value = cell.getValue();
          if (value != 0) {
            Paint cellValuePaint = cell.isEditable() ? mCellValuePaint : mCellValueReadonlyPaint;

            if (mHighlightWrongVals && !cell.isValid()) {
              cellValuePaint = mCellValueInvalidPaint;
            }
            canvas.drawText(Integer.toString(value),
                cellLeft + mNumberLeft,
                cellTop + mNumberTop - numberAscent,
                cellValuePaint);
          } else {
            if (!cell.getNote().isEmpty()) {
              Collection<Integer> numbers = cell.getNote().getNotedNumbers();
              for (Integer number : numbers) {
                int n = number - 1;
                int c = n % 3;
                int r = n / 3;
                //canvas.drawText(Integer.toString(number), cellLeft + c*noteWidth + 2, cellTop + noteAscent + r*noteWidth - 1, mNotePaint);
                canvas.drawText(Integer.toString(number), cellLeft + c * noteWidth + 2, cellTop + mNoteTop - noteAscent + r * noteWidth - 1, mCellNotePaint);
              }
            }
          }


        }
      }

      // highlight selected cell
      if (!mReadonly && mSelectedCell != null) {
        cellLeft = Math.round(mSelectedCell.getColumnIndex() * mCellWidth) + paddingLeft;
        cellTop = Math.round(mSelectedCell.getRowIndex() * mCellHeight) + paddingTop;
        canvas.drawRect(
            cellLeft, cellTop,
            cellLeft + mCellWidth, cellTop + mCellHeight,
            mBackgroundColorSelected);
      }

      // visually highlight cell under the finger (to cope with touch screen
      // imprecision)
      if (mHighlightTouchedCell && mTouchedCell != null) {
        cellLeft = Math.round(mTouchedCell.getColumnIndex() * mCellWidth) + paddingLeft;
        cellTop = Math.round(mTouchedCell.getRowIndex() * mCellHeight) + paddingTop;
        canvas.drawRect(
            cellLeft, paddingTop,
            cellLeft + mCellWidth, height,
            mBackgroundColorTouched);
        canvas.drawRect(
            paddingLeft, cellTop,
            width, cellTop + mCellHeight,
            mBackgroundColorTouched);
      }

    }

    // draw vertical lines
    for (int c = 0; c <= 9; c++) {
      float x = (c * mCellWidth) + paddingLeft;
      canvas.drawLine(x, paddingTop, x, height, mLinePaint);
    }

    // draw horizontal lines
    for (int r = 0; r <= 9; r++) {
      float y = r * mCellHeight + paddingTop;
      canvas.drawLine(paddingLeft, y, width, y, mLinePaint);
    }

    int sectorLineWidth1 = mSectorLineWidth / 2;
    int sectorLineWidth2 = sectorLineWidth1 + (mSectorLineWidth % 2);

    // draw sector (thick) lines
    for (int c = 0; c <= 9; c = c + 3) {
      float x = (c * mCellWidth) + paddingLeft;
      canvas.drawRect(x - sectorLineWidth1, paddingTop, x + sectorLineWidth2, height, mSectorLinePaint);
    }

    for (int r = 0; r <= 9; r = r + 3) {
      float y = r * mCellHeight + paddingTop;
      canvas.drawRect(paddingLeft, y - sectorLineWidth1, width, y + sectorLineWidth2, mSectorLinePaint);
    }

  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {

    if (!mReadonly) {
      int x = (int) event.getX();
      int y = (int) event.getY();

      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
          mTouchedCell = getCellAtPoint(x, y);
          break;
        case MotionEvent.ACTION_UP:
          mSelectedCell = getCellAtPoint(x, y);
          invalidate(); // selected cell has changed, update board as soon as you can

          if (mSelectedCell != null) {
            onCellTapped(mSelectedCell);
            onCellSelected(mSelectedCell);
          }

          if (mAutoHideTouchedCellHint) {
            mTouchedCell = null;
          }
          break;
        case MotionEvent.ACTION_CANCEL:
          mTouchedCell = null;
          break;
      }
      postInvalidate();
    }

    return !mReadonly;
  }

  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (!mReadonly) {
      switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_UP:
          return moveCellSelection(0, -1);
        case KeyEvent.KEYCODE_DPAD_RIGHT:
          return moveCellSelection(1, 0);
        case KeyEvent.KEYCODE_DPAD_DOWN:
          return moveCellSelection(0, 1);
        case KeyEvent.KEYCODE_DPAD_LEFT:
          return moveCellSelection(-1, 0);
        case KeyEvent.KEYCODE_0:
        case KeyEvent.KEYCODE_SPACE:
        case KeyEvent.KEYCODE_DEL:
          // clear value in selected cell
          // TODO: I'm not really sure that this is thread-safe
          if (mSelectedCell != null) {
            if (event.isShiftPressed() || event.isAltPressed()) {
              setCellNote(mSelectedCell, CellNote.EMPTY);
            } else {
              setCellValue(mSelectedCell, 0);
              moveCellSelectionRight();
            }
          }
          return true;
        case KeyEvent.KEYCODE_DPAD_CENTER:
          if (mSelectedCell != null) {
            onCellTapped(mSelectedCell);
          }
          return true;
      }

      if (keyCode >= KeyEvent.KEYCODE_1 && keyCode <= KeyEvent.KEYCODE_9) {
        int selNumber = keyCode - KeyEvent.KEYCODE_0;
        Cell cell = mSelectedCell;

        if (event.isShiftPressed() || event.isAltPressed()) {
          // add or remove number in cell's note
          setCellNote(cell, cell.getNote().toggleNumber(selNumber));
        } else {
          // enter number in cell
          setCellValue(cell, selNumber);
          moveCellSelectionRight();
        }
        return true;
      }
    }


    return false;
  }


  /**
   * Moves selected cell by one cell to the right. If edge is reached, selection
   * skips on beginning of another line.
   */
  public void moveCellSelectionRight() {
    if (!moveCellSelection(1, 0)) {
      int selRow = mSelectedCell.getRowIndex();
      selRow++;
      if (!moveCellSelectionTo(selRow, 0)) {
        moveCellSelectionTo(0, 0);
      }
    }
    postInvalidate();
  }

  private void setCellValue(Cell cell, int value) {
    if (cell.isEditable()) {
      if (mGame != null) {
        mGame.setCellValue(cell, value);
      } else {
        cell.setValue(value);
      }
    }
  }

  private void setCellNote(Cell cell, CellNote note) {
    if (cell.isEditable()) {
      if (mGame != null) {
        mGame.setCellNote(cell, note);
      } else {
        cell.setNote(note);
      }
    }
  }


  /**
   * Moves selected by vx cells right and vy cells down. vx and vy can be negative. Returns true,
   * if new cell is selected.
   *
   * @param vx Horizontal offset, by which move selected cell.
   * @param vy Vertical offset, by which move selected cell.
   */
  private boolean moveCellSelection(int vx, int vy) {
    int newRow = 0;
    int newCol = 0;

    if (mSelectedCell != null) {
      newRow = mSelectedCell.getRowIndex() + vy;
      newCol = mSelectedCell.getColumnIndex() + vx;
    }

    return moveCellSelectionTo(newRow, newCol);
  }


  /**
   * Moves selection to the cell given by row and column index.
   *
   * @param row Row index of cell which should be selected.
   * @param col Columnd index of cell which should be selected.
   * @return True, if cell was successfuly selected.
   */
  private boolean moveCellSelectionTo(int row, int col) {
    if (col >= 0 && col < CellCollection.SUDOKU_SIZE
        && row >= 0 && row < CellCollection.SUDOKU_SIZE) {
      mSelectedCell = mCells.getCell(row, col);
      onCellSelected(mSelectedCell);

      postInvalidate();
      return true;
    }

    return false;
  }

  /**
   * Returns cell at given screen coordinates. Returns null if no cell is found.
   *
   * @param x
   * @param y
   * @return
   */
  private Cell getCellAtPoint(int x, int y) {
    // take into account padding
    int lx = x - getPaddingLeft();
    int ly = y - getPaddingTop();

    int row = (int) (ly / mCellHeight);
    int col = (int) (lx / mCellWidth);

    if (col >= 0 && col < CellCollection.SUDOKU_SIZE
        && row >= 0 && row < CellCollection.SUDOKU_SIZE) {
      return mCells.getCell(row, col);
    } else {
      return null;
    }
  }

  /**
   * Occurs when user tap the cell.
   *
   * @author romario
   */
  public interface OnCellTappedListener {
    void onCellTapped(Cell cell);
  }

  /**
   * Occurs when user selects the cell.
   *
   * @author romario
   */
  public interface OnCellSelectedListener {
    void onCellSelected(Cell cell);
  }

//  private String getMeasureSpecModeString(int mode) {
//    String modeString = null;
//    switch (mode) {
//    case MeasureSpec.AT_MOST:
//      modeString = "MeasureSpec.AT_MOST";
//      break;
//    case MeasureSpec.EXACTLY:
//      modeString = "MeasureSpec.EXACTLY";
//      break;
//    case MeasureSpec.UNSPECIFIED:
//      modeString = "MeasureSpec.UNSPECIFIED";
//      break;
//    }
//    
//    if (modeString == null)
//      modeString = new Integer(mode).toString();
//    
//    return modeString;
//  }

}




Java Source Code List

org.moire.opensudoku.db.DatabaseHelper.java
org.moire.opensudoku.db.FolderColumns.java
org.moire.opensudoku.db.SudokuColumns.java
org.moire.opensudoku.db.SudokuDatabase.java
org.moire.opensudoku.db.SudokuImportParams.java
org.moire.opensudoku.db.SudokuInvalidFormatException.java
org.moire.opensudoku.game.CellCollection.java
org.moire.opensudoku.game.CellGroup.java
org.moire.opensudoku.game.CellNote.java
org.moire.opensudoku.game.Cell.java
org.moire.opensudoku.game.FolderInfo.java
org.moire.opensudoku.game.SudokuGame.java
org.moire.opensudoku.game.command.AbstractCellCommand.java
org.moire.opensudoku.game.command.AbstractCommand.java
org.moire.opensudoku.game.command.ClearAllNotesCommand.java
org.moire.opensudoku.game.command.CommandStack.java
org.moire.opensudoku.game.command.EditCellNoteCommand.java
org.moire.opensudoku.game.command.FillInNotesCommand.java
org.moire.opensudoku.game.command.SetCellValueCommand.java
org.moire.opensudoku.gui.Changelog.java
org.moire.opensudoku.gui.FileImportActivity.java
org.moire.opensudoku.gui.FileListActivity.java
org.moire.opensudoku.gui.FolderDetailLoader.java
org.moire.opensudoku.gui.FolderListActivity.java
org.moire.opensudoku.gui.GameSettingsActivity.java
org.moire.opensudoku.gui.GameTimeFormat.java
org.moire.opensudoku.gui.HintsQueue.java
org.moire.opensudoku.gui.ImportSudokuActivity.java
org.moire.opensudoku.gui.SeekBarPreference.java
org.moire.opensudoku.gui.SudokuBoardView.java
org.moire.opensudoku.gui.SudokuEditActivity.java
org.moire.opensudoku.gui.SudokuExportActivity.java
org.moire.opensudoku.gui.SudokuImportActivity.java
org.moire.opensudoku.gui.SudokuListActivity.java
org.moire.opensudoku.gui.SudokuListFilter.java
org.moire.opensudoku.gui.SudokuPlayActivity.java
org.moire.opensudoku.gui.Timer.java
org.moire.opensudoku.gui.exporting.FileExportTaskParams.java
org.moire.opensudoku.gui.exporting.FileExportTaskResult.java
org.moire.opensudoku.gui.exporting.FileExportTask.java
org.moire.opensudoku.gui.importing.AbstractImportTask.java
org.moire.opensudoku.gui.importing.ExtrasImportTask.java
org.moire.opensudoku.gui.importing.OpenSudokuImportTask.java
org.moire.opensudoku.gui.importing.SdmImportTask.java
org.moire.opensudoku.gui.inputmethod.IMControlPanelStatePersister.java
org.moire.opensudoku.gui.inputmethod.IMControlPanel.java
org.moire.opensudoku.gui.inputmethod.IMNumpad.java
org.moire.opensudoku.gui.inputmethod.IMPopupDialog.java
org.moire.opensudoku.gui.inputmethod.IMPopup.java
org.moire.opensudoku.gui.inputmethod.IMSingleNumber.java
org.moire.opensudoku.gui.inputmethod.InputMethod.java
org.moire.opensudoku.utils.AndroidUtils.java
org.moire.opensudoku.utils.Const.java
org.moire.opensudoku.utils.StringUtils.java