Separate logic from view

master
Alinson S. Xavier 10 years ago
parent a5be3c0693
commit 4b4207fbbf

@ -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);

@ -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;
}
}

@ -0,0 +1,6 @@
package org.isoron.simpletimer.model;
public interface SimpleTimerListener
{
public void onTimeout();
}

@ -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;