Reorganizing
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="uHabits" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$USER_HOME$/Android/uHabits" external.system.id="GRADLE" external.system.module.group="uHabits" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||||
<component name="FacetManager">
|
<component name="FacetManager">
|
||||||
<facet type="android-gradle" name="Android-Gradle">
|
<facet type="android-gradle" name="Android-Gradle">
|
||||||
<configuration>
|
<configuration>
|
||||||
@@ -12,8 +12,9 @@
|
|||||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
|
||||||
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
|
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
|
||||||
|
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||||
|
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||||
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
|
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
|
||||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||||
@@ -89,5 +90,4 @@
|
|||||||
<orderEntry type="library" exported="" name="ActiveAndroid" level="project" />
|
<orderEntry type="library" exported="" name="ActiveAndroid" level="project" />
|
||||||
<orderEntry type="library" exported="" name="support-annotations-22.0.0" level="project" />
|
<orderEntry type="library" exported="" name="support-annotations-22.0.0" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<application
|
<application
|
||||||
android:name="com.activeandroid.app.Application"
|
android:name="com.activeandroid.app.Application"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
|||||||
BIN
app/src/main/ic_launcher-web.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
@@ -6,6 +6,7 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -125,25 +126,24 @@ public class MainActivity extends Activity
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeCommand(Command command, boolean datasetChanged)
|
public void executeCommand(Command command)
|
||||||
{
|
{
|
||||||
executeCommand(command, datasetChanged, true);
|
executeCommand(command, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeCommand(Command command, boolean datasetChanged, boolean clearRedoStack)
|
|
||||||
|
public void executeCommand(Command command, boolean clearRedoStack)
|
||||||
{
|
{
|
||||||
undoList.push(command);
|
undoList.push(command);
|
||||||
if (undoList.size() > MAX_UNDO_LEVEL)
|
if (undoList.size() > MAX_UNDO_LEVEL)
|
||||||
undoList.removeLast();
|
undoList.removeLast();
|
||||||
if (clearRedoStack)
|
if (clearRedoStack)
|
||||||
redoList.clear();
|
redoList.clear();
|
||||||
|
|
||||||
command.execute();
|
command.execute();
|
||||||
|
listHabitsFragment.notifyDataSetChanged();
|
||||||
|
|
||||||
showToast(command.getExecuteStringId());
|
showToast(command.getExecuteStringId());
|
||||||
if (datasetChanged)
|
|
||||||
{
|
|
||||||
listHabitsFragment.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undo()
|
public void undo()
|
||||||
@@ -170,7 +170,7 @@ public class MainActivity extends Activity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Command last = redoList.pop();
|
Command last = redoList.pop();
|
||||||
executeCommand(last, true, false);
|
executeCommand(last, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showToast(Integer stringId)
|
private void showToast(Integer stringId)
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
@@ -14,148 +8,133 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
public class ReminderAlarmReceiver extends BroadcastReceiver
|
public class ReminderAlarmReceiver extends BroadcastReceiver
|
||||||
{
|
{
|
||||||
|
|
||||||
public static String ACTION_CHECK = "org.isoron.uhabits.ACTION_CHECK";
|
|
||||||
public static String ACTION_DISMISS = "org.isoron.uhabits.ACTION_DISMISS";
|
|
||||||
public static String ACTION_REMIND = "org.isoron.uhabits.ACTION_REMIND";
|
|
||||||
public static String ACTION_REMOVE_REMINDER = "org.isoron.uhabits.ACTION_REMOVE_REMINDER";
|
|
||||||
public static String ACTION_SNOOZE = "org.isoron.uhabits.ACTION_SNOOZE";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent)
|
|
||||||
{
|
|
||||||
String action = intent.getAction();
|
|
||||||
|
|
||||||
if(action.equals(ACTION_REMIND))
|
|
||||||
createNotification(context, intent.getData());
|
|
||||||
|
|
||||||
else if(action.equals(ACTION_DISMISS))
|
|
||||||
dismissAllHabits();
|
|
||||||
|
|
||||||
else if(action.equals(ACTION_CHECK))
|
|
||||||
checkHabit(context, intent.getData());
|
|
||||||
|
|
||||||
else if(action.equals(ACTION_SNOOZE))
|
public static String ACTION_CHECK = "org.isoron.uhabits.ACTION_CHECK";
|
||||||
snoozeHabit(context, intent.getData());
|
public static String ACTION_DISMISS = "org.isoron.uhabits.ACTION_DISMISS";
|
||||||
}
|
public static String ACTION_REMIND = "org.isoron.uhabits.ACTION_REMIND";
|
||||||
|
public static String ACTION_REMOVE_REMINDER = "org.isoron.uhabits.ACTION_REMOVE_REMINDER";
|
||||||
private void snoozeHabit(Context context, Uri data)
|
public static String ACTION_SNOOZE = "org.isoron.uhabits.ACTION_SNOOZE";
|
||||||
{
|
|
||||||
int delayMinutes = 15;
|
|
||||||
Habit habit = Habit.get(ContentUris.parseId(data));
|
|
||||||
MainActivity.createReminderAlarm(context, habit, new Date().getTime() + delayMinutes * 1000);
|
|
||||||
dismissNotification(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkHabit(Context context, Uri data)
|
|
||||||
{
|
|
||||||
Habit habit = Habit.get(ContentUris.parseId(data));
|
|
||||||
habit.toggleRepetitionToday();
|
|
||||||
habit.save();
|
|
||||||
dismissNotification(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dismissAllHabits()
|
|
||||||
{
|
|
||||||
for(Habit h : Habit.getHighlightedHabits())
|
|
||||||
{
|
|
||||||
Log.d("Alarm", String.format("Removing highlight from: %s", h.name));
|
|
||||||
h.highlight = 0;
|
|
||||||
h.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dismissNotification(Context context)
|
|
||||||
{
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context
|
|
||||||
.getSystemService(Activity.NOTIFICATION_SERVICE);
|
|
||||||
|
|
||||||
notificationManager.cancel(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void createNotification(Context context, Uri data)
|
|
||||||
{
|
|
||||||
Log.d("Alarm", "Alarm received!");
|
|
||||||
|
|
||||||
Habit habit = Habit.get(ContentUris.parseId(data));
|
|
||||||
|
|
||||||
if(habit.hasImplicitRepToday())
|
|
||||||
{
|
|
||||||
Log.d("Alarm", String.format("(%s) has implicit rep today", habit.name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
|
@Override
|
||||||
habit.highlight = 1;
|
public void onReceive(Context context, Intent intent)
|
||||||
habit.save();
|
{
|
||||||
|
String action = intent.getAction();
|
||||||
// Check if reminder has been turned off after alarm was scheduled
|
|
||||||
if(habit.reminder_hour == null)
|
if (action.equals(ACTION_REMIND)) createNotification(context, intent.getData());
|
||||||
return;
|
|
||||||
|
else if (action.equals(ACTION_DISMISS)) dismissAllHabits();
|
||||||
Intent contentIntent = new Intent(context, MainActivity.class);
|
|
||||||
contentIntent.setData(data);
|
else if (action.equals(ACTION_CHECK)) checkHabit(context, intent.getData());
|
||||||
PendingIntent contentPendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
|
|
||||||
|
else if (action.equals(ACTION_SNOOZE)) snoozeHabit(context, intent.getData());
|
||||||
Intent deleteIntent = new Intent(context, ReminderAlarmReceiver.class);
|
}
|
||||||
deleteIntent.setAction(ACTION_DISMISS);
|
|
||||||
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
|
private void snoozeHabit(Context context, Uri data)
|
||||||
|
{
|
||||||
Intent checkIntent = new Intent(context, ReminderAlarmReceiver.class);
|
int delayMinutes = 60;
|
||||||
checkIntent.setData(data);
|
Habit habit = Habit.get(ContentUris.parseId(data));
|
||||||
checkIntent.setAction(ACTION_CHECK);
|
MainActivity.createReminderAlarm(context, habit,
|
||||||
PendingIntent checkIntentPending = PendingIntent.getBroadcast(context, 0, checkIntent, 0);
|
new Date().getTime() + delayMinutes * 60 * 1000);
|
||||||
|
dismissNotification(context, habit);
|
||||||
Intent snoozeIntent = new Intent(context, ReminderAlarmReceiver.class);
|
}
|
||||||
snoozeIntent.setData(data);
|
|
||||||
snoozeIntent.setAction(ACTION_SNOOZE);
|
private void checkHabit(Context context, Uri data)
|
||||||
PendingIntent snoozeIntentPending = PendingIntent.getBroadcast(context, 0, snoozeIntent, 0);
|
{
|
||||||
|
Habit habit = Habit.get(ContentUris.parseId(data));
|
||||||
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
habit.toggleRepetitionToday();
|
||||||
|
habit.save();
|
||||||
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
|
dismissNotification(context, habit);
|
||||||
inboxStyle.setBigContentTitle("Habit Reminder:");
|
}
|
||||||
List<Habit> pendingHabits = Habit.getHighlightedHabits();
|
|
||||||
StringBuffer contentText = new StringBuffer();
|
private void dismissAllHabits()
|
||||||
for(Habit h : pendingHabits)
|
{
|
||||||
{
|
for (Habit h : Habit.getHighlightedHabits())
|
||||||
if(h.hasImplicitRepToday())
|
{
|
||||||
continue;
|
h.highlight = 0;
|
||||||
|
h.save();
|
||||||
inboxStyle.addLine(h.name);
|
}
|
||||||
if(contentText.length() > 0)
|
}
|
||||||
contentText.append(", ");
|
|
||||||
contentText.append(h.name);
|
private void dismissNotification(Context context, Habit habit)
|
||||||
Log.d("Alarm", String.format("Found highlighted: %s", h.name));
|
{
|
||||||
}
|
NotificationManager notificationManager =
|
||||||
|
(NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
|
||||||
Notification notification =
|
|
||||||
new NotificationCompat.Builder(context)
|
int notificationId = (int) (habit.getId() % Integer.MAX_VALUE);
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
notificationManager.cancel(notificationId);
|
||||||
.setContentTitle("Habit Reminder")
|
}
|
||||||
.setContentText(contentText)
|
|
||||||
.setContentIntent(contentPendingIntent)
|
|
||||||
.setDeleteIntent(deletePendingIntent)
|
private void createNotification(Context context, Uri data)
|
||||||
.addAction(R.drawable.ic_action_check, "Check", checkIntentPending)
|
{
|
||||||
.addAction(R.drawable.ic_action_snooze, "Later", snoozeIntentPending)
|
|
||||||
.setSound(soundUri)
|
Habit habit = Habit.get(ContentUris.parseId(data));
|
||||||
.setStyle(inboxStyle)
|
|
||||||
.build();
|
if (habit.hasImplicitRepToday()) return;
|
||||||
|
|
||||||
notification.flags |= Notification.FLAG_AUTO_CANCEL;
|
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
|
||||||
|
habit.highlight = 1;
|
||||||
NotificationManager notificationManager = (NotificationManager) context
|
habit.save();
|
||||||
.getSystemService(Activity.NOTIFICATION_SERVICE);
|
|
||||||
|
// Check if reminder has been turned off after alarm was scheduled
|
||||||
notificationManager.notify(1, notification);
|
if (habit.reminder_hour == null) return;
|
||||||
}
|
|
||||||
|
Intent contentIntent = new Intent(context, MainActivity.class);
|
||||||
|
contentIntent.setData(data);
|
||||||
|
PendingIntent contentPendingIntent =
|
||||||
|
PendingIntent.getActivity(context, 0, contentIntent, 0);
|
||||||
|
|
||||||
|
Intent deleteIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
deleteIntent.setAction(ACTION_DISMISS);
|
||||||
|
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
|
||||||
|
|
||||||
|
Intent checkIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
checkIntent.setData(data);
|
||||||
|
checkIntent.setAction(ACTION_CHECK);
|
||||||
|
PendingIntent checkIntentPending = PendingIntent.getBroadcast(context, 0, checkIntent, 0);
|
||||||
|
|
||||||
|
Intent snoozeIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
snoozeIntent.setData(data);
|
||||||
|
snoozeIntent.setAction(ACTION_SNOOZE);
|
||||||
|
PendingIntent snoozeIntentPending = PendingIntent.getBroadcast(context, 0, snoozeIntent, 0);
|
||||||
|
|
||||||
|
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
|
|
||||||
|
NotificationCompat.WearableExtender wearableExtender =
|
||||||
|
new NotificationCompat.WearableExtender().setBackground(
|
||||||
|
BitmapFactory.decodeResource(context.getResources(), R.drawable.stripe));
|
||||||
|
|
||||||
|
Notification notification =
|
||||||
|
new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setContentTitle(habit.name)
|
||||||
|
.setContentText(habit.description)
|
||||||
|
.setContentIntent(contentPendingIntent)
|
||||||
|
.setDeleteIntent(deletePendingIntent)
|
||||||
|
.addAction(R.drawable.ic_action_check, "Check", checkIntentPending)
|
||||||
|
.addAction(R.drawable.ic_action_snooze, "Later", snoozeIntentPending)
|
||||||
|
.setSound(soundUri)
|
||||||
|
.extend(wearableExtender)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
notification.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||||
|
|
||||||
|
NotificationManager notificationManager =
|
||||||
|
(NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
int notificationId = (int) (habit.getId() % Integer.MAX_VALUE);
|
||||||
|
notificationManager.notify(notificationId, notification);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,5 @@
|
|||||||
package org.isoron.uhabits.dialogs;
|
package org.isoron.uhabits.dialogs;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.helpers.DateHelper;
|
|
||||||
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
|
||||||
import org.isoron.uhabits.MainActivity;
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.ShowHabitActivity;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -20,9 +7,9 @@ import android.graphics.Color;
|
|||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.transition.Explode;
|
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
@@ -50,362 +37,359 @@ import com.mobeta.android.dslv.DragSortController;
|
|||||||
import com.mobeta.android.dslv.DragSortListView;
|
import com.mobeta.android.dslv.DragSortListView;
|
||||||
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
||||||
|
|
||||||
public class ListHabitsFragment extends Fragment implements OnSavedListener, OnItemClickListener,
|
import org.isoron.helpers.Command;
|
||||||
OnLongClickListener, DropListener, OnClickListener
|
import org.isoron.helpers.DateHelper;
|
||||||
|
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
||||||
|
import org.isoron.uhabits.MainActivity;
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.ShowHabitActivity;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public class ListHabitsFragment extends Fragment
|
||||||
|
implements OnSavedListener, OnItemClickListener, OnLongClickListener, DropListener,
|
||||||
|
OnClickListener
|
||||||
{
|
{
|
||||||
|
|
||||||
private int tvNameWidth;
|
|
||||||
private int button_count;
|
|
||||||
ListHabitsAdapter adapter;
|
|
||||||
DragSortListView listView;
|
|
||||||
MainActivity mainActivity;
|
|
||||||
TextView tvNameHeader;
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
ListHabitsAdapter adapter;
|
||||||
* Adapter *
|
DragSortListView listView;
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
MainActivity mainActivity;
|
||||||
|
TextView tvNameHeader;
|
||||||
|
long lastLongClick = 0;
|
||||||
|
private int tvNameWidth;
|
||||||
|
|
||||||
class ListHabitsAdapter extends BaseAdapter
|
private int button_count;
|
||||||
{
|
|
||||||
|
|
||||||
private Context context;
|
@Override
|
||||||
private LayoutInflater inflater;
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
private Typeface fontawesome;
|
Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
|
||||||
|
|
||||||
String habits[] = { "wake up early", "work out", "meditate", "take vitamins",
|
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||||
"go to school",
|
int width = (int) (dm.widthPixels / dm.density);
|
||||||
"cook dinner & lunch" };
|
button_count = (int) ((width - 160) / 42);
|
||||||
|
tvNameWidth = (int) ((width - 30 - button_count * 42) * dm.density);
|
||||||
|
|
||||||
public ListHabitsAdapter(Context context)
|
tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader);
|
||||||
{
|
|
||||||
this.context = context;
|
|
||||||
|
|
||||||
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
fontawesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount()
|
|
||||||
{
|
|
||||||
return Habit.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getItem(int position)
|
|
||||||
{
|
|
||||||
return Habit.getByPosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int position)
|
|
||||||
{
|
|
||||||
return ((Habit) getItem(position)).getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View view, ViewGroup parent)
|
|
||||||
{
|
|
||||||
final Habit habit = (Habit) getItem(position);
|
|
||||||
|
|
||||||
if(view == null || (Long) view.getTag(R.id.KEY_TIMESTAMP) != DateHelper.getStartOfToday())
|
|
||||||
{
|
|
||||||
view = inflater.inflate(R.layout.list_habits_item, null);
|
|
||||||
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
|
|
||||||
|
|
||||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(tvNameWidth,
|
|
||||||
LayoutParams.WRAP_CONTENT, 1);
|
|
||||||
((TextView) view.findViewById(R.id.tvName)).setLayoutParams(params);
|
|
||||||
|
|
||||||
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
|
|
||||||
.getDefaultDisplay();
|
|
||||||
Point size = new Point();
|
|
||||||
display.getSize(size);
|
|
||||||
|
|
||||||
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(
|
|
||||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
|
||||||
llp.setMargins(2, 0, 2, 0);
|
|
||||||
|
|
||||||
for (int i = 0; i < button_count; i++)
|
|
||||||
{
|
|
||||||
View check = inflater.inflate(R.layout.list_habits_item_check, null);
|
|
||||||
TextView btCheck = (TextView) check.findViewById(R.id.tvCheck);
|
|
||||||
btCheck.setTypeface(fontawesome);
|
|
||||||
btCheck.setOnLongClickListener(ListHabitsFragment.this);
|
|
||||||
// btCheck.setLayoutParams(llp);
|
|
||||||
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
|
|
||||||
}
|
|
||||||
|
|
||||||
// LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
|
|
||||||
// llInner.setOnClickListener(ListHabitsFragment.this);
|
|
||||||
|
|
||||||
view.setTag(R.id.KEY_TIMESTAMP, DateHelper.getStartOfToday());
|
|
||||||
}
|
|
||||||
|
|
||||||
TextView tvStar = (TextView) view.findViewById(R.id.tvStar);
|
|
||||||
TextView tvName = (TextView) view.findViewById(R.id.tvName);
|
|
||||||
|
|
||||||
|
|
||||||
if(habit == null)
|
|
||||||
{
|
|
||||||
tvName.setText(null);
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
|
|
||||||
llInner.setTag(R.string.habit_key, habit.getId());
|
|
||||||
|
|
||||||
int inactiveColor = Color.rgb(230, 230, 230);
|
|
||||||
int activeColor = habit.color;
|
|
||||||
|
|
||||||
tvName.setText(habit.name);
|
|
||||||
tvName.setTextColor(activeColor);
|
|
||||||
|
|
||||||
int score = habit.getScore();
|
|
||||||
|
|
||||||
if(score < Habit.HALF_STAR_CUTOFF)
|
|
||||||
{
|
|
||||||
tvStar.setText(context.getString(R.string.fa_star_o));
|
|
||||||
tvStar.setTextColor(inactiveColor);
|
|
||||||
}
|
|
||||||
else if(score < Habit.FULL_STAR_CUTOFF)
|
|
||||||
{
|
|
||||||
tvStar.setText(context.getString(R.string.fa_star_half_o));
|
|
||||||
tvStar.setTextColor(inactiveColor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tvStar.setText(context.getString(R.string.fa_star));
|
|
||||||
tvStar.setTextColor(activeColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons);
|
|
||||||
int m = llButtons.getChildCount();
|
|
||||||
|
|
||||||
long dateTo = DateHelper.getStartOfDay(DateHelper.getLocalTime());
|
|
||||||
long dateFrom = dateTo - m * DateHelper.millisecondsInOneDay;
|
|
||||||
|
|
||||||
int isChecked[] = habit.getReps(dateFrom, dateTo);
|
|
||||||
|
|
||||||
for (int i = 0; i < m; i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
TextView tvCheck = (TextView) llButtons.getChildAt(i);
|
|
||||||
tvCheck.setTag(R.string.habit_key, habit.getId());
|
|
||||||
tvCheck.setTag(R.string.offset_key, i);
|
|
||||||
|
|
||||||
switch(isChecked[i])
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
tvCheck.setText(R.string.fa_check);
|
|
||||||
tvCheck.setTextColor(activeColor);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
tvCheck.setText(R.string.fa_check);
|
|
||||||
tvCheck.setTextColor(inactiveColor);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
tvCheck.setText(R.string.fa_times);
|
|
||||||
tvCheck.setTextColor(inactiveColor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
* Creation *
|
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
|
|
||||||
|
|
||||||
DisplayMetrics dm = getResources().getDisplayMetrics();
|
|
||||||
int width = (int) (dm.widthPixels / dm.density);
|
|
||||||
button_count = (int) ((width - 160) / 42);
|
|
||||||
tvNameWidth = (int) ((width - 30 - button_count * 42) * dm.density);
|
|
||||||
|
|
||||||
tvNameHeader = (TextView) view.findViewById(R.id.tvNameHeader);
|
|
||||||
// updateStarCount();
|
// updateStarCount();
|
||||||
|
|
||||||
adapter = new ListHabitsAdapter(getActivity());
|
adapter = new ListHabitsAdapter(getActivity());
|
||||||
listView = (DragSortListView) view.findViewById(R.id.listView);
|
listView = (DragSortListView) view.findViewById(R.id.listView);
|
||||||
listView.setAdapter(adapter);
|
listView.setAdapter(adapter);
|
||||||
listView.setOnItemClickListener(this);
|
listView.setOnItemClickListener(this);
|
||||||
registerForContextMenu(listView);
|
registerForContextMenu(listView);
|
||||||
listView.setDropListener(this);
|
listView.setDropListener(this);
|
||||||
|
|
||||||
DragSortController controller = new DragSortController(listView);
|
DragSortController controller = new DragSortController(listView);
|
||||||
controller.setDragHandleId(R.id.tvStar);
|
controller.setDragHandleId(R.id.tvStar);
|
||||||
controller.setRemoveEnabled(false);
|
controller.setRemoveEnabled(false);
|
||||||
controller.setSortEnabled(true);
|
controller.setSortEnabled(true);
|
||||||
controller.setDragInitMode(1);
|
controller.setDragInitMode(1);
|
||||||
|
|
||||||
listView.setFloatViewManager(controller);
|
listView.setFloatViewManager(controller);
|
||||||
listView.setOnTouchListener(controller);
|
listView.setOnTouchListener(controller);
|
||||||
listView.setDragEnabled(true);
|
listView.setDragEnabled(true);
|
||||||
|
|
||||||
GregorianCalendar day = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
GregorianCalendar day = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
||||||
day.setTimeInMillis(DateHelper.getStartOfDay(DateHelper.getLocalTime()));
|
day.setTimeInMillis(DateHelper.getStartOfDay(DateHelper.getLocalTime()));
|
||||||
|
|
||||||
for (int i = 0; i < button_count; i++)
|
|
||||||
{
|
|
||||||
View check = inflater.inflate(R.layout.list_habits_header_check, null);
|
|
||||||
Button btCheck = (Button) check.findViewById(R.id.tvCheck);
|
|
||||||
btCheck.setText(day.getDisplayName(GregorianCalendar.DAY_OF_WEEK,
|
|
||||||
GregorianCalendar.SHORT, Locale.US) + "\n"
|
|
||||||
+ Integer.toString(day.get(GregorianCalendar.DAY_OF_MONTH)));
|
|
||||||
((LinearLayout) view.findViewById(R.id.llButtonsHeader)).addView(check);
|
|
||||||
|
|
||||||
day.add(GregorianCalendar.DAY_OF_MONTH, -1);
|
for (int i = 0; i < button_count; i++)
|
||||||
}
|
{
|
||||||
|
View check = inflater.inflate(R.layout.list_habits_header_check, null);
|
||||||
mainActivity = (MainActivity) getActivity();
|
Button btCheck = (Button) check.findViewById(R.id.tvCheck);
|
||||||
|
btCheck.setText(
|
||||||
|
day.getDisplayName(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.SHORT,
|
||||||
|
Locale.US) + "\n" +
|
||||||
|
Integer.toString(day.get(GregorianCalendar.DAY_OF_MONTH)));
|
||||||
|
((LinearLayout) view.findViewById(R.id.llButtonsHeader)).addView(check);
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
day.add(GregorianCalendar.DAY_OF_MONTH, -1);
|
||||||
return view;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
mainActivity = (MainActivity) getActivity();
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
|
||||||
{
|
|
||||||
inflater.inflate(R.menu.show_habits_options, menu);
|
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
setHasOptionsMenu(true);
|
||||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
|
return view;
|
||||||
{
|
}
|
||||||
super.onCreateContextMenu(menu, view, menuInfo);
|
|
||||||
getActivity().getMenuInflater().inflate(R.menu.show_habits_context, menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
@Override
|
||||||
* Callback *
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
{
|
||||||
|
inflater.inflate(R.menu.show_habits_options, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item)
|
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
|
||||||
{
|
{
|
||||||
int id = item.getItemId();
|
super.onCreateContextMenu(menu, view, menuInfo);
|
||||||
|
getActivity().getMenuInflater().inflate(R.menu.show_habits_context, menu);
|
||||||
|
}
|
||||||
|
|
||||||
if(id == R.id.action_add)
|
@Override
|
||||||
{
|
public boolean onOptionsItemSelected(MenuItem item)
|
||||||
EditHabitFragment frag = EditHabitFragment.createHabitFragment();
|
{
|
||||||
frag.setOnSavedListener(this);
|
int id = item.getItemId();
|
||||||
frag.show(getFragmentManager(), "dialog");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
if (id == R.id.action_add)
|
||||||
}
|
{
|
||||||
|
EditHabitFragment frag = EditHabitFragment.createHabitFragment();
|
||||||
|
frag.setOnSavedListener(this);
|
||||||
|
frag.show(getFragmentManager(), "dialog");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
return super.onOptionsItemSelected(item);
|
||||||
public boolean onContextItemSelected(MenuItem menuItem)
|
}
|
||||||
{
|
|
||||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuItem.getMenuInfo();
|
|
||||||
final int id = menuItem.getItemId();
|
|
||||||
final Habit habit = Habit.get(info.id);
|
|
||||||
|
|
||||||
if(id == R.id.action_edit_habit)
|
@Override
|
||||||
{
|
public boolean onContextItemSelected(MenuItem menuItem)
|
||||||
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(habit.getId());
|
{
|
||||||
frag.setOnSavedListener(this);
|
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuItem.getMenuInfo();
|
||||||
frag.show(getFragmentManager(), "dialog");
|
final int id = menuItem.getItemId();
|
||||||
return true;
|
final Habit habit = Habit.get(info.id);
|
||||||
}
|
|
||||||
|
|
||||||
return super.onContextItemSelected(menuItem);
|
if (id == R.id.action_edit_habit)
|
||||||
}
|
{
|
||||||
|
EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(habit.getId());
|
||||||
long lastLongClick = 0;
|
frag.setOnSavedListener(this);
|
||||||
|
frag.show(getFragmentManager(), "dialog");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
return super.onContextItemSelected(menuItem);
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
}
|
||||||
{
|
|
||||||
if(new Date().getTime() - lastLongClick < 1000) return;
|
|
||||||
|
|
||||||
Habit habit = Habit.getByPosition(position);
|
|
||||||
Log.d("ItemClick", Long.toString(id));
|
|
||||||
|
|
||||||
Intent intent = new Intent(getActivity(), ShowHabitActivity.class);
|
|
||||||
intent.setData(Uri.parse("content://org.isoron.uhabits/habit/"
|
|
||||||
+ habit.getId()));
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaved(Command command)
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||||
{
|
{
|
||||||
executeCommand(command);
|
if (new Date().getTime() - lastLongClick < 1000) return;
|
||||||
MainActivity.createReminderAlarms(mainActivity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyDataSetChanged()
|
Habit habit = Habit.getByPosition(position);
|
||||||
{
|
Log.d("ItemClick", Long.toString(id));
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Intent intent = new Intent(getActivity(), ShowHabitActivity.class);
|
||||||
public boolean onLongClick(View v)
|
intent.setData(Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId()));
|
||||||
{
|
startActivity(intent);
|
||||||
int id = v.getId();
|
}
|
||||||
|
|
||||||
if(id == R.id.tvCheck)
|
@Override
|
||||||
{
|
public void onSaved(Command command)
|
||||||
lastLongClick = new Date().getTime();
|
{
|
||||||
Habit habit = Habit.get((Long) v.getTag(R.string.habit_key));
|
executeCommand(command);
|
||||||
int offset = (Integer) v.getTag(R.string.offset_key);
|
MainActivity.createReminderAlarms(mainActivity);
|
||||||
long timestamp = DateHelper.getStartOfDay(DateHelper.getLocalTime() - offset
|
}
|
||||||
* DateHelper.millisecondsInOneDay);
|
|
||||||
|
|
||||||
executeCommand(habit.new ToggleRepetitionCommand(timestamp));
|
public void notifyDataSetChanged()
|
||||||
|
{
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
Vibrator vb = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
|
@Override
|
||||||
vb.vibrate(100);
|
public boolean onLongClick(View v)
|
||||||
|
{
|
||||||
return true;
|
int id = v.getId();
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
if (id == R.id.tvCheck)
|
||||||
}
|
{
|
||||||
|
lastLongClick = new Date().getTime();
|
||||||
|
Habit habit = Habit.get((Long) v.getTag(R.string.habit_key));
|
||||||
|
int offset = (Integer) v.getTag(R.string.offset_key);
|
||||||
|
long timestamp = DateHelper.getStartOfDay(
|
||||||
|
DateHelper.getLocalTime() - offset * DateHelper.millisecondsInOneDay);
|
||||||
|
|
||||||
private void executeCommand(Command c)
|
executeCommand(habit.new ToggleRepetitionCommand(timestamp));
|
||||||
{
|
|
||||||
mainActivity.executeCommand(c, false);
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Vibrator vb = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
public void drop(int from, int to)
|
vb.vibrate(100);
|
||||||
{
|
|
||||||
Habit.reorder(from, to);
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
return true;
|
||||||
public void onClick(View v)
|
}
|
||||||
{
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
void updateStarCount()
|
|
||||||
{
|
private void executeCommand(Command c)
|
||||||
Log.d("StarCount", "updating star count");
|
{
|
||||||
String msg = "";
|
mainActivity.executeCommand(c);
|
||||||
int starCount = Habit.getStarCount();
|
}
|
||||||
|
|
||||||
if(starCount == 1)
|
@Override
|
||||||
msg = String.format("%d star", starCount);
|
public void drop(int from, int to)
|
||||||
else if(starCount > 1)
|
{
|
||||||
msg = String.format("%d stars", starCount);
|
Habit.reorder(from, to);
|
||||||
|
notifyDataSetChanged();
|
||||||
tvNameHeader.setText(msg);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateStarCount()
|
||||||
|
{
|
||||||
|
Log.d("StarCount", "updating star count");
|
||||||
|
String msg = "";
|
||||||
|
int starCount = Habit.getStarCount();
|
||||||
|
|
||||||
|
if (starCount == 1) msg = String.format("%d star", starCount);
|
||||||
|
else if (starCount > 1) msg = String.format("%d stars", starCount);
|
||||||
|
|
||||||
|
tvNameHeader.setText(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListHabitsAdapter extends BaseAdapter
|
||||||
|
{
|
||||||
|
|
||||||
|
String habits[] = {"wake up early", "work out", "meditate", "take vitamins", "go to school",
|
||||||
|
"cook dinner & lunch"};
|
||||||
|
private Context context;
|
||||||
|
private LayoutInflater inflater;
|
||||||
|
private Typeface fontawesome;
|
||||||
|
|
||||||
|
public ListHabitsAdapter(Context context)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
|
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
fontawesome = Typeface.createFromAsset(context.getAssets(), "fontawesome-webfont.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount()
|
||||||
|
{
|
||||||
|
return Habit.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position)
|
||||||
|
{
|
||||||
|
return Habit.getByPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position)
|
||||||
|
{
|
||||||
|
return ((Habit) getItem(position)).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View view, ViewGroup parent)
|
||||||
|
{
|
||||||
|
final Habit habit = (Habit) getItem(position);
|
||||||
|
|
||||||
|
if (view == null ||
|
||||||
|
(Long) view.getTag(R.id.KEY_TIMESTAMP) != DateHelper.getStartOfToday())
|
||||||
|
{
|
||||||
|
view = inflater.inflate(R.layout.list_habits_item, null);
|
||||||
|
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
|
||||||
|
|
||||||
|
LinearLayout.LayoutParams params =
|
||||||
|
new LinearLayout.LayoutParams(tvNameWidth, LayoutParams.WRAP_CONTENT, 1);
|
||||||
|
((TextView) view.findViewById(R.id.tvName)).setLayoutParams(params);
|
||||||
|
|
||||||
|
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
|
||||||
|
.getDefaultDisplay();
|
||||||
|
Point size = new Point();
|
||||||
|
display.getSize(size);
|
||||||
|
|
||||||
|
LinearLayout.LayoutParams llp =
|
||||||
|
new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
|
||||||
|
LayoutParams.WRAP_CONTENT);
|
||||||
|
llp.setMargins(2, 0, 2, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < button_count; i++)
|
||||||
|
{
|
||||||
|
View check = inflater.inflate(R.layout.list_habits_item_check, null);
|
||||||
|
TextView btCheck = (TextView) check.findViewById(R.id.tvCheck);
|
||||||
|
btCheck.setTypeface(fontawesome);
|
||||||
|
btCheck.setOnLongClickListener(ListHabitsFragment.this);
|
||||||
|
// btCheck.setLayoutParams(llp);
|
||||||
|
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
|
||||||
|
// llInner.setOnClickListener(ListHabitsFragment.this);
|
||||||
|
|
||||||
|
view.setTag(R.id.KEY_TIMESTAMP, DateHelper.getStartOfToday());
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView tvStar = (TextView) view.findViewById(R.id.tvStar);
|
||||||
|
TextView tvName = (TextView) view.findViewById(R.id.tvName);
|
||||||
|
|
||||||
|
|
||||||
|
if (habit == null)
|
||||||
|
{
|
||||||
|
tvName.setText(null);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearLayout llInner = (LinearLayout) view.findViewById(R.id.llInner);
|
||||||
|
llInner.setTag(R.string.habit_key, habit.getId());
|
||||||
|
|
||||||
|
int inactiveColor = Color.rgb(230, 230, 230);
|
||||||
|
int activeColor = habit.color;
|
||||||
|
|
||||||
|
tvName.setText(habit.name);
|
||||||
|
tvName.setTextColor(activeColor);
|
||||||
|
|
||||||
|
int score = habit.getScore();
|
||||||
|
|
||||||
|
if (score < Habit.HALF_STAR_CUTOFF)
|
||||||
|
{
|
||||||
|
tvStar.setText(context.getString(R.string.fa_star_o));
|
||||||
|
tvStar.setTextColor(inactiveColor);
|
||||||
|
} else if (score < Habit.FULL_STAR_CUTOFF)
|
||||||
|
{
|
||||||
|
tvStar.setText(context.getString(R.string.fa_star_half_o));
|
||||||
|
tvStar.setTextColor(inactiveColor);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
tvStar.setText(context.getString(R.string.fa_star));
|
||||||
|
tvStar.setTextColor(activeColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearLayout llButtons = (LinearLayout) view.findViewById(R.id.llButtons);
|
||||||
|
int m = llButtons.getChildCount();
|
||||||
|
|
||||||
|
long dateTo = DateHelper.getStartOfDay(DateHelper.getLocalTime());
|
||||||
|
long dateFrom = dateTo - m * DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
|
int isChecked[] = habit.getReps(dateFrom, dateTo);
|
||||||
|
|
||||||
|
for (int i = 0; i < m; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
TextView tvCheck = (TextView) llButtons.getChildAt(i);
|
||||||
|
tvCheck.setTag(R.string.habit_key, habit.getId());
|
||||||
|
tvCheck.setTag(R.string.offset_key, i);
|
||||||
|
|
||||||
|
switch (isChecked[i])
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
tvCheck.setText(R.string.fa_check);
|
||||||
|
tvCheck.setTextColor(activeColor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
tvCheck.setText(R.string.fa_check);
|
||||||
|
tvCheck.setTextColor(inactiveColor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
tvCheck.setText(R.string.fa_times);
|
||||||
|
tvCheck.setTextColor(inactiveColor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,42 @@
|
|||||||
package org.isoron.uhabits.dialogs;
|
package org.isoron.uhabits.dialogs;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
|
||||||
import org.isoron.helpers.DateHelper;
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.ShowHabitActivity;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
import org.isoron.uhabits.views.HabitHistoryView;
|
|
||||||
import org.isoron.uhabits.views.HabitStreakView;
|
|
||||||
import org.isoron.uhabits.views.RingView;
|
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.LinearLayout.LayoutParams;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.isoron.helpers.ColorHelper;
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.ShowHabitActivity;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.views.HabitHistoryView;
|
||||||
|
import org.isoron.uhabits.views.HabitScoreView;
|
||||||
|
import org.isoron.uhabits.views.HabitStreakView;
|
||||||
|
import org.isoron.uhabits.views.RingView;
|
||||||
|
|
||||||
public class ShowHabitFragment extends Fragment
|
public class ShowHabitFragment extends Fragment
|
||||||
{
|
{
|
||||||
protected ShowHabitActivity activity;
|
protected ShowHabitActivity activity;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart()
|
public void onStart()
|
||||||
{
|
{
|
||||||
super.onStart();
|
super.onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState)
|
Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
Log.d("ShowHabitActivity", "Creating view...");
|
Log.d("ShowHabitActivity", "Creating view...");
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.show_habit, container, false);
|
View view = inflater.inflate(R.layout.show_habit, container, false);
|
||||||
activity = (ShowHabitActivity) getActivity();
|
activity = (ShowHabitActivity) getActivity();
|
||||||
Habit habit = activity.habit;
|
Habit habit = activity.habit;
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 21)
|
if (android.os.Build.VERSION.SDK_INT >= 21)
|
||||||
@@ -52,26 +45,34 @@ public class ShowHabitFragment extends Fragment
|
|||||||
activity.getWindow().setStatusBarColor(darkerHabitColor);
|
activity.getWindow().setStatusBarColor(darkerHabitColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView tvHistory = (TextView) view.findViewById(R.id.tvHistory);
|
TextView tvHistory = (TextView) view.findViewById(R.id.tvHistory);
|
||||||
TextView tvOverview = (TextView) view.findViewById(R.id.tvOverview);
|
TextView tvOverview = (TextView) view.findViewById(R.id.tvOverview);
|
||||||
TextView tvStreaks= (TextView) view.findViewById(R.id.tvStreaks);
|
TextView tvStrength = (TextView) view.findViewById(R.id.tvStrength);
|
||||||
tvHistory.setTextColor(habit.color);
|
TextView tvStreaks = (TextView) view.findViewById(R.id.tvStreaks);
|
||||||
tvOverview.setTextColor(habit.color);
|
tvHistory.setTextColor(habit.color);
|
||||||
|
tvOverview.setTextColor(habit.color);
|
||||||
|
tvStrength.setTextColor(habit.color);
|
||||||
tvStreaks.setTextColor(habit.color);
|
tvStreaks.setTextColor(habit.color);
|
||||||
|
|
||||||
LinearLayout llOverview = (LinearLayout) view.findViewById(R.id.llOverview);
|
LinearLayout llOverview = (LinearLayout) view.findViewById(R.id.llOverview);
|
||||||
llOverview.addView(new RingView(activity, 200, habit.color, ((float) habit.getScore() / Habit.MAX_SCORE), "Habit strength"));
|
llOverview.addView(new RingView(activity,
|
||||||
|
(int) activity.getResources().getDimension(R.dimen.small_square_size) * 4, habit.color,
|
||||||
|
((float) habit.getScore() / Habit.MAX_SCORE), "Habit strength"));
|
||||||
|
|
||||||
LinearLayout llHistory = (LinearLayout) view.findViewById(R.id.llHistory);
|
LinearLayout llStrength = (LinearLayout) view.findViewById(R.id.llStrength);
|
||||||
|
llStrength.addView(new HabitScoreView(activity, habit,
|
||||||
|
(int) activity.getResources().getDimension(R.dimen.small_square_size)));
|
||||||
|
|
||||||
|
LinearLayout llHistory = (LinearLayout) view.findViewById(R.id.llHistory);
|
||||||
HabitHistoryView hhv = new HabitHistoryView(activity, habit,
|
HabitHistoryView hhv = new HabitHistoryView(activity, habit,
|
||||||
(int) activity.getResources().getDimension(R.dimen.square_size));
|
(int) activity.getResources().getDimension(R.dimen.small_square_size));
|
||||||
llHistory.addView(hhv);
|
llHistory.addView(hhv);
|
||||||
|
|
||||||
LinearLayout llStreaks = (LinearLayout) view.findViewById(R.id.llStreaks);
|
LinearLayout llStreaks = (LinearLayout) view.findViewById(R.id.llStreaks);
|
||||||
HabitStreakView hsv = new HabitStreakView(activity, habit,
|
HabitStreakView hsv = new HabitStreakView(activity, habit,
|
||||||
(int) activity.getResources().getDimension(R.dimen.square_size));
|
(int) activity.getResources().getDimension(R.dimen.small_square_size));
|
||||||
llStreaks.addView(hsv);
|
llStreaks.addView(hsv);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.isoron.uhabits.models;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.activeandroid.Cache;
|
import com.activeandroid.Cache;
|
||||||
@@ -20,6 +21,7 @@ import org.isoron.helpers.Command;
|
|||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Table(name = "Habits")
|
@Table(name = "Habits")
|
||||||
@@ -77,8 +79,7 @@ public class Habit extends Model
|
|||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
public static void updateId(long oldId, long newId)
|
public static void updateId(long oldId, long newId)
|
||||||
{
|
{
|
||||||
SQLiteUtils.execSql(String.format(
|
SQLiteUtils.execSql(String.format("update Habits set Id = %d where Id = %d", newId, oldId));
|
||||||
"update Habits set Id = %d where Id = %d", newId, oldId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static From select()
|
protected static From select()
|
||||||
@@ -114,18 +115,13 @@ public class Habit extends Model
|
|||||||
|
|
||||||
public static void reorder(int from, int to)
|
public static void reorder(int from, int to)
|
||||||
{
|
{
|
||||||
if (from == to)
|
if (from == to) return;
|
||||||
return;
|
|
||||||
|
|
||||||
Habit h = Habit.getByPosition(from);
|
Habit h = Habit.getByPosition(from);
|
||||||
if (to < from)
|
if (to < from) new Update(Habit.class).set("position = position + 1")
|
||||||
new Update(Habit.class).set("position = position + 1")
|
.where("position >= ? and position < ?", to, from).execute();
|
||||||
.where("position >= ? and position < ?", to, from)
|
else new Update(Habit.class).set("position = position - 1")
|
||||||
.execute();
|
.where("position > ? and position <= ?", from, to).execute();
|
||||||
else
|
|
||||||
new Update(Habit.class).set("position = position - 1")
|
|
||||||
.where("position > ? and position <= ?", from, to)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
h.position = to;
|
h.position = to;
|
||||||
h.save();
|
h.save();
|
||||||
@@ -152,13 +148,20 @@ public class Habit extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void recomputeAllScores()
|
||||||
|
{
|
||||||
|
for (Habit habit : getHabits())
|
||||||
|
{
|
||||||
|
habit.deleteScoresNewerThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static int getStarCount()
|
public static int getStarCount()
|
||||||
{
|
{
|
||||||
String args[] = {};
|
String args[] = {};
|
||||||
return SQLiteUtils.intQuery(
|
return SQLiteUtils.intQuery("select count(*) from (select score, max(timestamp) from " +
|
||||||
"select count(*) from (select score, max(timestamp) from " +
|
"score group by habit) as scores where scores.score >= " +
|
||||||
"score group by habit) as scores where scores.score >= "
|
Integer.toString(12973000), args);
|
||||||
+ Integer.toString(12973000), args);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,14 +187,12 @@ public class Habit extends Model
|
|||||||
|
|
||||||
protected From selectReps()
|
protected From selectReps()
|
||||||
{
|
{
|
||||||
return new Select().from(Repetition.class).where("habit = ?", getId())
|
return new Select().from(Repetition.class).where("habit = ?", getId()).orderBy("timestamp");
|
||||||
.orderBy("timestamp");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected From selectRepsFromTo(long timeFrom, long timeTo)
|
protected From selectRepsFromTo(long timeFrom, long timeTo)
|
||||||
{
|
{
|
||||||
return selectReps().and("timestamp >= ?", timeFrom).and(
|
return selectReps().and("timestamp >= ?", timeFrom).and("timestamp <= ?", timeTo);
|
||||||
"timestamp <= ?", timeTo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasRep(long timestamp)
|
public boolean hasRep(long timestamp)
|
||||||
@@ -236,8 +237,7 @@ public class Habit extends Model
|
|||||||
for (int j = 0; j < freq_den; j++)
|
for (int j = 0; j < freq_den; j++)
|
||||||
if (checkExtended[i + j] == 2) counter++;
|
if (checkExtended[i + j] == 2) counter++;
|
||||||
|
|
||||||
if (counter >= freq_num)
|
if (counter >= freq_num) checkExtended[i] = Math.max(checkExtended[i], 1);
|
||||||
checkExtended[i] = Math.max(checkExtended[i], 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int check[] = new int[nDays + 1];
|
int check[] = new int[nDays + 1];
|
||||||
@@ -247,6 +247,13 @@ public class Habit extends Model
|
|||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRepsCount(int days)
|
||||||
|
{
|
||||||
|
long timeTo = DateHelper.getStartOfToday();
|
||||||
|
long timeFrom = timeTo - DateHelper.millisecondsInOneDay * days;
|
||||||
|
return selectRepsFromTo(timeFrom, timeTo).count();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasImplicitRepToday()
|
public boolean hasImplicitRepToday()
|
||||||
{
|
{
|
||||||
long today = DateHelper.getStartOfToday();
|
long today = DateHelper.getStartOfToday();
|
||||||
@@ -282,14 +289,14 @@ public class Habit extends Model
|
|||||||
|
|
||||||
public Score getNewestScore()
|
public Score getNewestScore()
|
||||||
{
|
{
|
||||||
return new Select().from(Score.class).where("habit = ?", getId())
|
return new Select().from(Score.class).where("habit = ?", getId()).orderBy("timestamp desc")
|
||||||
.orderBy("timestamp desc").limit(1).executeSingle();
|
.limit(1).executeSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteScoresNewerThan(long timestamp)
|
public void deleteScoresNewerThan(long timestamp)
|
||||||
{
|
{
|
||||||
new Delete().from(Score.class).where("habit = ?", getId())
|
new Delete().from(Score.class).where("habit = ?", getId()).and("timestamp >= ?", timestamp)
|
||||||
.and("timestamp >= ?", timestamp).execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getScore()
|
public Integer getScore()
|
||||||
@@ -307,8 +314,7 @@ public class Habit extends Model
|
|||||||
if (newestScore == null)
|
if (newestScore == null)
|
||||||
{
|
{
|
||||||
Repetition oldestRep = getOldestRep();
|
Repetition oldestRep = getOldestRep();
|
||||||
if (oldestRep == null)
|
if (oldestRep == null) return 0;
|
||||||
return 0;
|
|
||||||
beginningTime = oldestRep.timestamp;
|
beginningTime = oldestRep.timestamp;
|
||||||
beginningScore = 0;
|
beginningScore = 0;
|
||||||
} else
|
} else
|
||||||
@@ -318,8 +324,7 @@ public class Habit extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
long nDays = (today - beginningTime) / day;
|
long nDays = (today - beginningTime) / day;
|
||||||
if (nDays < 0)
|
if (nDays < 0) return newestScore.score;
|
||||||
return newestScore.score;
|
|
||||||
|
|
||||||
int reps[] = getReps(beginningTime, today);
|
int reps[] = getReps(beginningTime, today);
|
||||||
|
|
||||||
@@ -343,13 +348,26 @@ public class Habit extends Model
|
|||||||
return lastScore;
|
return lastScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Score> getScores(long fromTimestamp, long toTimestamp)
|
||||||
|
{
|
||||||
|
return getScores(fromTimestamp, toTimestamp, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Score> getScores(long fromTimestamp, long toTimestamp, int divisor, long offset)
|
||||||
|
{
|
||||||
|
return new Select().from(Score.class).where("habit = ? and timestamp > ? and " +
|
||||||
|
"timestamp <= ? and (timestamp - ?) % ? = 0", getId(), fromTimestamp, toTimestamp,
|
||||||
|
offset, divisor).execute();
|
||||||
|
}
|
||||||
|
|
||||||
public long[] getStreaks()
|
public long[] getStreaks()
|
||||||
{
|
{
|
||||||
String query = "create temporary table T as select distinct r1.habit as habit, r1.timestamp as time,\n" +
|
String query =
|
||||||
" (select count(*) from repetitions r2 where r1.habit = r2.habit and\n" +
|
"create temporary table T as select distinct r1.habit as habit, r1.timestamp as time,\n" +
|
||||||
" (r1.timestamp = r2.timestamp - 24*60*60*1000 or\n" +
|
" (select count(*) from repetitions r2 where r1.habit = r2.habit and\n" +
|
||||||
" r1.timestamp = r2.timestamp + 24*60*60*1000)) as neighbors\n" +
|
" (r1.timestamp = r2.timestamp - 24*60*60*1000 or\n" +
|
||||||
"from repetitions r1 where r1.habit = ?";
|
" r1.timestamp = r2.timestamp + 24*60*60*1000)) as neighbors\n" +
|
||||||
|
"from repetitions r1 where r1.habit = ?";
|
||||||
|
|
||||||
String query2 =
|
String query2 =
|
||||||
"select time from T, (select 0 union select 1) where neighbors = 0 union all\n" +
|
"select time from T, (select 0 union select 1) where neighbors = 0 union all\n" +
|
||||||
@@ -436,8 +454,8 @@ public class Habit extends Model
|
|||||||
this.modified = new Habit(modified);
|
this.modified = new Habit(modified);
|
||||||
this.original = new Habit(Habit.this);
|
this.original = new Habit(Habit.this);
|
||||||
|
|
||||||
hasIntervalChanged = (this.original.freq_den != this.modified.freq_den
|
hasIntervalChanged = (this.original.freq_den != this.modified.freq_den ||
|
||||||
|| this.original.freq_num != this.modified.freq_num);
|
this.original.freq_num != this.modified.freq_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute()
|
public void execute()
|
||||||
@@ -446,7 +464,30 @@ public class Habit extends Model
|
|||||||
habit.copyAttributes(modified);
|
habit.copyAttributes(modified);
|
||||||
habit.save();
|
habit.save();
|
||||||
if (hasIntervalChanged)
|
if (hasIntervalChanged)
|
||||||
habit.deleteScoresNewerThan(0);
|
{
|
||||||
|
new AsyncTask<Habit, Integer, Integer>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Integer doInBackground(Habit... habits)
|
||||||
|
{
|
||||||
|
// HACK: We wait one second before deleting old score, otherwise the view will
|
||||||
|
// trigger the very slow getScore on the main thread at the same time, or even
|
||||||
|
// before us.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
habits[0].deleteScoresNewerThan(0);
|
||||||
|
habits[0].getScore();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}.execute(habit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undo()
|
public void undo()
|
||||||
@@ -455,7 +496,28 @@ public class Habit extends Model
|
|||||||
habit.copyAttributes(original);
|
habit.copyAttributes(original);
|
||||||
habit.save();
|
habit.save();
|
||||||
if (hasIntervalChanged)
|
if (hasIntervalChanged)
|
||||||
habit.deleteScoresNewerThan(0);
|
{
|
||||||
|
new AsyncTask<Habit, Integer, Integer>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected Integer doInBackground(Habit... habits)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
habits[0].deleteScoresNewerThan(0);
|
||||||
|
habits[0].getScore();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}.execute(habit);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getExecuteStringId()
|
public Integer getExecuteStringId()
|
||||||
|
|||||||
@@ -1,233 +1,233 @@
|
|||||||
package org.isoron.uhabits.views;
|
package org.isoron.uhabits.views;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
|
||||||
import org.isoron.helpers.DateHelper;
|
|
||||||
import org.isoron.uhabits.R;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Paint.Align;
|
import android.graphics.Paint.Align;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.support.v4.view.MotionEventCompat;
|
import android.support.v4.view.MotionEventCompat;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.isoron.helpers.ColorHelper;
|
||||||
|
import org.isoron.helpers.DateHelper;
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
public class HabitHistoryView extends View
|
public class HabitHistoryView extends View
|
||||||
{
|
{
|
||||||
|
|
||||||
private Habit habit;
|
private Habit habit;
|
||||||
private int reps[];
|
private int reps[];
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private Paint pSquareBg, pSquareFg, pTextHeader;
|
private Paint pSquareBg, pSquareFg, pTextHeader;
|
||||||
|
|
||||||
private int squareSize, squareSpacing;
|
private int squareSize, squareSpacing;
|
||||||
private int nColumns, offsetWeeks;
|
private int nColumns, offsetWeeks;
|
||||||
|
|
||||||
private int colorPrimary, colorPrimaryBrighter, grey;
|
private int colorPrimary, colorPrimaryBrighter, grey;
|
||||||
|
private Float prevX, prevY;
|
||||||
|
|
||||||
public HabitHistoryView(Context context, Habit habit, int squareSize)
|
public HabitHistoryView(Context context, Habit habit, int squareSize)
|
||||||
{
|
{
|
||||||
super(context);
|
super(context);
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.squareSize = squareSize;
|
this.squareSize = squareSize;
|
||||||
|
|
||||||
Typeface fontawesome = Typeface.createFromAsset(context.getAssets(),
|
colorPrimary = habit.color;
|
||||||
"fontawesome-webfont.ttf");
|
colorPrimaryBrighter = ColorHelper.mixColors(colorPrimary, Color.WHITE, 0.5f);
|
||||||
|
grey = Color.rgb(230, 230, 230);
|
||||||
|
squareSpacing = 2;
|
||||||
|
|
||||||
colorPrimary = habit.color;
|
pTextHeader = new Paint();
|
||||||
colorPrimaryBrighter = ColorHelper.mixColors(colorPrimary, Color.WHITE, 0.5f);
|
pTextHeader.setColor(Color.LTGRAY);
|
||||||
grey = Color.rgb(230, 230, 230);
|
pTextHeader.setTextAlign(Align.LEFT);
|
||||||
squareSpacing = 2;
|
pTextHeader.setTextSize(squareSize * 0.5f);
|
||||||
|
pTextHeader.setAntiAlias(true);
|
||||||
|
|
||||||
pTextHeader = new Paint();
|
pSquareBg = new Paint();
|
||||||
pTextHeader.setColor(Color.LTGRAY);
|
pSquareBg.setColor(habit.color);
|
||||||
pTextHeader.setTextAlign(Align.LEFT);
|
|
||||||
pTextHeader.setTextSize(squareSize * 0.5f);
|
|
||||||
pTextHeader.setAntiAlias(true);
|
|
||||||
|
|
||||||
pSquareBg = new Paint();
|
pSquareFg = new Paint();
|
||||||
pSquareBg.setColor(habit.color);
|
pSquareFg.setColor(Color.WHITE);
|
||||||
|
pSquareFg.setAntiAlias(true);
|
||||||
|
pSquareFg.setTextSize(squareSize * 0.5f);
|
||||||
|
pSquareFg.setTextAlign(Align.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
pSquareFg = new Paint();
|
@Override
|
||||||
pSquareFg.setColor(Color.WHITE);
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||||
pSquareFg.setAntiAlias(true);
|
{
|
||||||
// pSquareFg.setTypeface(fontawesome);
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
pSquareFg.setTextSize(squareSize * 0.5f);
|
setMeasuredDimension(getMeasuredWidth(), 8 * squareSize);
|
||||||
pSquareFg.setTextAlign(Align.CENTER);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||||
{
|
{
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
||||||
setMeasuredDimension(getMeasuredWidth(), 8 * squareSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
|
||||||
{
|
|
||||||
nColumns = (w / squareSize) - 1;
|
nColumns = (w / squareSize) - 1;
|
||||||
fetchReps();
|
fetchReps();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchReps()
|
private void fetchReps()
|
||||||
{
|
{
|
||||||
Calendar currentDate = new GregorianCalendar();
|
Calendar currentDate = new GregorianCalendar();
|
||||||
currentDate.add(Calendar.DAY_OF_YEAR, -offsetWeeks * 7);
|
currentDate.add(Calendar.DAY_OF_YEAR, -offsetWeeks * 7);
|
||||||
int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK) % 7;
|
int dayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK) % 7;
|
||||||
|
|
||||||
long dateTo = DateHelper.getStartOfToday();
|
long dateTo = DateHelper.getStartOfToday();
|
||||||
for (int i = 0; i < 7 - dayOfWeek; i++)
|
for (int i = 0; i < 7 - dayOfWeek; i++)
|
||||||
dateTo += DateHelper.millisecondsInOneDay;
|
dateTo += DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
for (int i = 0; i < offsetWeeks * 7; i++)
|
for (int i = 0; i < offsetWeeks * 7; i++)
|
||||||
dateTo -= DateHelper.millisecondsInOneDay;
|
dateTo -= DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
long dateFrom = dateTo;
|
long dateFrom = dateTo;
|
||||||
for (int i = 0; i < nColumns * 7; i++)
|
for (int i = 0; i < nColumns * 7; i++)
|
||||||
dateFrom -= DateHelper.millisecondsInOneDay;
|
dateFrom -= DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
reps = habit.getReps(dateFrom, dateTo);
|
reps = habit.getReps(dateFrom, dateTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas)
|
protected void onDraw(Canvas canvas)
|
||||||
{
|
{
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
|
||||||
Rect square = new Rect(0, 0, squareSize - squareSpacing, squareSize - squareSpacing);
|
Rect square = new Rect(0, 0, squareSize - squareSpacing, squareSize - squareSpacing);
|
||||||
|
|
||||||
Calendar currentDate = new GregorianCalendar();
|
Calendar currentDate = new GregorianCalendar();
|
||||||
currentDate.add(Calendar.DAY_OF_YEAR, -(offsetWeeks-1) * 7);
|
currentDate.add(Calendar.DAY_OF_YEAR, - (offsetWeeks - 1) * 7);
|
||||||
|
|
||||||
int nDays = nColumns * 7;
|
int nDays = nColumns * 7;
|
||||||
int todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
|
int todayWeekday = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) % 7;
|
||||||
|
|
||||||
currentDate.add(Calendar.DAY_OF_YEAR, -nDays);
|
currentDate.add(Calendar.DAY_OF_YEAR, -nDays);
|
||||||
|
currentDate.add(Calendar.DAY_OF_YEAR, -todayWeekday);
|
||||||
|
|
||||||
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
||||||
SimpleDateFormat dfYear = new SimpleDateFormat("yyyy");
|
SimpleDateFormat dfYear = new SimpleDateFormat("yyyy");
|
||||||
|
|
||||||
String previousMonth = "";
|
String previousMonth = "";
|
||||||
String previousYear = "";
|
String previousYear = "";
|
||||||
|
|
||||||
int colors[] = { grey, colorPrimaryBrighter, colorPrimary };
|
int colors[] = {grey, colorPrimaryBrighter, colorPrimary};
|
||||||
String markers[] = { context.getString(R.string.fa_times),
|
String markers[] =
|
||||||
context.getString(R.string.fa_check), context.getString(R.string.fa_check) };
|
{context.getString(R.string.fa_times), context.getString(R.string.fa_check),
|
||||||
|
context.getString(R.string.fa_check)};
|
||||||
|
|
||||||
float squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
float squareTextOffset = pSquareFg.getFontSpacing() * 0.4f;
|
||||||
float headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
float headerTextOffset = pTextHeader.getFontSpacing() * 0.3f;
|
||||||
boolean justPrintedYear = false;
|
boolean justPrintedYear = false;
|
||||||
|
|
||||||
int k = nDays;
|
int k = nDays;
|
||||||
for (int i = 0; i < nColumns; i++)
|
for (int i = 0; i < nColumns; i++)
|
||||||
{
|
{
|
||||||
String month = dfMonth.format(currentDate.getTime());
|
String month = dfMonth.format(currentDate.getTime());
|
||||||
String year = dfYear.format(currentDate.getTime());
|
String year = dfYear.format(currentDate.getTime());
|
||||||
|
|
||||||
if(!month.equals(previousMonth))
|
if (!month.equals(previousMonth))
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if(justPrintedYear)
|
if (justPrintedYear) offset += squareSize;
|
||||||
offset += squareSize;
|
|
||||||
|
canvas.drawText(month, square.left + offset, square.bottom - headerTextOffset,
|
||||||
canvas.drawText(month, square.left + offset, square.bottom - headerTextOffset,
|
pTextHeader);
|
||||||
pTextHeader);
|
previousMonth = month;
|
||||||
previousMonth = month;
|
justPrintedYear = false;
|
||||||
justPrintedYear = false;
|
} else if (!year.equals(previousYear))
|
||||||
}
|
{
|
||||||
else if(!year.equals(previousYear))
|
canvas.drawText(year, square.left, square.bottom - headerTextOffset, pTextHeader);
|
||||||
{
|
previousYear = year;
|
||||||
canvas.drawText(year, square.left, square.bottom - headerTextOffset, pTextHeader);
|
justPrintedYear = true;
|
||||||
previousYear = year;
|
} else
|
||||||
justPrintedYear = true;
|
{
|
||||||
}
|
justPrintedYear = false;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
justPrintedYear = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
square.offset(0, squareSize);
|
square.offset(0, squareSize);
|
||||||
|
|
||||||
for (int j = 0; j < 7; j++)
|
for (int j = 0; j < 7; j++)
|
||||||
{
|
{
|
||||||
if(!(i == nColumns - 1 && offsetWeeks == 0 && j > todayWeekday))
|
if (!(i == nColumns - 1 && offsetWeeks == 0 && j > todayWeekday))
|
||||||
{
|
{
|
||||||
pSquareBg.setColor(colors[reps[k]]);
|
pSquareBg.setColor(colors[reps[k]]);
|
||||||
canvas.drawRect(square, pSquareBg);
|
canvas.drawRect(square, pSquareBg);
|
||||||
// canvas.drawText(markers[reps[k]], square.centerX(), square.centerY()
|
canvas.drawText(Integer.toString(currentDate.get(Calendar.DAY_OF_MONTH)),
|
||||||
// + squareTextOffset, pSquareFg);
|
square.centerX(), square.centerY() + squareTextOffset, pSquareFg);
|
||||||
canvas.drawText(Integer.toString(currentDate.get(Calendar.DAY_OF_MONTH)),
|
}
|
||||||
square.centerX(), square.centerY() + squareTextOffset, pSquareFg);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDate.add(Calendar.DAY_OF_MONTH, 1);
|
currentDate.add(Calendar.DAY_OF_MONTH, 1);
|
||||||
square.offset(0, squareSize);
|
square.offset(0, squareSize);
|
||||||
k--;
|
k--;
|
||||||
}
|
}
|
||||||
|
|
||||||
square.offset(squareSize, -8 * squareSize);
|
square.offset(squareSize, -8 * squareSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
String wdays[] = { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri" };
|
String wdays[] = {"Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"};
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++)
|
for (int i = 0; i < 7; i++)
|
||||||
{
|
{
|
||||||
square.offset(0, squareSize);
|
square.offset(0, squareSize);
|
||||||
canvas.drawText(wdays[i], square.left + headerTextOffset, square.bottom
|
canvas.drawText(wdays[i], square.left + headerTextOffset,
|
||||||
- headerTextOffset, pTextHeader);
|
square.bottom - headerTextOffset, pTextHeader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Float prevX, prevY;
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event)
|
||||||
|
{
|
||||||
|
int action = event.getAction();
|
||||||
|
|
||||||
@Override
|
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
||||||
public boolean onTouchEvent(MotionEvent event)
|
final float x = MotionEventCompat.getX(event, pointerIndex);
|
||||||
{
|
final float y = MotionEventCompat.getY(event, pointerIndex);
|
||||||
int action = event.getAction();
|
|
||||||
|
|
||||||
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
if (action == MotionEvent.ACTION_DOWN)
|
||||||
final float x = MotionEventCompat.getX(event, pointerIndex);
|
{
|
||||||
final float y = MotionEventCompat.getY(event, pointerIndex);
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
}
|
||||||
|
|
||||||
if(action == MotionEvent.ACTION_DOWN)
|
if (action == MotionEvent.ACTION_MOVE)
|
||||||
{
|
{
|
||||||
prevX = x;
|
float dx = x - prevX;
|
||||||
prevY = y;
|
float dy = y - prevY;
|
||||||
}
|
|
||||||
|
|
||||||
if(action == MotionEvent.ACTION_MOVE)
|
if (Math.abs(dy) > Math.abs(dx)) return false;
|
||||||
{
|
getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
float dx = x - prevX;
|
if(move(dx))
|
||||||
float dy = y - prevY;
|
{
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int newOffsetWeeks = offsetWeeks + (int) (dx / squareSize);
|
return true;
|
||||||
newOffsetWeeks = Math.max(0, newOffsetWeeks);
|
}
|
||||||
|
|
||||||
if(newOffsetWeeks != offsetWeeks)
|
private boolean move(float dx)
|
||||||
{
|
{
|
||||||
prevX = x;
|
int newOffsetWeeks = offsetWeeks + (int) (dx / squareSize);
|
||||||
prevY = y;
|
newOffsetWeeks = Math.max(0, newOffsetWeeks);
|
||||||
offsetWeeks = newOffsetWeeks;
|
|
||||||
|
|
||||||
fetchReps();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (newOffsetWeeks != offsetWeeks)
|
||||||
|
{
|
||||||
|
offsetWeeks = newOffsetWeeks;
|
||||||
|
fetchReps();
|
||||||
|
invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
252
app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
package org.isoron.uhabits.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.support.v4.view.MotionEventCompat;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.isoron.helpers.ColorHelper;
|
||||||
|
import org.isoron.helpers.DateHelper;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
import org.isoron.uhabits.models.Score;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HabitScoreView extends View
|
||||||
|
{
|
||||||
|
public static final int BUCKET_SIZE = 7;
|
||||||
|
|
||||||
|
private final Paint pGrid;
|
||||||
|
private final float em;
|
||||||
|
private Habit habit;
|
||||||
|
private int columnWidth, columnHeight, nColumns;
|
||||||
|
|
||||||
|
private Paint pText, pGraph;
|
||||||
|
private int dataOffset;
|
||||||
|
|
||||||
|
private int barHeaderHeight;
|
||||||
|
|
||||||
|
private int[] colors;
|
||||||
|
private float prevX;
|
||||||
|
private float prevY;
|
||||||
|
private List<Score> scores;
|
||||||
|
|
||||||
|
public HabitScoreView(Context context, Habit habit, int columnWidth)
|
||||||
|
{
|
||||||
|
super(context);
|
||||||
|
this.habit = habit;
|
||||||
|
this.columnWidth = columnWidth;
|
||||||
|
|
||||||
|
pText = new Paint();
|
||||||
|
pText.setColor(Color.LTGRAY);
|
||||||
|
pText.setTextAlign(Paint.Align.LEFT);
|
||||||
|
pText.setTextSize(columnWidth * 0.5f);
|
||||||
|
pText.setAntiAlias(true);
|
||||||
|
|
||||||
|
pGraph = new Paint();
|
||||||
|
pGraph.setTextAlign(Paint.Align.CENTER);
|
||||||
|
pGraph.setTextSize(columnWidth * 0.5f);
|
||||||
|
pGraph.setAntiAlias(true);
|
||||||
|
pGraph.setStrokeWidth(columnWidth * 0.1f);
|
||||||
|
|
||||||
|
pGrid = new Paint();
|
||||||
|
pGrid.setColor(Color.LTGRAY);
|
||||||
|
pGrid.setAntiAlias(true);
|
||||||
|
pGrid.setStrokeWidth(columnWidth * 0.05f);
|
||||||
|
|
||||||
|
columnHeight = 8 * columnWidth;
|
||||||
|
barHeaderHeight = columnWidth;
|
||||||
|
em = pText.getFontSpacing();
|
||||||
|
|
||||||
|
colors = new int[4];
|
||||||
|
|
||||||
|
colors[0] = Color.rgb(230, 230, 230);
|
||||||
|
colors[3] = habit.color;
|
||||||
|
colors[1] = ColorHelper.mixColors(colors[0], colors[3], 0.66f);
|
||||||
|
colors[2] = ColorHelper.mixColors(colors[0], colors[3], 0.33f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchScores()
|
||||||
|
{
|
||||||
|
|
||||||
|
long toTimestamp = DateHelper.getStartOfToday();
|
||||||
|
for (int i = 0; i < dataOffset * BUCKET_SIZE; i++)
|
||||||
|
toTimestamp -= DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
|
long fromTimestamp = toTimestamp;
|
||||||
|
for (int i = 0; i < nColumns * BUCKET_SIZE; i++)
|
||||||
|
fromTimestamp -= DateHelper.millisecondsInOneDay;
|
||||||
|
|
||||||
|
scores = habit.getScores(fromTimestamp, toTimestamp, BUCKET_SIZE * DateHelper.millisecondsInOneDay,
|
||||||
|
toTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||||
|
{
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
setMeasuredDimension(getMeasuredWidth(), columnHeight + 2 * barHeaderHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||||
|
{
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
nColumns = w / columnWidth;
|
||||||
|
fetchScores();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas)
|
||||||
|
{
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
float lineHeight = pText.getFontSpacing();
|
||||||
|
float barHeaderOffset = lineHeight * 0.4f;
|
||||||
|
|
||||||
|
RectF rGrid = new RectF(0, 0, nColumns * columnWidth, columnHeight);
|
||||||
|
rGrid.offset(0, barHeaderHeight);
|
||||||
|
drawGrid(canvas, rGrid);
|
||||||
|
|
||||||
|
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
||||||
|
SimpleDateFormat dfDay = new SimpleDateFormat("d");
|
||||||
|
|
||||||
|
String previousMonth = "";
|
||||||
|
|
||||||
|
pGraph.setColor(habit.color);
|
||||||
|
RectF prevR = null;
|
||||||
|
|
||||||
|
for (int offset = nColumns - scores.size(); offset < nColumns; offset++)
|
||||||
|
{
|
||||||
|
Score score = scores.get(offset - nColumns + scores.size());
|
||||||
|
String month = dfMonth.format(score.timestamp);
|
||||||
|
String day = dfDay.format(score.timestamp);
|
||||||
|
|
||||||
|
long s = score.score;
|
||||||
|
double sRelative = ((double) s) / Habit.MAX_SCORE;
|
||||||
|
|
||||||
|
int height = (int) (columnHeight * sRelative);
|
||||||
|
|
||||||
|
RectF r = new RectF(0, 0, columnWidth, columnWidth);
|
||||||
|
r.offset(offset * columnWidth,
|
||||||
|
barHeaderHeight + columnHeight - height - columnWidth / 2);
|
||||||
|
|
||||||
|
if (prevR != null)
|
||||||
|
{
|
||||||
|
drawLine(canvas, prevR, r);
|
||||||
|
drawMarker(canvas, prevR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == nColumns - 1) drawMarker(canvas, r);
|
||||||
|
|
||||||
|
prevR = r;
|
||||||
|
|
||||||
|
r = new RectF(0, 0, columnWidth, columnHeight);
|
||||||
|
r.offset(offset * columnWidth, barHeaderHeight);
|
||||||
|
if (!month.equals(previousMonth))
|
||||||
|
{
|
||||||
|
canvas.drawText(month, r.centerX(), r.bottom + lineHeight * 1.2f, pText);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
canvas.drawText(day, r.centerX(), r.bottom + lineHeight * 1.2f, pText);
|
||||||
|
}
|
||||||
|
|
||||||
|
previousMonth = month;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawGrid(Canvas canvas, RectF rGrid)
|
||||||
|
{
|
||||||
|
// pGrid.setColor(Color.rgb(230, 230, 230));
|
||||||
|
// pGrid.setStyle(Paint.Style.STROKE);
|
||||||
|
// canvas.drawRect(rGrid, pGrid);
|
||||||
|
|
||||||
|
int nRows = 5;
|
||||||
|
float rowHeight = rGrid.height() / nRows;
|
||||||
|
|
||||||
|
pGrid.setColor(Color.rgb(240, 240, 240));
|
||||||
|
for (int i = 0; i < nRows; i++)
|
||||||
|
{
|
||||||
|
canvas.drawText(String.format("%d%%", (100 - i * 100 / nRows)), rGrid.left + 0.5f * em,
|
||||||
|
rGrid.top + 1f * em, pText);
|
||||||
|
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
|
||||||
|
rGrid.offset(0, rowHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawLine(Canvas canvas, RectF rectFrom, RectF rectTo)
|
||||||
|
{
|
||||||
|
pGraph.setColor(habit.color);
|
||||||
|
canvas.drawLine(rectFrom.centerX(), rectFrom.centerY(), rectTo.centerX(), rectTo.centerY(),
|
||||||
|
pGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawMarker(Canvas canvas, RectF rect)
|
||||||
|
{
|
||||||
|
rect.inset(columnWidth * 0.15f, columnWidth * 0.15f);
|
||||||
|
pGraph.setColor(Color.WHITE);
|
||||||
|
canvas.drawOval(rect, pGraph);
|
||||||
|
|
||||||
|
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
||||||
|
pGraph.setColor(habit.color);
|
||||||
|
canvas.drawOval(rect, pGraph);
|
||||||
|
|
||||||
|
rect.inset(columnWidth * 0.1f, columnWidth * 0.1f);
|
||||||
|
pGraph.setColor(Color.WHITE);
|
||||||
|
canvas.drawOval(rect, pGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event)
|
||||||
|
{
|
||||||
|
int action = event.getAction();
|
||||||
|
|
||||||
|
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
||||||
|
final float x = MotionEventCompat.getX(event, pointerIndex);
|
||||||
|
final float y = MotionEventCompat.getY(event, pointerIndex);
|
||||||
|
|
||||||
|
if (action == MotionEvent.ACTION_DOWN)
|
||||||
|
{
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == MotionEvent.ACTION_MOVE)
|
||||||
|
{
|
||||||
|
float dx = x - prevX;
|
||||||
|
float dy = y - prevY;
|
||||||
|
|
||||||
|
if (Math.abs(dy) > Math.abs(dx)) return false;
|
||||||
|
getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
|
if (move(dx))
|
||||||
|
{
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean move(float dx)
|
||||||
|
{
|
||||||
|
int newDataOffset = dataOffset + (int) (dx / columnWidth);
|
||||||
|
newDataOffset = Math.max(0, newDataOffset);
|
||||||
|
|
||||||
|
if (newDataOffset != dataOffset)
|
||||||
|
{
|
||||||
|
dataOffset = newDataOffset;
|
||||||
|
fetchScores();
|
||||||
|
invalidate();
|
||||||
|
return true;
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.support.v4.view.MotionEventCompat;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
@@ -22,6 +24,7 @@ public class HabitStreakView extends View
|
|||||||
|
|
||||||
private Paint pText, pBar;
|
private Paint pText, pBar;
|
||||||
private long streaks[];
|
private long streaks[];
|
||||||
|
private int dataOffset;
|
||||||
|
|
||||||
private long streakStart[], streakEnd[], streakLength[];
|
private long streakStart[], streakEnd[], streakLength[];
|
||||||
private long maxStreakLength;
|
private long maxStreakLength;
|
||||||
@@ -29,6 +32,8 @@ public class HabitStreakView extends View
|
|||||||
private int barHeaderHeight;
|
private int barHeaderHeight;
|
||||||
|
|
||||||
private int[] colors;
|
private int[] colors;
|
||||||
|
private float prevX;
|
||||||
|
private float prevY;
|
||||||
|
|
||||||
public HabitStreakView(Context context, Habit habit, int columnWidth)
|
public HabitStreakView(Context context, Habit habit, int columnWidth)
|
||||||
{
|
{
|
||||||
@@ -98,7 +103,7 @@ public class HabitStreakView extends View
|
|||||||
float lineHeight = pText.getFontSpacing();
|
float lineHeight = pText.getFontSpacing();
|
||||||
float barHeaderOffset = lineHeight * 0.4f;
|
float barHeaderOffset = lineHeight * 0.4f;
|
||||||
|
|
||||||
int start = Math.max(0, streakStart.length - nColumns);
|
int start = Math.max(0, streakStart.length - nColumns - dataOffset);
|
||||||
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
SimpleDateFormat dfMonth = new SimpleDateFormat("MMM");
|
||||||
|
|
||||||
String previousMonth = "";
|
String previousMonth = "";
|
||||||
@@ -125,4 +130,51 @@ public class HabitStreakView extends View
|
|||||||
previousMonth = month;
|
previousMonth = month;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event)
|
||||||
|
{
|
||||||
|
int action = event.getAction();
|
||||||
|
|
||||||
|
int pointerIndex = MotionEventCompat.getActionIndex(event);
|
||||||
|
final float x = MotionEventCompat.getX(event, pointerIndex);
|
||||||
|
final float y = MotionEventCompat.getY(event, pointerIndex);
|
||||||
|
|
||||||
|
if (action == MotionEvent.ACTION_DOWN)
|
||||||
|
{
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == MotionEvent.ACTION_MOVE)
|
||||||
|
{
|
||||||
|
float dx = x - prevX;
|
||||||
|
float dy = y - prevY;
|
||||||
|
|
||||||
|
if (Math.abs(dy) > Math.abs(dx)) return false;
|
||||||
|
getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
|
if(move(dx))
|
||||||
|
{
|
||||||
|
prevX = x;
|
||||||
|
prevY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean move(float dx)
|
||||||
|
{
|
||||||
|
int newDataOffset = dataOffset + (int) (dx / columnWidth);
|
||||||
|
newDataOffset = Math.max(0, Math.min(streakStart.length - nColumns, newDataOffset));
|
||||||
|
|
||||||
|
if (newDataOffset != dataOffset)
|
||||||
|
{
|
||||||
|
dataOffset = newDataOffset;
|
||||||
|
invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,8 @@ public class RingView extends View
|
|||||||
pRing.setColor(color);
|
pRing.setColor(color);
|
||||||
pRing.setAntiAlias(true);
|
pRing.setAntiAlias(true);
|
||||||
pRing.setTextAlign(Paint.Align.CENTER);
|
pRing.setTextAlign(Paint.Align.CENTER);
|
||||||
pRing.setTextSize(size * 0.15f);
|
|
||||||
|
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
||||||
lineHeight = pRing.getFontSpacing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,16 +49,19 @@ public class RingView extends View
|
|||||||
RectF r = new RectF(0, 0, size, size);
|
RectF r = new RectF(0, 0, size, size);
|
||||||
canvas.drawArc(r, -90, 360 * perc, true, pRing);
|
canvas.drawArc(r, -90, 360 * perc, true, pRing);
|
||||||
|
|
||||||
|
|
||||||
pRing.setColor(Color.rgb(230, 230, 230));
|
pRing.setColor(Color.rgb(230, 230, 230));
|
||||||
canvas.drawArc(r, 360 * perc - 90 + 2, 360 * (1-perc) - 4, true, pRing);
|
canvas.drawArc(r, 360 * perc - 90 + 2, 360 * (1 - perc) - 4, true, pRing);
|
||||||
|
|
||||||
pRing.setColor(Color.WHITE);
|
pRing.setColor(Color.WHITE);
|
||||||
r.inset(thickness, thickness);
|
r.inset(thickness, thickness);
|
||||||
canvas.drawArc(r, -90, 360, true, pRing);
|
canvas.drawArc(r, -90, 360, true, pRing);
|
||||||
|
|
||||||
pRing.setColor(Color.GRAY);
|
pRing.setColor(Color.GRAY);
|
||||||
canvas.drawText(String.format("%.2f%%", perc*100), r.centerX(), r.centerY()+lineHeight/3, pRing);
|
pRing.setTextSize(size * 0.2f);
|
||||||
|
lineHeight = pRing.getFontSpacing();
|
||||||
|
canvas.drawText(String.format("%.0f%%", perc * 100), r.centerX(), r.centerY()+lineHeight/3, pRing);
|
||||||
|
|
||||||
|
pRing.setTextSize(size * 0.15f);
|
||||||
canvas.drawText(label, size/2, size + lineHeight * 1.2f, pRing);
|
canvas.drawText(label, size/2, size + lineHeight * 1.2f, pRing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
BIN
app/src/main/res/drawable/stripe.png
Normal file
|
After Width: | Height: | Size: 344 B |
@@ -1,21 +1,35 @@
|
|||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fillViewport="true"
|
android:background="@color/windowBackground"
|
||||||
android:background="@color/windowBackground">
|
android:fillViewport="true">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/cardsListStyle"
|
style="@style/cardsListStyle"
|
||||||
tools:context="org.isoron.uhabits.ShowHabitActivity">
|
tools:context="org.isoron.uhabits.ShowHabitActivity">
|
||||||
|
|
||||||
<LinearLayout style="@style/cardStyle"
|
<LinearLayout
|
||||||
android:id="@+id/llOverview">
|
android:id="@+id/llOverview"
|
||||||
|
style="@style/cardStyle"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvOverview"
|
android:id="@+id/tvOverview"
|
||||||
style="@style/cardHeaderStyle"
|
style="@style/cardHeaderStyle"
|
||||||
android:text="@string/overview" />
|
android:text="@string/overview"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llStrength"
|
||||||
|
style="@style/cardStyle"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvStrength"
|
||||||
|
style="@style/cardHeaderStyle"
|
||||||
|
android:text="@string/habit_strength"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -24,13 +38,13 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvHistory"
|
android:id="@+id/tvHistory"
|
||||||
style="@style/cardHeaderStyle"
|
style="@style/cardHeaderStyle"
|
||||||
android:text="@string/history" />
|
android:text="@string/history"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/llHistory"
|
android:id="@+id/llHistory"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal" />
|
android:orientation="horizontal"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout style="@style/cardStyle">
|
<LinearLayout style="@style/cardStyle">
|
||||||
@@ -38,13 +52,13 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvStreaks"
|
android:id="@+id/tvStreaks"
|
||||||
style="@style/cardHeaderStyle"
|
style="@style/cardHeaderStyle"
|
||||||
android:text="@string/streaks" />
|
android:text="@string/streaks"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/llStreaks"
|
android:id="@+id/llStreaks"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal" />
|
android:orientation="horizontal"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
@@ -14,19 +14,9 @@
|
|||||||
<style name="MyDialogStyle" parent="android:Theme.Material.Light.Dialog">
|
<style name="MyDialogStyle" parent="android:Theme.Material.Light.Dialog">
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="cardStyle">
|
<style name="cardStyle" parent="cardBasicStyle">
|
||||||
<item name="android:layout_width">match_parent</item>
|
|
||||||
<item name="android:layout_height">wrap_content</item>
|
|
||||||
<item name="android:background">@color/white</item>
|
<item name="android:background">@color/white</item>
|
||||||
<item name="android:elevation">1dp</item>
|
<item name="android:elevation">1dp</item>
|
||||||
<item name="android:orientation">vertical</item>
|
|
||||||
<item name="android:paddingTop">16dp</item>
|
|
||||||
<item name="android:paddingBottom">16dp</item>
|
|
||||||
<item name="android:paddingLeft">16dp</item>
|
|
||||||
<item name="android:paddingRight">4dp</item>
|
|
||||||
<item name="android:layout_marginBottom">3dp</item>
|
|
||||||
<item name="android:layout_marginLeft">3dp</item>
|
|
||||||
<item name="android:layout_marginRight">3dp</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,20 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="habitsListHeaderStyle">
|
<style name="habitsListHeaderStyle" parent="habitsListHeaderBasicStyle">
|
||||||
<item name="android:layout_width">match_parent</item>
|
|
||||||
<item name="android:layout_height">wrap_content</item>
|
|
||||||
<item name="android:layout_alignParentTop">true</item>
|
|
||||||
<item name="android:background">#f0f0f0</item>
|
<item name="android:background">#f0f0f0</item>
|
||||||
<item name="android:elevation">2dp</item>
|
<item name="android:elevation">2dp</item>
|
||||||
<item name="android:paddingRight">4dp</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="habitsListCheckStyle">
|
<style name="habitsListCheckStyle" parent="habitsListCheckBasicStyle">
|
||||||
<item name="android:focusable">false</item>
|
|
||||||
<item name="android:minHeight">42dp</item>
|
|
||||||
<item name="android:minWidth">42dp</item>
|
|
||||||
<item name="android:gravity">center</item>
|
|
||||||
<item name="android:background">@drawable/ripple_background</item>
|
<item name="android:background">@drawable/ripple_background</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
30
app/src/main/res/values/attrs_dslv.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="DragSortListView">
|
||||||
|
<attr name="collapsed_height" format="dimension"/>
|
||||||
|
<attr name="drag_scroll_start" format="float"/>
|
||||||
|
<attr name="max_drag_scroll_speed" format="float"/>
|
||||||
|
<attr name="float_background_color" format="color"/>
|
||||||
|
<attr name="remove_mode">
|
||||||
|
<enum name="clickRemove" value="0"/>
|
||||||
|
<enum name="flingRemove" value="1"/>
|
||||||
|
</attr>
|
||||||
|
<attr name="track_drag_sort" format="boolean"/>
|
||||||
|
<attr name="float_alpha" format="float"/>
|
||||||
|
<attr name="slide_shuffle_speed" format="float"/>
|
||||||
|
<attr name="remove_animation_duration" format="integer"/>
|
||||||
|
<attr name="drop_animation_duration" format="integer"/>
|
||||||
|
<attr name="drag_enabled" format="boolean"/>
|
||||||
|
<attr name="sort_enabled" format="boolean"/>
|
||||||
|
<attr name="remove_enabled" format="boolean"/>
|
||||||
|
<attr name="drag_start_mode">
|
||||||
|
<enum name="onDown" value="0"/>
|
||||||
|
<enum name="onMove" value="1"/>
|
||||||
|
<enum name="onLongPress" value="2"/>
|
||||||
|
</attr>
|
||||||
|
<attr name="drag_handle_id" format="integer"/>
|
||||||
|
<attr name="fling_handle_id" format="integer"/>
|
||||||
|
<attr name="click_remove_id" format="integer"/>
|
||||||
|
<attr name="use_default_controller" format="boolean"/>
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
@@ -1,54 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
|
||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
<dimen name="small_square_size">20dp</dimen>
|
||||||
<dimen name="square_size">20dp</dimen>
|
<dimen name="check_square_size">42dp</dimen>
|
||||||
|
|
||||||
<!-- Color picker -->
|
|
||||||
<dimen name="color_swatch_large">64dip</dimen>
|
|
||||||
<dimen name="color_swatch_small">48dip</dimen>
|
|
||||||
<dimen name="color_swatch_margins_large">8dip</dimen>
|
|
||||||
<dimen name="color_swatch_margins_small">4dip</dimen>
|
|
||||||
|
|
||||||
<!-- Date and time picker -->
|
|
||||||
<item name="circle_radius_multiplier" format="float" type="string">0.82</item>
|
|
||||||
<item name="circle_radius_multiplier_24HourMode" format="float" type="string">0.85</item>
|
|
||||||
<item name="selection_radius_multiplier" format="float" type="string">0.16</item>
|
|
||||||
<item name="ampm_circle_radius_multiplier" format="float" type="string">0.19</item>
|
|
||||||
<item name="numbers_radius_multiplier_normal" format="float" type="string">0.81</item>
|
|
||||||
<item name="numbers_radius_multiplier_inner" format="float" type="string">0.60</item>
|
|
||||||
<item name="numbers_radius_multiplier_outer" format="float" type="string">0.83</item>
|
|
||||||
<item name="text_size_multiplier_normal" format="float" type="string">0.17</item>
|
|
||||||
<item name="text_size_multiplier_inner" format="float" type="string">0.14</item>
|
|
||||||
<item name="text_size_multiplier_outer" format="float" type="string">0.11</item>
|
|
||||||
<dimen name="time_label_size">60sp</dimen>
|
|
||||||
<dimen name="extra_time_label_margin">-30dp</dimen>
|
|
||||||
<dimen name="ampm_label_size">16sp</dimen>
|
|
||||||
<dimen name="done_label_size">14sp</dimen>
|
|
||||||
<dimen name="ampm_left_padding">6dip</dimen>
|
|
||||||
<dimen name="separator_padding">4dip</dimen>
|
|
||||||
<dimen name="header_height">96dip</dimen>
|
|
||||||
<dimen name="footer_height">48dip</dimen>
|
|
||||||
<dimen name="minimum_margin_sides">48dip</dimen>
|
|
||||||
<dimen name="minimum_margin_top_bottom">24dip</dimen>
|
|
||||||
<dimen name="picker_dimen">270dip</dimen>
|
|
||||||
<dimen name="date_picker_component_width">270dp</dimen>
|
|
||||||
<dimen name="date_picker_header_height">30dp</dimen>
|
|
||||||
<dimen name="selected_calendar_layout_height">155dp</dimen>
|
|
||||||
<dimen name="date_picker_view_animator_height">270dp</dimen>
|
|
||||||
<dimen name="done_button_height">42dp</dimen>
|
|
||||||
<dimen name="month_list_item_header_height">50dp</dimen>
|
|
||||||
<dimen name="month_day_label_text_size">10sp</dimen>
|
|
||||||
<dimen name="day_number_select_circle_radius">16dp</dimen>
|
|
||||||
<dimen name="month_select_circle_radius">45dp</dimen>
|
|
||||||
<dimen name="selected_date_year_size">30dp</dimen>
|
|
||||||
<dimen name="selected_date_day_size">75dp</dimen>
|
|
||||||
<dimen name="selected_date_month_size">30dp</dimen>
|
|
||||||
<dimen name="date_picker_header_text_size">14dp</dimen>
|
|
||||||
<dimen name="month_label_size">16sp</dimen>
|
|
||||||
<dimen name="day_number_size">16sp</dimen>
|
|
||||||
<dimen name="year_label_height">64dp</dimen>
|
|
||||||
<dimen name="year_label_text_size">22dp</dimen>
|
|
||||||
</resources>
|
</resources>
|
||||||
7
app/src/main/res/values/dimens_color_picker.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<dimen name="color_swatch_large">64dip</dimen>
|
||||||
|
<dimen name="color_swatch_small">48dip</dimen>
|
||||||
|
<dimen name="color_swatch_margins_large">8dip</dimen>
|
||||||
|
<dimen name="color_swatch_margins_small">4dip</dimen>
|
||||||
|
</resources>
|
||||||
42
app/src/main/res/values/dimens_date_time.xml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item name="circle_radius_multiplier" format="float" type="string">0.82</item>
|
||||||
|
<item name="circle_radius_multiplier_24HourMode" format="float" type="string">0.85</item>
|
||||||
|
<item name="selection_radius_multiplier" format="float" type="string">0.16</item>
|
||||||
|
<item name="ampm_circle_radius_multiplier" format="float" type="string">0.19</item>
|
||||||
|
<item name="numbers_radius_multiplier_normal" format="float" type="string">0.81</item>
|
||||||
|
<item name="numbers_radius_multiplier_inner" format="float" type="string">0.60</item>
|
||||||
|
<item name="numbers_radius_multiplier_outer" format="float" type="string">0.83</item>
|
||||||
|
<item name="text_size_multiplier_normal" format="float" type="string">0.17</item>
|
||||||
|
<item name="text_size_multiplier_inner" format="float" type="string">0.14</item>
|
||||||
|
<item name="text_size_multiplier_outer" format="float" type="string">0.11</item>
|
||||||
|
|
||||||
|
<dimen name="time_label_size">60sp</dimen>
|
||||||
|
<dimen name="extra_time_label_margin">-30dp</dimen>
|
||||||
|
<dimen name="ampm_label_size">16sp</dimen>
|
||||||
|
<dimen name="done_label_size">14sp</dimen>
|
||||||
|
<dimen name="ampm_left_padding">6dip</dimen>
|
||||||
|
<dimen name="separator_padding">4dip</dimen>
|
||||||
|
<dimen name="header_height">96dip</dimen>
|
||||||
|
<dimen name="footer_height">48dip</dimen>
|
||||||
|
<dimen name="minimum_margin_sides">48dip</dimen>
|
||||||
|
<dimen name="minimum_margin_top_bottom">24dip</dimen>
|
||||||
|
<dimen name="picker_dimen">270dip</dimen>
|
||||||
|
<dimen name="date_picker_component_width">270dp</dimen>
|
||||||
|
<dimen name="date_picker_header_height">30dp</dimen>
|
||||||
|
<dimen name="selected_calendar_layout_height">155dp</dimen>
|
||||||
|
<dimen name="date_picker_view_animator_height">270dp</dimen>
|
||||||
|
<dimen name="done_button_height">42dp</dimen>
|
||||||
|
<dimen name="month_list_item_header_height">50dp</dimen>
|
||||||
|
<dimen name="month_day_label_text_size">10sp</dimen>
|
||||||
|
<dimen name="day_number_select_circle_radius">16dp</dimen>
|
||||||
|
<dimen name="month_select_circle_radius">45dp</dimen>
|
||||||
|
<dimen name="selected_date_year_size">30dp</dimen>
|
||||||
|
<dimen name="selected_date_day_size">75dp</dimen>
|
||||||
|
<dimen name="selected_date_month_size">30dp</dimen>
|
||||||
|
<dimen name="date_picker_header_text_size">14dp</dimen>
|
||||||
|
<dimen name="month_label_size">16sp</dimen>
|
||||||
|
<dimen name="day_number_size">16sp</dimen>
|
||||||
|
<dimen name="year_label_height">64dp</dimen>
|
||||||
|
<dimen name="year_label_text_size">22dp</dimen>
|
||||||
|
</resources>
|
||||||
@@ -25,20 +25,24 @@
|
|||||||
<item name="android:orientation">vertical</item>
|
<item name="android:orientation">vertical</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="cardStyle">
|
<style name="cardBasicStyle">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
<item name="android:background">@drawable/card_background</item>
|
|
||||||
<item name="android:orientation">vertical</item>
|
<item name="android:orientation">vertical</item>
|
||||||
<item name="android:paddingTop">16dp</item>
|
<item name="android:paddingTop">16dp</item>
|
||||||
<item name="android:paddingBottom">16dp</item>
|
<item name="android:paddingBottom">16dp</item>
|
||||||
<item name="android:paddingLeft">16dp</item>
|
<item name="android:paddingLeft">16dp</item>
|
||||||
<item name="android:paddingRight">4dp</item>
|
<item name="android:paddingRight">4dp</item>
|
||||||
<item name="android:layout_marginBottom">1dp</item>
|
<item name="android:layout_marginBottom">3dp</item>
|
||||||
<item name="android:layout_marginLeft">3dp</item>
|
<item name="android:layout_marginLeft">3dp</item>
|
||||||
<item name="android:layout_marginRight">3dp</item>
|
<item name="android:layout_marginRight">3dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="cardStyle" parent="cardBasicStyle">
|
||||||
|
<item name="android:background">@drawable/card_background</item>
|
||||||
|
<item name="android:layout_marginBottom">1dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="cardHeaderStyle">
|
<style name="cardHeaderStyle">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
|||||||
@@ -10,11 +10,15 @@
|
|||||||
<item name="android:background">@color/windowBackground</item>
|
<item name="android:background">@color/windowBackground</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="habitsListHeaderStyle">
|
|
||||||
|
<style name="habitsListHeaderBasicStyle">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
<item name="android:layout_alignParentTop">true</item>
|
<item name="android:layout_alignParentTop">true</item>
|
||||||
<item name="android:paddingRight">4dp</item>
|
<item name="android:paddingRight">4dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="habitsListHeaderStyle" parent="habitsListHeaderBasicStyle">
|
||||||
<item name="android:background">@drawable/habits_list_header_background</item>
|
<item name="android:background">@drawable/habits_list_header_background</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -58,13 +62,16 @@
|
|||||||
<item name="android:padding">3dp</item>
|
<item name="android:padding">3dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="habitsListCheckStyle">
|
<style name="habitsListCheckBasicStyle">
|
||||||
<item name="android:focusable">false</item>
|
<item name="android:focusable">false</item>
|
||||||
<item name="android:minHeight">42dp</item>
|
<item name="android:minHeight">@dimen/check_square_size</item>
|
||||||
<item name="android:minWidth">42dp</item>
|
<item name="android:minWidth">@dimen/check_square_size</item>
|
||||||
<item name="android:gravity">center</item>
|
<item name="android:gravity">center</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="habitsListCheckStyle" parent="habitsListCheckBasicStyle">
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="habitsListHeaderCheckStyle" parent="habitsListCheckStyle">
|
<style name="habitsListHeaderCheckStyle" parent="habitsListCheckStyle">
|
||||||
<item name="android:layout_width">42dp</item>
|
<item name="android:layout_width">42dp</item>
|
||||||
<item name="android:layout_height">match_parent</item>
|
<item name="android:layout_height">match_parent</item>
|
||||||
|
|||||||