diff --git a/wear/src/main/java/org/isoron/simpletimer/MainActivity.java b/wear/src/main/java/org/isoron/simpletimer/MainActivity.java index e67878b..1735590 100644 --- a/wear/src/main/java/org/isoron/simpletimer/MainActivity.java +++ b/wear/src/main/java/org/isoron/simpletimer/MainActivity.java @@ -40,8 +40,6 @@ public class MainActivity extends WearableActivity setAmbientEnabled(); - stimer = new SimpleTimer(); - alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent ambientModeIntent = new Intent(getApplicationContext(), MainActivity.class); ambientModeIntent.setAction("REFRESH"); @@ -52,6 +50,9 @@ public class MainActivity extends WearableActivity SharedPreferences preferences = getSharedPreferences(PREFS_NAME, 0); final long initialTime = preferences.getLong("initialTime", DEFAULT_INITIAL_TIME); + stimer = new SimpleTimer(); + stimer.setTotalTime(initialTime); + final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub); stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() { @@ -59,8 +60,8 @@ public class MainActivity extends WearableActivity public void onLayoutInflated(WatchViewStub stub) { timerView = (TimerView) findViewById(R.id.timerview); - timerView.setTime(initialTime); timerView.setTimer(stimer); + stimer.setListener(timerView); setAmbientModeListener(timerView); startFixedRateTimer(); refreshViews(); @@ -99,7 +100,6 @@ public class MainActivity extends WearableActivity { if (timerView != null) { - timerView.tick(); timerView.invalidate(); } @@ -108,7 +108,7 @@ public class MainActivity extends WearableActivity private void scheduleNextRefresh() { - long delay = timerView.getMillisecondsUntilNextMinute(); + long delay = stimer.getMillisecondsUntilNextMinute(); if (delay < 0) return; Log.d(TAG, "sleeping for " + delay + " milliseconds (" + delay / 1000 / 60.0 + @@ -190,7 +190,7 @@ public class MainActivity extends WearableActivity private void savePreferences() { - long totalTime = timerView.getTime(); + long totalTime = stimer.getTotalTime(); SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putLong("initialTime", totalTime); diff --git a/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimer.java b/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimer.java index e7af0e5..d732a7f 100644 --- a/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimer.java +++ b/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimer.java @@ -1,8 +1,13 @@ package org.isoron.simpletimer.model; +import android.util.Log; + public class SimpleTimer { - private enum TimerState { + private static final String TAG = "TimerView"; + + private enum TimerState + { PAUSED, RUNNING } @@ -11,25 +16,35 @@ public class SimpleTimer private long remainingTime; private TimerState state; - public static final int DEFAULT_INITIAL_TIME = 5 * 60 * 1000; + private SimpleTimerListener listener; + + private static final int DEFAULT_INITIAL_TIME = 5 * 60 * 1000; public SimpleTimer() { - startTime = -1; remainingTime = totalTime = DEFAULT_INITIAL_TIME; + state = TimerState.PAUSED; + } + + public void setListener(SimpleTimerListener listener) + { + this.listener = listener; } public void resume() { - if(isRunning()) return; + if (isRunning()) return; startTime = System.currentTimeMillis(); + startTime -= totalTime - remainingTime; state = TimerState.RUNNING; } public void pause() { - if(isPaused()) return; + if (isPaused()) return; + + remainingTime = getRemainingTime(); state = TimerState.PAUSED; } @@ -43,6 +58,12 @@ public class SimpleTimer return state == TimerState.PAUSED; } + public void flip() + { + if (isRunning()) pause(); + else resume(); + } + public void reset() { state = TimerState.PAUSED; @@ -51,9 +72,56 @@ public class SimpleTimer public long getRemainingTime() { - long currentTime = System.currentTimeMillis(); - long elapsedTime = currentTime - startTime; + if (isPaused()) + { + return remainingTime; + } + else + { + long currentTime = System.currentTimeMillis(); + long elapsedTime = currentTime - startTime; + long answer = totalTime - elapsedTime; + + if (answer >= 0) + { + return answer; + } + else + { + if (listener != null) listener.onTimeout(); + reset(); + + return remainingTime; + } + } + } + + public long getTotalTime() + { + return totalTime; + } + + public void setTotalTime(long totalTime) + { + this.totalTime = totalTime; + this.remainingTime = totalTime; + } + + public long getMillisecondsUntilNextMinute() + { + if (!isRunning()) return -1; + return getRemainingTime() % 60000; + } - return totalTime - elapsedTime; + public void increment(int direction) + { + if (isRunning()) return; + + int granularity = 60000; + if (totalTime + direction <= 3 * 60000) granularity = 10000; + + totalTime = Math.max(0, totalTime + direction * granularity); + totalTime = (totalTime / granularity) * granularity; + remainingTime = totalTime; } } diff --git a/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimerListener.java b/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimerListener.java new file mode 100644 index 0000000..b8caa75 --- /dev/null +++ b/wear/src/main/java/org/isoron/simpletimer/model/SimpleTimerListener.java @@ -0,0 +1,6 @@ +package org.isoron.simpletimer.model; + +public interface SimpleTimerListener +{ + public void onTimeout(); +} diff --git a/wear/src/main/java/org/isoron/simpletimer/views/TimerView.java b/wear/src/main/java/org/isoron/simpletimer/views/TimerView.java index af51b65..b745480 100644 --- a/wear/src/main/java/org/isoron/simpletimer/views/TimerView.java +++ b/wear/src/main/java/org/isoron/simpletimer/views/TimerView.java @@ -18,20 +18,19 @@ import android.view.View; import org.isoron.base.AmbientModeListener; import org.isoron.base.ColorHelper; -import org.isoron.simpletimer.MainActivity; import org.isoron.simpletimer.model.SimpleTimer; +import org.isoron.simpletimer.model.SimpleTimerListener; import java.util.Calendar; -public class TimerView extends View implements AmbientModeListener +public class TimerView extends View implements AmbientModeListener, SimpleTimerListener { private static final String TAG = "TimerView"; private int primaryColor; private int secondaryColor; private int tertiaryColor; - private int backgroundColor; private Paint paint; @@ -47,10 +46,6 @@ public class TimerView extends View implements AmbientModeListener private Vibrator vibrator; private int step; - private boolean isRunning; - private long totalTime; - private long remainingTime; - private long lastTick; private boolean hasLongPressed; private boolean hasMoved = false; @@ -69,10 +64,7 @@ public class TimerView extends View implements AmbientModeListener this.activity = (WearableActivity) ctx; step = 0; - totalTime = MainActivity.DEFAULT_INITIAL_TIME; - remainingTime = totalTime; - isRunning = false; hasMoved = false; hasLongPressed = false; stimer = null; @@ -121,55 +113,17 @@ public class TimerView extends View implements AmbientModeListener paintAmbient.setTextAlign(Paint.Align.CENTER); } - public void tick() - { - long currentTime = System.currentTimeMillis(); - - step = (step + 1) % 2; - - if (remainingTime <= 0) - { - isRunning = false; - } - - if (isRunning) - { - remainingTime -= (currentTime - lastTick); - - if (remainingTime <= 0) - { - step = 1; - isRunning = false; - remainingTime = totalTime; - vibrator.vibrate(VIBRATION_FINISH, -1); - - PowerManager powerManager = - (PowerManager) activity.getSystemService(Activity.POWER_SERVICE); - PowerManager.WakeLock wakeLock = powerManager.newWakeLock( - (PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | - PowerManager.ACQUIRE_CAUSES_WAKEUP), "MyWakelockTag"); - wakeLock.acquire(500); - } - } - - lastTick = currentTime; - } - - public long getMillisecondsUntilNextMinute() + public void onTimeout() { - if (!isRunning) return -1; - return remainingTime % 60000; - } - - public long getTime() - { - return totalTime; - } - - public void setTime(long totalTime) - { - this.totalTime = totalTime; - this.remainingTime = totalTime; + step = 0; + vibrator.vibrate(VIBRATION_FINISH, -1); + + PowerManager powerManager = + (PowerManager) activity.getSystemService(Activity.POWER_SERVICE); + PowerManager.WakeLock wakeLock = powerManager.newWakeLock( + PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, + "MyWakelockTag"); + wakeLock.acquire(5000); } @Override @@ -195,6 +149,8 @@ public class TimerView extends View implements AmbientModeListener paint = paintInteractive; if (ambientMode) paint = paintAmbient; + step = (step + 1) % 2; + clearBackground(canvas); drawTimer(canvas); drawCurrentTime(canvas); @@ -226,6 +182,8 @@ public class TimerView extends View implements AmbientModeListener else paint.setColor(primaryColor); long minutes; + long remainingTime = stimer.getRemainingTime(); + if (ambientMode) { minutes = (long) (60 * Math.ceil(remainingTime / 1000 / 60.0)); @@ -238,7 +196,7 @@ public class TimerView extends View implements AmbientModeListener minutes = (long) (60 * Math.floor(remainingTime / 1000 / 60.0)); long seconds = remainingTime / 1000 % 60; - if (isRunning || step == 1) + if (stimer.isRunning() || step == 1) { paint.setTextSize(size * 0.25f); float minutesWidth = paint.measureText(String.format("%d", minutes / 60)); @@ -273,14 +231,16 @@ public class TimerView extends View implements AmbientModeListener private void clearBackground(Canvas canvas) { - paint.setColor(backgroundColor); + if(ambientMode) paint.setColor(Color.BLACK); + else paint.setColor(backgroundColor); + canvas.drawRect(screenRect, paint); } @Override public void onEnterAmbient(Bundle ambientDetails) { - if (!isRunning) activity.finishAffinity(); + if (!stimer.isRunning()) activity.finishAffinity(); ambientMode = true; Log.d(TAG, "onEnterAmbient()"); @@ -302,7 +262,8 @@ public class TimerView extends View implements AmbientModeListener class TouchListener implements View.OnTouchListener { private float prevY; - private long prevTime; + private float prevX; + private long prevDy; @Override public boolean onTouch(View v, MotionEvent event) @@ -313,31 +274,35 @@ public class TimerView extends View implements AmbientModeListener { case MotionEvent.ACTION_DOWN: prevY = event.getY(); - prevTime = remainingTime; + prevX = event.getX(); hasMoved = false; hasLongPressed = false; break; case MotionEvent.ACTION_MOVE: - float dy = (event.getY() - prevY) / box; + int dy = (int) ((prevY - event.getY()) / box); + int dx = (int) ((prevX - event.getX()) / box); + if (Math.abs(dy) < 1) break; - hasMoved = true; - if (isRunning) break; - totalTime = Math.max(GRANULARITY, prevTime - (long) dy * GRANULARITY); - totalTime = (totalTime / GRANULARITY) * GRANULARITY; - remainingTime = totalTime; + hasMoved = true; + if (dy == prevDy) break; + + stimer.increment(dy > 0 ? 1 : -1); - step = 1; + step = 0; + prevDy = dy; + prevY = event.getY(); invalidate(); break; case MotionEvent.ACTION_UP: if (hasMoved) break; if (hasLongPressed) break; + prevDy = -100; - isRunning = !isRunning; + stimer.flip(); vibrator.vibrate(80); invalidate(); @@ -355,8 +320,7 @@ public class TimerView extends View implements AmbientModeListener { if (hasMoved) return false; - remainingTime = totalTime; - isRunning = false; + stimer.reset(); vibrator.vibrate(250); hasLongPressed = true;