/* * Copyright (C) 2014 weides@gmail.com * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.runnerup.view; import android.annotation.TargetApi; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Point; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.wearable.view.DotsPageIndicator; import android.support.wearable.view.FragmentGridPagerAdapter; import android.support.wearable.view.GridViewPager; import android.widget.LinearLayout; import org.runnerup.R; import org.runnerup.common.tracker.TrackerState; import org.runnerup.common.util.Constants; import org.runnerup.common.util.ValueModel; import org.runnerup.service.StateService; import org.runnerup.widget.MyDotsPageIndicator; import java.util.ArrayList; @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) public class MainActivity extends Activity implements Constants, ValueModel.ChangeListener<TrackerState> { private Handler handler = new Handler(); private GridViewPager pager; private StateService mStateService; final private ValueModel<TrackerState> trackerState = new ValueModel<TrackerState>(); final private ValueModel<Bundle> headers = new ValueModel<>(); private boolean pauseStep = false; private int scroll = 0; private boolean postScrollRightRunning = false; private static final int RUN_INFO_ROW = 0; private static final int PAUSE_RESUME_ROW = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pager = (GridViewPager) findViewById(R.id.pager); FragmentGridPagerAdapter pageAdapter = new PagerAdapter(getFragmentManager()); pager.setAdapter(pageAdapter); LinearLayout verticalDotsPageIndicator = (LinearLayout) findViewById(R.id.vert_page_indicator); MyDotsPageIndicator dot2 = new MyDotsPageIndicator(verticalDotsPageIndicator); DotsPageIndicator dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator); dotsPageIndicator.setPager(pager); dotsPageIndicator.setDotFadeWhenIdle(false); dotsPageIndicator.setDotFadeOutDelay(1000 * 3600 * 24); dotsPageIndicator.setOnPageChangeListener(dot2); dotsPageIndicator.setOnAdapterChangeListener(dot2); dot2.setPager(pager); } @Override protected void onStart() { super.onStart(); } @Override protected void onResume() { super.onResume(); getApplicationContext().bindService(new Intent(this, StateService.class), mStateServiceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onPause() { super.onPause(); if (mStateService != null) { mStateService.unregisterTrackerStateListener(this); mStateService.unregisterHeadersListener(this); } getApplicationContext().unbindService(mStateServiceConnection); mStateService = null; } @Override protected void onStop() { super.onStop(); } private class PagerAdapter extends FragmentGridPagerAdapter implements ValueModel.ChangeListener<TrackerState> { int currentRow = 0; int currentCol = 0; int rows = 1; int cols = 1; public PagerAdapter(FragmentManager fm) { super(fm); update(trackerState.get()); trackerState.registerChangeListener(this); } @Override public Fragment getFragment(int row, int col) { if (trackerState.get() == null) return new ConnectToPhoneFragment(); else if (mStateService == null) return new ConnectToPhoneFragment(); currentRow = row; currentCol = col; switch (trackerState.get()) { case INIT: case INITIALIZING: case CLEANUP: case ERROR: return new ConnectToPhoneFragment(); case INITIALIZED: return new StartFragment(); case CONNECTING: return new SearchingFragment(); case CONNECTED: return new StartFragment(); case STARTED: case PAUSED: case STOPPED: if (row == RUN_INFO_ROW) { if (pauseStep) { if (col == 0) return new CountdownFragment(); col--; // during pause step col=0 is CountDown } return RunInfoFragment.createForScreen(col, getRowsForScreen(col)); } else if (row == PAUSE_RESUME_ROW) { if (trackerState.get() == TrackerState.STOPPED) return new StoppedFragment(); else { return new PauseResumeFragment(); } } } return new ConnectToPhoneFragment(); } @Override public int getRowCount() { return rows; } @Override public int getColumnCount(int i) { if (pauseStep) return cols + 1; return cols; } @Override public void onValueChanged(ValueModel<TrackerState> obj, TrackerState oldValue, TrackerState newValue) { notifyDataSetChanged(); } @Override public void notifyDataSetChanged() { update(trackerState.get()); super.notifyDataSetChanged(); } private void update(TrackerState newValue) { if (newValue == null || mStateService == null) { cols = rows = 1; return; } switch (newValue) { case INIT: case INITIALIZING: case CLEANUP: case ERROR: case INITIALIZED: case CONNECTING: case CONNECTED: cols = rows = 1; break; case STARTED: case PAUSED: case STOPPED: cols = getScreensCount(); rows = 2; break; } } } private int getRowsForScreen(int col) { Bundle b = headers.get(); if (b == null) { System.err.println("getRowsForScreen(): headers == null"); return 1; } ArrayList<Integer> screens = b.getIntegerArrayList(Wear.RunInfo.SCREENS); if (screens == null) { System.err.println("getRowsForScreen(): screens == null"); return 1; } if (col > screens.size()) return 1; return screens.get(col); } private int getScreensCount() { Bundle b = headers.get(); if (b == null) { System.err.println("getScreensCount(): headers == null"); return 1; } ArrayList<Integer> screens = b.getIntegerArrayList(Wear.RunInfo.SCREENS); if (screens == null) { System.err.println("getScreensCount(): screens == null"); return 1; } return screens.size(); } Bundle getData(long lastUpdateTime) { if (mStateService == null) { return null; } return mStateService.getData(lastUpdateTime); } Bundle getHeaders(long lastUpdateTime) { if (mStateService == null) { return null; } return mStateService.getHeaders(lastUpdateTime); } public StateService getStateService() { return mStateService; } public void scrollToRunInfo() { Point curr = pager.getCurrentItem(); pager.setCurrentItem(RUN_INFO_ROW, curr.x, true); } public void scrollRight() { Point curr = pager.getCurrentItem(); if (curr.y != RUN_INFO_ROW) return; if (getScreensCount() <= 1) return; int newx = (curr.x + 1) % getScreensCount(); pager.setCurrentItem(curr.y, newx, true); } private ServiceConnection mStateServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (mStateService == null) { mStateService = ((StateService.LocalBinder) service).getService(); mStateService.registerTrackerStateListener(MainActivity.this); mStateService.registerHeadersListener(MainActivity.this); } } @Override public void onServiceDisconnected(ComponentName name) { mStateService = null; } }; public TrackerState getTrackerState() { if (mStateService == null) return null; synchronized (trackerState) { return mStateService.getTrackerState(); } } @Override public void onValueChanged(ValueModel<TrackerState> obj, final TrackerState oldState, final TrackerState newState) { synchronized (trackerState) { runOnUiThread(new Runnable() { @Override public void run() { synchronized (trackerState) { trackerState.set(newState); } } }); } } public void registerTrackerStateListener(ValueModel.ChangeListener<TrackerState> listener) { synchronized (trackerState) { trackerState.registerChangeListener(listener); } } public void unregisterTrackerStateListener(ValueModel.ChangeListener<TrackerState> listener) { synchronized (trackerState) { trackerState.unregisterChangeListener(listener); } } void postScrollRight() { if (postScrollRightRunning) return; if (scroll > 0 && getScreensCount() > 1) { postScrollRightRunning = true; handler.postDelayed(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { postScrollRightRunning = false; postScrollRight(); scrollRight(); } }); } }, scroll * 1000); } } public void onValueChanged(final Bundle oldValue, final Bundle newValue) { synchronized (trackerState) { runOnUiThread(new Runnable() { @Override public void run() { synchronized (trackerState) { pauseStep = false; if (newValue != null) { pauseStep = newValue.getBoolean(Wear.RunInfo.PAUSE_STEP); scroll = newValue.getInt(Wear.RunInfo.SCROLL); } headers.set(newValue); pager.getAdapter().notifyDataSetChanged(); postScrollRight(); } } }); } } }