/*
* Copyright (C) Winson Chiu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cw.kop.autobackground.settings;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.media.ThumbnailUtils;
import android.os.Bundle;
import android.os.Handler;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.InputType;
import android.text.format.Time;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TimePicker;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.Wearable;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import cw.kop.autobackground.DialogFactory;
import cw.kop.autobackground.MainActivity;
import cw.kop.autobackground.OptionData;
import cw.kop.autobackground.OptionsListAdapter;
import cw.kop.autobackground.R;
import cw.kop.autobackground.RecyclerViewListClickListener;
import cw.kop.autobackground.files.FileHandler;
import cw.kop.autobackground.shared.WearConstants;
public class WearSettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener, View.OnTouchListener, View.OnClickListener {
private static final String TAG = WearSettingsFragment.class.getName();
private static final float SHADOW_RADIUS = 5f;
private Context appContext;
private GoogleApiClient googleApiClient;
private boolean isWearConnected = false;
private Handler handler;
private DateFormat timeFormat;
private ImageView watchBackground;
private RelativeLayout watchContainer;
private RecyclerView recyclerView;
private ListView preferenceList;
private IntentFilter intentFilter;
private SurfaceView surfaceView;
private Canvas canvas;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case MainActivity.LOAD_NAV_PICTURE:
loadImageFile();
redraw();
break;
case MainActivity.DRAWER_OPENED:
surfaceView.setVisibility(View.GONE);
break;
case MainActivity.DRAWER_CLOSED:
surfaceView.setVisibility(View.VISIBLE);
break;
}
}
};
private Bitmap imageBitmap;
private float tickRadius = 0.80f;
private float separatorWidth = 0f;
private float hourRadius = 1f;
private float minuteRadius = 1f;
private float secondRadius = 1f;
private float tickWidth = 5f;
private float hourWidth = 5f;
private float minuteWidth = 5f;
private float secondWidth = 5f;
private long timeOffset = 0l;
private String timeSeparator = ":";
private float xOffset;
private Paint bitmapPaint;
private Paint indicatorPaint;
private Paint hourPaint;
private Paint minutePaint;
private Paint secondPaint;
private String[] options;
private String[] optionDescriptions;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences_wear);
handler = new Handler(appContext.getMainLooper());
intentFilter = new IntentFilter();
intentFilter.addAction(MainActivity.LOAD_NAV_PICTURE);
intentFilter.addAction(MainActivity.DRAWER_OPENED);
intentFilter.addAction(MainActivity.DRAWER_CLOSED);
bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(false);
bitmapPaint.setDither(true);
indicatorPaint = new Paint();
indicatorPaint.setStrokeCap(Paint.Cap.BUTT);
indicatorPaint.setTextAlign(Paint.Align.LEFT);
hourPaint = new Paint();
hourPaint.setStrokeCap(Paint.Cap.BUTT);
hourPaint.setTextAlign(Paint.Align.LEFT);
minutePaint = new Paint();
minutePaint.setStrokeCap(Paint.Cap.BUTT);
minutePaint.setTextAlign(Paint.Align.LEFT);
secondPaint = new Paint();
secondPaint.setStrokeCap(Paint.Cap.BUTT);
secondPaint.setTextAlign(Paint.Align.LEFT);
options = getResources().getStringArray(R.array.wear_time_options);
optionDescriptions = getResources().getStringArray(R.array.wear_time_options_descriptions);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
appContext = activity;
}
@Override
public void onDetach() {
appContext = null;
super.onDetach();
}
@Override
public void onStart() {
super.onStart();
googleApiClient = new GoogleApiClient.Builder(appContext)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle connectionHint) {
isWearConnected = true;
}
@Override
public void onConnectionSuspended(int cause) {
isWearConnected = false;
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
isWearConnected = false;
}
})
// Request access only to the Wearable API
.addApi(Wearable.API)
.build();
googleApiClient.connect();
}
@Override
public void onStop() {
googleApiClient.disconnect();
super.onStop();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
View view;
if (displayMetrics.widthPixels > displayMetrics.heightPixels) {
view = inflater.inflate(R.layout.wear_settings_layout_landscape, container, false);
watchContainer = (RelativeLayout) view.findViewById(R.id.watch_face_container);
watchContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int height = watchBackground.getHeight();
ViewGroup.LayoutParams watchContainerParams = watchContainer.getLayoutParams();
watchContainerParams.height = height;
watchContainerParams.width = height;
watchContainer.setLayoutParams(watchContainerParams);
watchContainer.setPadding(Math.round(height * 0.278f),
Math.round(height * 0.23f),
Math.round(height * 0.278f),
Math.round(height * 0.33f));
watchContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
redraw();
}
});
watchContainer.setOnClickListener(this);
watchBackground = (ImageView) view.findViewById(R.id.watch_face_background);
watchBackground.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getView() == null) {
return;
}
ViewGroup.LayoutParams watchContainerParams = watchBackground.getLayoutParams();
watchContainerParams.width = watchBackground.getHeight();
watchBackground.setLayoutParams(watchContainerParams);
watchBackground.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
else {
view = inflater.inflate(R.layout.wear_settings_layout, container, false);
watchContainer = (RelativeLayout) view.findViewById(R.id.watch_face_container);
watchContainer.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int width = displayMetrics.widthPixels;
ViewGroup.LayoutParams watchContainerParams = watchContainer.getLayoutParams();
watchContainerParams.height = width;
watchContainerParams.width = width;
watchContainer.setLayoutParams(watchContainerParams);
watchContainer.setPadding(Math.round(width * 0.278f),
Math.round(width * 0.23f),
Math.round(width * 0.278f),
Math.round(width * 0.33f));
watchContainer.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
redraw();
}
});
watchContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
preferenceList.setVisibility(View.VISIBLE);
recyclerView.setAdapter(null);
recyclerView.setVisibility(View.GONE);
}
});
watchBackground = (ImageView) view.findViewById(R.id.watch_face_background);
watchBackground.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getView() == null) {
return;
}
ViewGroup.LayoutParams watchContainerParams = watchBackground.getLayoutParams();
watchContainerParams.height = watchBackground.getWidth();
watchBackground.setLayoutParams(watchContainerParams);
watchBackground.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
surfaceView = (SurfaceView) view.findViewById(R.id.surface_view);
// surfaceView.setZOrderOnTop(true);
surfaceView.setOnClickListener(this);
surfaceView.setOnTouchListener(this);
SurfaceHolder holder = surfaceView.getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
loadImageFile();
redraw();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
loadImageFile();
redraw();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
recyclerView = (RecyclerView) view.findViewById(R.id.watch_options_list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
preferenceList = (ListView) view.findViewById(android.R.id.list);
Button syncButton = (Button) view.findViewById(R.id.sync_button);
syncButton.setText("Sync Settings");
syncButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "syncButton pressed");
syncSettings();
}
});
findPreference("wear_time_type").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
DialogFactory.ListDialogListener listDialogListener = new DialogFactory.ListDialogListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view,
int position,
long id) {
switch (position) {
case 0:
AppSettings.setTimeType(AppSettings.DIGITAL);
recyclerView.setAdapter(null);
preferenceList.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
redraw();
break;
case 1:
AppSettings.setTimeType(AppSettings.ANALOG);
recyclerView.setAdapter(null);
preferenceList.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
redraw();
break;
}
dismissDialog();
}
};
DialogFactory.showListDialog(appContext,
"Watch face",
listDialogListener,
R.array.wear_time_types);
return true;
}
});
findPreference("wear_time_adjust").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
DialogFactory.TimeDialogListener listener = new DialogFactory.TimeDialogListener() {
@Override
public void onTimeSet(TimePicker view, int hour, int minute) {
Time time = new Time();
time.setToNow();
long offset = (hour - time.hour) * 3600000 + (minute - time.minute) * 60000;
Log.i(TAG, "Time offset set: " + offset);
AppSettings.setTimeOffset(offset);
this.dismissDialog();
redraw();
}
};
DialogFactory.showTimeDialog(appContext,
"Enter time",
listener,
-1,
-1);
return true;
}
});
return view;
}
private void setPaints() {
timeOffset = AppSettings.getTimeOffset();
timeSeparator = AppSettings.getSeparatorText();
indicatorPaint.setAntiAlias(true);
hourPaint.setAntiAlias(true);
minutePaint.setAntiAlias(true);
secondPaint.setAntiAlias(true);
indicatorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
hourPaint.setStyle(Paint.Style.FILL_AND_STROKE);
minutePaint.setStyle(Paint.Style.FILL_AND_STROKE);
secondPaint.setStyle(Paint.Style.FILL_AND_STROKE);
indicatorPaint.setColor(AppSettings.getSeparatorColor());
hourPaint.setColor(AppSettings.getHourColor());
minutePaint.setColor(AppSettings.getMinuteColor());
secondPaint.setColor(AppSettings.getSecondColor());
indicatorPaint.setShadowLayer(SHADOW_RADIUS,
0f,
0f,
AppSettings.getSeparatorShadowColor());
hourPaint.setShadowLayer(SHADOW_RADIUS, 0f, 0f, AppSettings.getHourShadowColor());
minutePaint.setShadowLayer(SHADOW_RADIUS,
0f,
0f,
AppSettings.getMinuteShadowColor());
secondPaint.setShadowLayer(SHADOW_RADIUS,
0f,
0f,
AppSettings.getSecondShadowColor());
tickRadius = AppSettings.getTickLengthRatio();
hourRadius = AppSettings.getHourLengthRatio();
minuteRadius = AppSettings.getMinuteLengthRatio();
secondRadius = AppSettings.getSecondLengthRatio();
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
tickWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppSettings.getTickWidth(),
displayMetrics);
hourWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppSettings.getHourWidth(),
displayMetrics);
minuteWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, AppSettings.getMinuteWidth(), displayMetrics);
secondWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
AppSettings.getSecondWidth(),
displayMetrics);
Log.d(TAG, "surfaceView width: " + surfaceView.getWidth() + " surfaceView height: " + surfaceView.getHeight());
float textSize = surfaceView.getHeight() / 4;
float radius = surfaceView.getWidth() / 2;
float width = (float) Math.sqrt(Math.pow(radius, 2f) - Math.pow(textSize, 2f)) * 2f;
float textScale = 1.0f;
xOffset = radius - width / 2f;
indicatorPaint.setTextSize(textSize);
hourPaint.setTextSize(textSize);
minutePaint.setTextSize(textSize);
secondPaint.setTextSize(textSize);
indicatorPaint.setTextScaleX(textScale);
hourPaint.setTextScaleX(textScale);
minutePaint.setTextScaleX(textScale);
secondPaint.setTextScaleX(textScale);
while (getTimeWidth() > width) {
Log.d(TAG, "getTimeWidth: " + getTimeWidth());
Log.d(TAG, "width: " + width);
textScale -= 0.05f;
indicatorPaint.setTextScaleX(textScale);
hourPaint.setTextScaleX(textScale);
minutePaint.setTextScaleX(textScale);
secondPaint.setTextScaleX(textScale);
}
separatorWidth = indicatorPaint.measureText(timeSeparator);
if (AppSettings.getTimeType().equals(AppSettings.DIGITAL)) {
indicatorPaint.setStrokeWidth(1.0f);
}
else {
indicatorPaint.setStrokeWidth(tickWidth);
}
}
private float getTimeWidth() {
float width = 0;
width += hourPaint.measureText("00");
width += minutePaint.measureText("00");
width += secondPaint.measureText("00");
width += indicatorPaint.measureText(timeSeparator);
width += indicatorPaint.measureText(timeSeparator);
return width;
}
private void loadImageFile() {
new Thread(new Runnable() {
@Override
public void run() {
float sideLength = surfaceView.getWidth();
Log.i(TAG, "sideLength: " + sideLength);
if (sideLength > 0) {
if (FileHandler.getCurrentBitmapFile() != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(FileHandler.getCurrentBitmapFile().getAbsolutePath(), options);
options.inJustDecodeBounds = false;
int sampleSize = 1;
float longestLength = options.outWidth > options.outHeight ? options.outWidth : options.outHeight;
while (longestLength / (sampleSize + 1) > sideLength) {
sampleSize++;
}
options.inSampleSize = sampleSize;
final Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(FileHandler.getCurrentBitmapFile().getAbsolutePath(), options),
Math.round(sideLength),
Math.round(sideLength));
handler.post(new Runnable() {
@Override
public void run() {
if (imageBitmap != null) {
try {
imageBitmap.recycle();
}
catch (Exception e) {
}
}
imageBitmap = bitmap;
redraw();
}
});
}
}
}
}).start();
}
private void redraw() {
if (AppSettings.getTimeType().equals(AppSettings.DIGITAL)) {
drawDigital();
}
else {
drawAnalog();
}
}
private void drawDigital() {
canvas = surfaceView.getHolder().lockCanvas();
if (canvas == null) {
return;
}
canvas.drawColor(0xFFFF0000);
setPaints();
Time time = new Time();
time.setToNow();
time.set(time.toMillis(false) + timeOffset);
float centerX = watchContainer.getWidth() * 0.222f;
float centerY = watchContainer.getHeight() * 0.222f;
if (imageBitmap != null) {
canvas.drawBitmap(imageBitmap, 0, 0, bitmapPaint);
}
float x = xOffset + (time.hour < 10 ? hourPaint.measureText("0") : 0);
float hourWidth = hourPaint.measureText("" + time.hour);
float minuteWidth = minutePaint.measureText(String.format("%02d", time.minute));
canvas.drawText("" + time.hour, x, centerY, hourPaint);
canvas.drawText("" + time.hour, x, centerY, hourPaint);
canvas.drawText("" + time.hour, x, centerY, hourPaint);
canvas.drawText("" + time.hour, x, centerY, hourPaint);
canvas.drawText("" + time.hour, x, centerY, hourPaint);
x += hourPaint.measureText("" + time.hour);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
x += separatorWidth;
canvas.drawText(String.format("%02d", time.minute), x, centerY, minutePaint);
canvas.drawText(String.format("%02d", time.minute), x, centerY, minutePaint);
canvas.drawText(String.format("%02d", time.minute), x, centerY, minutePaint);
canvas.drawText(String.format("%02d", time.minute), x, centerY, minutePaint);
canvas.drawText(String.format("%02d", time.minute), x, centerY, minutePaint);
x += minutePaint.measureText(String.format("%02d", time.minute));
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
canvas.drawText(timeSeparator, x, centerY, indicatorPaint);
x += separatorWidth;
canvas.drawText(String.format("%02d", time.second), x, centerY,
secondPaint);
canvas.drawText(String.format("%02d", time.second), x, centerY,
secondPaint);
canvas.drawText(String.format("%02d", time.second), x, centerY,
secondPaint);
canvas.drawText(String.format("%02d", time.second), x, centerY,
secondPaint);
canvas.drawText(String.format("%02d", time.second), x, centerY,
secondPaint);
surfaceView.getHolder().unlockCanvasAndPost(canvas);
}
private void drawAnalog() {
if (!AppSettings.getTimeType().equals(AppSettings.ANALOG)) {
return;
}
canvas = surfaceView.getHolder().lockCanvas();
if (canvas == null) {
return;
}
canvas.drawColor(0xFFFF0000);
setPaints();
if (imageBitmap != null) {
canvas.drawBitmap(imageBitmap, 0, 0, bitmapPaint);
}
// Time time = new Time();
// time.setToNow();
// time.set(time.toMillis(false) + AppSettings.getTimeOffset());
//
// float hour = time.hour + time.minute / 60f;
// float minute = time.minute + time.second / 60f;
// float second = time.second;
float centerX = watchContainer.getWidth() * 0.222f;
float centerY = watchContainer.getHeight() * 0.222f;
float radius = centerX;
// Draw tick marks
for (int i = 0; i < 12; i++) {
canvas.drawLine(
(float) (centerX + (radius * (100f - tickRadius) / 100f) * Math.cos(Math.toRadians(i * 30f))),
(float) (centerY + (radius * (100f - tickRadius) / 100f) * Math.sin(Math.toRadians(i * 30f))),
(float) (centerX + (radius) * Math.cos(Math.toRadians(i * 30f))),
(float) (centerY + (radius) * Math.sin(Math.toRadians(i * 30f))),
indicatorPaint);
}
// Draw clock hands
Path hourPath = new Path();
hourPath.moveTo((float) (centerX + hourWidth / 2f * Math.cos(Math.toRadians(90f))),
(float) (centerY + hourWidth / 2f * Math.sin(Math.toRadians(90f))));
hourPath.quadTo(
(float) (centerX - (hourWidth / 2f) * Math.cos(Math.toRadians(0f))),
(float) (centerY - (hourWidth / 2f) * Math.sin(Math.toRadians(0f))),
(float) (centerX + hourWidth / 2f * Math.cos(Math.toRadians(270f))),
(float) (centerY + hourWidth / 2f * Math.sin(Math.toRadians(270f))));
hourPath.lineTo((float) (centerX + (radius * hourRadius / 100f) * Math.cos(Math.toRadians(0f))),
(float) (centerY + (radius * hourRadius / 100f) * Math.sin(Math.toRadians(0f))));
hourPath.close();
canvas.drawPath(hourPath, hourPaint);
canvas.drawPath(hourPath, hourPaint);
canvas.drawPath(hourPath, hourPaint);
canvas.drawPath(hourPath, hourPaint);
canvas.drawPath(hourPath, hourPaint);
Path minutePath = new Path();
minutePath.moveTo((float) (centerX + minuteWidth / 2f * Math.cos(Math.toRadians(0f))),
(float) (centerY + minuteWidth / 2f * Math.sin(Math.toRadians(0f))));
minutePath.quadTo(
(float) (centerX - (minuteWidth / 2f) * Math.cos(Math.toRadians(-180f))),
(float) (centerY - (minuteWidth / 2f) * Math.sin(Math.toRadians(-180f))),
(float) (centerX + minuteWidth / 2f * Math.cos(Math.toRadians(90f))),
(float) (centerY + minuteWidth / 2f * Math.sin(Math.toRadians(90f))));
minutePath.lineTo((float) (centerX + (radius * minuteRadius / 100f) * Math.cos(Math.toRadians(-90f))),
(float) (centerY + (radius * minuteRadius / 100f) * Math.sin(Math.toRadians(-90f))));
minutePath.close();
canvas.drawPath(minutePath, minutePaint);
canvas.drawPath(minutePath, minutePaint);
canvas.drawPath(minutePath, minutePaint);
canvas.drawPath(minutePath, minutePaint);
canvas.drawPath(minutePath, minutePaint);
Path secondPath = new Path();
secondPath.moveTo((float) (centerX + secondWidth / 2f * Math.cos(Math.toRadians(225f))),
(float) (centerY + secondWidth / 2f * Math.sin(Math.toRadians(225f))));
secondPath.quadTo(
(float) (centerX - (secondWidth / 2f) * Math.cos(Math.toRadians(45f))),
(float) (centerY - (secondWidth / 2f) * Math.sin(Math.toRadians(45f))),
(float) (centerX + secondWidth / 2f * Math.cos(Math.toRadians(315f))),
(float) (centerY + secondWidth / 2f * Math.sin(Math.toRadians(315f))));
secondPath.lineTo((float) (centerX + (radius * secondRadius / 100f) * Math.cos(Math.toRadians(
135f))),
(float) (centerY + (radius * secondRadius / 100f) * Math.sin(Math.toRadians(
135f))));
secondPath.close();
canvas.drawPath(secondPath, secondPaint);
canvas.drawPath(secondPath, secondPaint);
canvas.drawPath(secondPath, secondPaint);
canvas.drawPath(secondPath, secondPaint);
canvas.drawPath(secondPath, secondPaint);
surfaceView.getHolder().unlockCanvasAndPost(canvas);
}
private void syncSettings() {
new Thread(new Runnable() {
@Override
public void run() {
PutDataMapRequest dataMap = PutDataMapRequest.create(WearConstants.SETTINGS);
dataMap.getDataMap().putLong(WearConstants.TIME, new Date().getTime());
dataMap.getDataMap().putString(WearConstants.TIME_TYPE, AppSettings.getTimeType());
dataMap.getDataMap().putLong(WearConstants.TIME_OFFSET, AppSettings.getTimeOffset());
dataMap.getDataMap().putBoolean(WearConstants.USE_TIME_PALETTE,
AppSettings.useTimePalette());
dataMap.getDataMap().putString(WearConstants.SEPARATOR_TEXT,
AppSettings.getSeparatorText());
dataMap.getDataMap().putInt(WearConstants.SEPARATOR_COLOR,
AppSettings.getSeparatorColor());
dataMap.getDataMap().putInt(WearConstants.SEPARATOR_SHADOW_COLOR,
AppSettings.getSeparatorShadowColor());
dataMap.getDataMap().putInt(WearConstants.HOUR_COLOR,
AppSettings.getHourColor());
dataMap.getDataMap().putInt(WearConstants.HOUR_SHADOW_COLOR,
AppSettings.getHourShadowColor());
dataMap.getDataMap().putInt(WearConstants.MINUTE_COLOR,
AppSettings.getMinuteColor());
dataMap.getDataMap().putInt(WearConstants.MINUTE_SHADOW_COLOR,
AppSettings.getMinuteShadowColor());
dataMap.getDataMap().putInt(WearConstants.SECOND_COLOR,
AppSettings.getSecondColor());
dataMap.getDataMap().putInt(WearConstants.SECOND_SHADOW_COLOR,
AppSettings.getSecondShadowColor());
dataMap.getDataMap().putFloat(WearConstants.TICK_LENGTH_RATIO, AppSettings.getTickLengthRatio());
dataMap.getDataMap().putFloat(WearConstants.HOUR_LENGTH_RATIO, AppSettings.getHourLengthRatio());
dataMap.getDataMap().putFloat(WearConstants.MINUTE_LENGTH_RATIO, AppSettings.getMinuteLengthRatio());
dataMap.getDataMap().putFloat(WearConstants.SECOND_LENGTH_RATIO, AppSettings.getSecondLengthRatio());
dataMap.getDataMap().putFloat(WearConstants.TICK_WIDTH, AppSettings.getTickWidth());
dataMap.getDataMap().putFloat(WearConstants.HOUR_WIDTH, AppSettings.getHourWidth());
dataMap.getDataMap().putFloat(WearConstants.MINUTE_WIDTH, AppSettings.getMinuteWidth());
dataMap.getDataMap().putFloat(WearConstants.SECOND_WIDTH, AppSettings.getSecondWidth());
Wearable.DataApi.putDataItem(googleApiClient, dataMap.asPutDataRequest());
}
}).start();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
float sideLength = surfaceView.getWidth();
float x = event.getX();
float y = event.getY();
if (AppSettings.getTimeType().equals(AppSettings.DIGITAL)) {
float hourWidth = hourPaint.measureText("00");
float minuteWidth = minutePaint.measureText("00");
if (y > sideLength / 2) {
showIndicatorOptions();
}
else if (xOffset < x && x < xOffset + hourWidth) {
showHourOptions(2);
}
else if (xOffset + hourWidth + separatorWidth < x & x < xOffset + hourWidth + separatorWidth + minuteWidth) {
showMinuteOptions(2);
}
else if (xOffset + hourWidth + separatorWidth + minuteWidth + separatorWidth< x) {
showSecondOptions(2);
}
else {
showIndicatorOptions();
}
}
else {
double touchRadius = Math.hypot(Math.abs(x - sideLength / 2), Math.abs(y - sideLength / 2));
if (touchRadius > 0.4 * sideLength) {
showTickOptions();
}
else if (y < sideLength / 2 && x < sideLength - y) {
showMinuteOptions(4);
}
else if (x > sideLength / 2) {
showHourOptions(4);
}
else {
showSecondOptions(4);
}
}
recyclerView.setVisibility(View.VISIBLE);
preferenceList.setVisibility(View.GONE);
}
return false;
}
private void showIndicatorOptions() {
String[] titles = new String[] {"Separator Color",
"Separator Shadow Color",
"Separator"};
String[] summaries = new String[] {"Color of separator",
"Color of separator shadow",
"Text to separate time sections"};
int[] icons = new int[] {R.drawable.ic_text_format_white_24dp,
R.drawable.ic_color_lens_white_24dp,
R.drawable.ic_color_lens_white_24dp};
ArrayList<OptionData> optionsList = new ArrayList<>();
for (int index = 0; index < titles.length; index++) {
optionsList.add(new OptionData(titles[index],
summaries[index],
icons[index]));
}
final RecyclerViewListClickListener listener = new RecyclerViewListClickListener() {
@Override
public void onClick(int position, String title, int drawable) {
switch (position) {
case 0:
DialogFactory.ColorDialogListener separatorColorDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSeparatorColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter separator color:",
separatorColorDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getSeparatorColor());
break;
case 1:
DialogFactory.ColorDialogListener separatorShadowColorDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSeparatorShadowColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter separator shadow color:",
separatorShadowColorDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getSeparatorShadowColor());
break;
case 2:
DialogFactory.InputDialogListener separatorTextDialogListener = new DialogFactory.InputDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSeparatorText(getEditTextString());
redraw();
this.dismissDialog();
}
};
DialogFactory.showInputDialog(appContext,
"Enter separator text",
"",
AppSettings.getSeparatorText(),
separatorTextDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
InputType.TYPE_CLASS_TEXT);
break;
}
}
};
OptionsListAdapter titlesAdapter = new OptionsListAdapter(appContext,
optionsList,
-1,
listener);
recyclerView.setAdapter(titlesAdapter);
}
private void showTickOptions() {
String[] titles = new String[] {"Tick Marking Color",
"Tick Marking Shadow Color",
"Tick Marking Length",
"Tick Marking Width"};
String[] summaries = new String[] {"Color of marking",
"Color of marking shadow",
"Marking Length",
"Marking Width"};
ArrayList<OptionData> optionsList = new ArrayList<>();
for (int index = 0; index < titles.length; index++) {
optionsList.add(new OptionData(titles[index],
summaries[index],
R.drawable.ic_color_lens_white_24dp));
}
RecyclerViewListClickListener listener = new RecyclerViewListClickListener() {
@Override
public void onClick(int position, String title, int drawable) {
switch (position) {
case 0:
DialogFactory.ColorDialogListener minuteDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSeparatorColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter tick color:",
minuteDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getSeparatorColor());
break;
case 1:
DialogFactory.ColorDialogListener minuteShadowDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSeparatorShadowColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter tick shadow color:",
minuteShadowDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getSeparatorShadowColor());
break;
case 2:
DialogFactory.SeekBarDialogListener minuteLengthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setTickLengthRatio(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Tick marking length", "% of radius", minuteLengthDialogListener, 1000, Math.round(AppSettings.getTickLengthRatio() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
case 3:
DialogFactory.SeekBarDialogListener minuteWidthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setTickWidth(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Tick marking width", "dp", minuteWidthDialogListener, 200, Math.round(AppSettings.getTickWidth() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
}
}
};
OptionsListAdapter titlesAdapter = new OptionsListAdapter(appContext,
optionsList,
-1,
listener);
recyclerView.setAdapter(titlesAdapter);
}
private void showMinuteOptions(int numToShow) {
ArrayList<OptionData> optionsList = new ArrayList<>();
for (int index = 0; index < numToShow; index++) {
optionsList.add(new OptionData(options[index].replaceAll("TYPE", "Minute"),
optionDescriptions[index].replaceAll("TYPE", "Minute"),
R.drawable.ic_color_lens_white_24dp));
}
RecyclerViewListClickListener listener = new RecyclerViewListClickListener() {
@Override
public void onClick(int position, String title, int drawable) {
switch (position) {
case 0:
DialogFactory.ColorDialogListener minuteDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setMinuteColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter minute color:",
minuteDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getMinuteColor());
break;
case 1:
DialogFactory.ColorDialogListener minuteShadowDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setMinuteShadowColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter minute shadow color:",
minuteShadowDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getMinuteShadowColor());
break;
case 2:
DialogFactory.SeekBarDialogListener minuteLengthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setMinuteLengthRatio(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Minute hand length", "% of radius", minuteLengthDialogListener, 1000, Math.round(AppSettings.getMinuteLengthRatio() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
case 3:
DialogFactory.SeekBarDialogListener minuteWidthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setMinuteWidth(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Minute hand width", "dp", minuteWidthDialogListener, 200, Math.round(AppSettings.getMinuteWidth() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
}
}
};
OptionsListAdapter titlesAdapter = new OptionsListAdapter(appContext,
optionsList,
-1,
listener);
recyclerView.setAdapter(titlesAdapter);
}
private void showHourOptions(int numToShow) {
ArrayList<OptionData> optionsList = new ArrayList<>();
for (int index = 0; index < numToShow; index++) {
optionsList.add(new OptionData(options[index].replaceAll("TYPE", "Hour"),
optionDescriptions[index].replaceAll("TYPE", "Hour"),
R.drawable.ic_color_lens_white_24dp));
}
RecyclerViewListClickListener listener = new RecyclerViewListClickListener() {
@Override
public void onClick(int position, String title, int drawable) {
switch (position) {
case 0:
DialogFactory.ColorDialogListener hourDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setHourColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter hour color:",
hourDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getHourColor());
break;
case 1:
DialogFactory.ColorDialogListener hourShadowDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setHourShadowColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter hour shadow color:",
hourShadowDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getHourShadowColor());
break;
case 2:
DialogFactory.SeekBarDialogListener hourLengthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setHourLengthRatio(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Hour hand length", "% of radius", hourLengthDialogListener, 1000, Math.round(AppSettings.getHourLengthRatio() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
case 3:
DialogFactory.SeekBarDialogListener hourWidthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setHourWidth(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Hour hand width", "dp", hourWidthDialogListener, 200, Math.round(AppSettings.getHourWidth() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
}
}
};
OptionsListAdapter titlesAdapter = new OptionsListAdapter(appContext,
optionsList,
-1,
listener);
recyclerView.setAdapter(titlesAdapter);
}
private void showSecondOptions(int numToShow) {
ArrayList<OptionData> optionsList = new ArrayList<>();
for (int index = 0; index < numToShow; index++) {
optionsList.add(new OptionData(options[index].replaceAll("TYPE", "Second"),
optionDescriptions[index].replaceAll("TYPE", "Second"),
R.drawable.ic_color_lens_white_24dp));
}
RecyclerViewListClickListener listener = new RecyclerViewListClickListener() {
@Override
public void onClick(int position, String title, int drawable) {
switch (position) {
case 0:
DialogFactory.ColorDialogListener secondDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSecondColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter second color:",
secondDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getSecondColor());
break;
case 1:
DialogFactory.ColorDialogListener secondShadowDialogListener = new DialogFactory.ColorDialogListener() {
@Override
public void onClickRight(View v) {
AppSettings.setSecondShadowColor(getColorPickerView().getColor());
redraw();
this.dismissDialog();
}
};
DialogFactory.showColorPickerDialog(appContext,
"Enter second shadow color:",
secondShadowDialogListener,
-1,
R.string.cancel_button,
R.string.ok_button,
AppSettings.getSecondShadowColor());
break;
case 2:
DialogFactory.SeekBarDialogListener secondLengthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setSecondLengthRatio(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Second hand length", "% of radius", secondLengthDialogListener, 1000, Math.round(AppSettings.getSecondLengthRatio() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
case 3:
DialogFactory.SeekBarDialogListener secondWidthDialogListener = new DialogFactory.SeekBarDialogListener() {
@Override
public void onValueChanged(SeekBar seekBar,
int progress,
boolean fromUser) {
setValueText("" + (progress / 10f));
}
@Override
public void onClickRight(View v) {
AppSettings.setSecondWidth(getValue() / 10f);
redraw();
this.dismissDialog();
}
};
DialogFactory.showSeekBarDialog(appContext, "Second hand width", "dp", secondWidthDialogListener, 200, Math.round(AppSettings.getSecondWidth() * 10f), -1, R.string.cancel_button, R.string.ok_button);
break;
}
}
};
OptionsListAdapter titlesAdapter = new OptionsListAdapter(appContext,
optionsList,
-1,
listener);
recyclerView.setAdapter(titlesAdapter);
}
@Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(appContext).registerReceiver(broadcastReceiver,
intentFilter);
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
loadImageFile();
}
@Override
public void onPause() {
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
LocalBroadcastManager.getInstance(appContext).unregisterReceiver(broadcastReceiver);
syncSettings();
super.onPause();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (!((Activity) appContext).isFinishing()) {
}
}
private void sendMessage(final String messagePath, final String data) {
new Thread(new Runnable() {
@Override
public void run() {
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(
googleApiClient).await();
for (Node node : nodes.getNodes()) {
MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(
googleApiClient,
node.getId(),
messagePath,
data.getBytes()).await();
if (!result.getStatus().isSuccess()) {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(appContext,
"Error syncing to Wear",
Toast.LENGTH_LONG).show();
}
});
}
}
}
}).start();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.watch_face_container:
preferenceList.setVisibility(View.VISIBLE);
recyclerView.setAdapter(null);
recyclerView.setVisibility(View.GONE);
break;
}
}
}