Merge branch 'master' into 4.0
Conflicts: astrid/AndroidManifest.xml astrid/plugin-src/com/todoroo/astrid/actfm/TagViewActivity.java astrid/project.properties astrid/res/drawable-hdpi/widget_frame.png astrid/res/drawable-land-hdpi/widget_frame.png astrid/res/drawable-land/widget_frame.png astrid/res/drawable/widget_frame.png astrid/res/layout/task_list_activity.xml astrid/src/com/todoroo/astrid/activity/FilterListActivity.java astrid/src/com/todoroo/astrid/activity/TaskListActivity.java greendroid/GreenDroid/.classpathpull/14/head
@ -0,0 +1,198 @@
|
|||||||
|
package com.mdimension.jchronic;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.mdimension.jchronic.handlers.Handler;
|
||||||
|
import com.mdimension.jchronic.numerizer.Numerizer;
|
||||||
|
import com.mdimension.jchronic.repeaters.Repeater;
|
||||||
|
import com.mdimension.jchronic.tags.Grabber;
|
||||||
|
import com.mdimension.jchronic.tags.Ordinal;
|
||||||
|
import com.mdimension.jchronic.tags.Pointer;
|
||||||
|
import com.mdimension.jchronic.tags.Scalar;
|
||||||
|
import com.mdimension.jchronic.tags.Separator;
|
||||||
|
import com.mdimension.jchronic.tags.TimeZone;
|
||||||
|
import com.mdimension.jchronic.utils.Span;
|
||||||
|
import com.mdimension.jchronic.utils.Token;
|
||||||
|
|
||||||
|
public class AstridChronic {
|
||||||
|
public static final String VERSION = "0.2.3";
|
||||||
|
|
||||||
|
private AstridChronic() {
|
||||||
|
// DO NOTHING
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Span parse(String text) {
|
||||||
|
return AstridChronic.parse(text, new Options());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string containing a natural language date or time. If the parser
|
||||||
|
* can find a date or time, either a Time or Chronic::Span will be returned
|
||||||
|
* (depending on the value of <tt>:guess</tt>). If no date or time can be found,
|
||||||
|
* +nil+ will be returned.
|
||||||
|
*
|
||||||
|
* Options are:
|
||||||
|
*
|
||||||
|
* [<tt>:context</tt>]
|
||||||
|
* <tt>:past</tt> or <tt>:future</tt> (defaults to <tt>:future</tt>)
|
||||||
|
*
|
||||||
|
* If your string represents a birthday, you can set <tt>:context</tt> to <tt>:past</tt>
|
||||||
|
* and if an ambiguous string is given, it will assume it is in the
|
||||||
|
* past. Specify <tt>:future</tt> or omit to set a future context.
|
||||||
|
*
|
||||||
|
* [<tt>:now</tt>]
|
||||||
|
* Time (defaults to Time.now)
|
||||||
|
*
|
||||||
|
* By setting <tt>:now</tt> to a Time, all computations will be based off
|
||||||
|
* of that time instead of Time.now
|
||||||
|
*
|
||||||
|
* [<tt>:guess</tt>]
|
||||||
|
* +true+ or +false+ (defaults to +true+)
|
||||||
|
*
|
||||||
|
* By default, the parser will guess a single point in time for the
|
||||||
|
* given date or time. If you'd rather have the entire time span returned,
|
||||||
|
* set <tt>:guess</tt> to +false+ and a Chronic::Span will be returned.
|
||||||
|
*
|
||||||
|
* [<tt>:ambiguous_time_range</tt>]
|
||||||
|
* Integer or <tt>:none</tt> (defaults to <tt>6</tt> (6am-6pm))
|
||||||
|
*
|
||||||
|
* If an Integer is given, ambiguous times (like 5:00) will be
|
||||||
|
* assumed to be within the range of that time in the AM to that time
|
||||||
|
* in the PM. For example, if you set it to <tt>7</tt>, then the parser will
|
||||||
|
* look for the time between 7am and 7pm. In the case of 5:00, it would
|
||||||
|
* assume that means 5:00pm. If <tt>:none</tt> is given, no assumption
|
||||||
|
* will be made, and the first matching instance of that time will
|
||||||
|
* be used.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Span parse(String text, Options options) {
|
||||||
|
// store now for later =)
|
||||||
|
//_now = options.getNow();
|
||||||
|
|
||||||
|
// put the text into a normal format to ease scanning
|
||||||
|
String normalizedText = AstridChronic.preNormalize(text);
|
||||||
|
|
||||||
|
// get base tokens for each word
|
||||||
|
List<Token> tokens = AstridChronic.baseTokenize(normalizedText);
|
||||||
|
|
||||||
|
try {
|
||||||
|
tokens = Repeater.scan(tokens, options);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException("Failed to scan tokens.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Class> scannerClasses = new LinkedList<Class>();
|
||||||
|
scannerClasses.add(Grabber.class);
|
||||||
|
scannerClasses.add(Pointer.class);
|
||||||
|
scannerClasses.add(Scalar.class);
|
||||||
|
scannerClasses.add(Ordinal.class);
|
||||||
|
scannerClasses.add(Separator.class);
|
||||||
|
scannerClasses.add(TimeZone.class);
|
||||||
|
for (Class scannerClass : scannerClasses) {
|
||||||
|
try {
|
||||||
|
tokens = (List<Token>) scannerClass.getMethod("scan", List.class, Options.class).invoke(null, tokens, options);
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
throw new RuntimeException("Failed to scan tokens.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Token> taggedTokens = new LinkedList<Token>();
|
||||||
|
for (Token token : tokens) {
|
||||||
|
if (token.isTagged()) {
|
||||||
|
taggedTokens.add(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokens = taggedTokens;
|
||||||
|
|
||||||
|
if (options.isDebug()) {
|
||||||
|
System.out.println("Chronic.parse: " + tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
Span span = Handler.tokensToSpan(tokens, options);
|
||||||
|
|
||||||
|
// guess a time within a span if required
|
||||||
|
if (options.isGuess()) {
|
||||||
|
span = guess(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
return span;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up the specified input text by stripping unwanted characters,
|
||||||
|
* converting idioms to their canonical form, converting number words
|
||||||
|
* to numbers (three => 3), and converting ordinal words to numeric
|
||||||
|
* ordinals (third => 3rd)
|
||||||
|
*/
|
||||||
|
protected static String preNormalize(String text) {
|
||||||
|
String normalizedText = text.toLowerCase();
|
||||||
|
normalizedText = Chronic.numericizeNumbers(normalizedText);
|
||||||
|
normalizedText = normalizedText.replaceAll("['\"\\.]", "");
|
||||||
|
normalizedText = normalizedText.replaceAll("([/\\-,@])", " $1 ");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\btoday\\b", "this day");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\btomm?orr?ow\\b", "next day");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\byesterday\\b", "last day");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\bnoon\\b", "12:00");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\bmidnight\\b", "24:00");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\bbefore now\\b", "past");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\bnow\\b", "this second");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\b(ago|before)\\b", "past");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\bthis past\\b", "last");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\bthis last\\b", "last");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\b(?:in|during) the (morning)\\b", "$1");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\b(?:in the|during the|at) (afternoon|evening|night)\\b", "$1");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\btonight\\b", "this night");
|
||||||
|
normalizedText = normalizedText.replaceAll("(?=\\w)([ap]m|oclock)\\b", " $1");
|
||||||
|
normalizedText = normalizedText.replaceAll("\\b(hence|after|from)\\b", "future");
|
||||||
|
normalizedText = AstridChronic.numericizeOrdinals(normalizedText);
|
||||||
|
return normalizedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert number words to numbers (three => 3)
|
||||||
|
*/
|
||||||
|
protected static String numericizeNumbers(String text) {
|
||||||
|
return Numerizer.numerize(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert ordinal words to numeric ordinals (third => 3rd)
|
||||||
|
*/
|
||||||
|
protected static String numericizeOrdinals(String text) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the text on spaces and convert each word into
|
||||||
|
* a Token
|
||||||
|
*/
|
||||||
|
protected static List<Token> baseTokenize(String text) {
|
||||||
|
String[] words = text.split(" ");
|
||||||
|
List<Token> tokens = new LinkedList<Token>();
|
||||||
|
for (String word : words) {
|
||||||
|
tokens.add(new Token(word));
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guess a specific time within the given span
|
||||||
|
*/
|
||||||
|
// DIFF: We return Span instead of Date
|
||||||
|
protected static Span guess(Span span) {
|
||||||
|
if (span == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
long guessValue;
|
||||||
|
if (span.getWidth() > 1) {
|
||||||
|
guessValue = span.getBegin() + (span.getWidth() / 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
guessValue = span.getBegin();
|
||||||
|
}
|
||||||
|
Span guess = new Span(guessValue, guessValue);
|
||||||
|
return guess;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,234 @@
|
|||||||
|
/**
|
||||||
|
* See the file "LICENSE" for the full license governing this code.
|
||||||
|
*/
|
||||||
|
package com.todoroo.astrid.actfm.sync;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import com.todoroo.andlib.data.TodorooCursor;
|
||||||
|
import com.todoroo.andlib.service.Autowired;
|
||||||
|
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||||
|
import com.todoroo.andlib.service.ExceptionService;
|
||||||
|
import com.todoroo.andlib.sql.Criterion;
|
||||||
|
import com.todoroo.andlib.sql.Query;
|
||||||
|
import com.todoroo.andlib.utility.Preferences;
|
||||||
|
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
|
||||||
|
import com.todoroo.astrid.data.TagData;
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
import com.todoroo.astrid.service.AstridDependencyInjector;
|
||||||
|
import com.todoroo.astrid.service.StartupService;
|
||||||
|
import com.todoroo.astrid.service.SyncV2Service.SyncResultCallback;
|
||||||
|
import com.todoroo.astrid.service.SyncV2Service.SyncV2Provider;
|
||||||
|
import com.todoroo.astrid.service.TaskService;
|
||||||
|
import com.todoroo.astrid.tags.TagService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes sync action
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ActFmSyncV2Provider implements SyncV2Provider {
|
||||||
|
|
||||||
|
@Autowired ActFmPreferenceService actFmPreferenceService;
|
||||||
|
|
||||||
|
@Autowired ActFmSyncService actFmSyncService;
|
||||||
|
|
||||||
|
@Autowired ExceptionService exceptionService;
|
||||||
|
|
||||||
|
@Autowired TaskService taskService;
|
||||||
|
|
||||||
|
static {
|
||||||
|
AstridDependencyInjector.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActFmSyncV2Provider() {
|
||||||
|
DependencyInjectionService.getInstance().inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return actFmPreferenceService.isLoggedIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String LAST_TAG_FETCH_TIME = "actfm_lastTag"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
// --- synchronize active tasks
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void synchronizeActiveTasks(boolean manual,
|
||||||
|
final SyncResultCallback callback) {
|
||||||
|
|
||||||
|
callback.started();
|
||||||
|
callback.incrementMax(100);
|
||||||
|
|
||||||
|
final AtomicInteger finisher = new AtomicInteger(2);
|
||||||
|
|
||||||
|
startTagFetcher(callback, finisher);
|
||||||
|
|
||||||
|
startTaskFetcher(manual, callback, finisher);
|
||||||
|
|
||||||
|
pushQueued(callback, finisher);
|
||||||
|
|
||||||
|
callback.incrementProgress(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** fetch changes to tags */
|
||||||
|
private void startTagFetcher(final SyncResultCallback callback,
|
||||||
|
final AtomicInteger finisher) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int time = Preferences.getInt(LAST_TAG_FETCH_TIME, 0);
|
||||||
|
try {
|
||||||
|
time = actFmSyncService.fetchTags(time);
|
||||||
|
Preferences.setInt(LAST_TAG_FETCH_TIME, time);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
exceptionService.reportError("actfm-sync", e); //$NON-NLS-1$
|
||||||
|
} catch (IOException e) {
|
||||||
|
exceptionService.reportError("actfm-sync", e); //$NON-NLS-1$
|
||||||
|
} finally {
|
||||||
|
callback.incrementProgress(20);
|
||||||
|
if(finisher.decrementAndGet() == 0)
|
||||||
|
callback.finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return runnable to fetch changes to tags */
|
||||||
|
private void startTaskFetcher(final boolean manual, final SyncResultCallback callback,
|
||||||
|
final AtomicInteger finisher) {
|
||||||
|
actFmSyncService.fetchActiveTasks(manual, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
callback.incrementProgress(30);
|
||||||
|
if(finisher.decrementAndGet() == 0)
|
||||||
|
callback.finished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushQueued(final SyncResultCallback callback,
|
||||||
|
final AtomicInteger finisher) {
|
||||||
|
TodorooCursor<Task> cursor = taskService.query(Query.select(Task.PROPERTIES).
|
||||||
|
where(Criterion.or(
|
||||||
|
Criterion.and(TaskCriteria.isActive(),
|
||||||
|
Task.ID.gt(StartupService.INTRO_TASK_SIZE),
|
||||||
|
Task.REMOTE_ID.eq(0)),
|
||||||
|
Criterion.and(Task.REMOTE_ID.gt(0),
|
||||||
|
Task.MODIFICATION_DATE.gt(Task.LAST_SYNC)))));
|
||||||
|
|
||||||
|
try {
|
||||||
|
callback.incrementMax(cursor.getCount() * 20);
|
||||||
|
finisher.addAndGet(cursor.getCount());
|
||||||
|
|
||||||
|
for(int i = 0; i < cursor.getCount(); i++) {
|
||||||
|
cursor.moveToNext();
|
||||||
|
final Task task = new Task(cursor);
|
||||||
|
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
actFmSyncService.pushTaskOnSave(task, task.getMergedValues());
|
||||||
|
} finally {
|
||||||
|
callback.incrementProgress(20);
|
||||||
|
if(finisher.decrementAndGet() == 0)
|
||||||
|
callback.finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- synchronize list
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void synchronizeList(Object list, boolean manual,
|
||||||
|
final SyncResultCallback callback) {
|
||||||
|
|
||||||
|
if(!(list instanceof TagData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TagData tagData = (TagData) list;
|
||||||
|
final boolean noRemoteId = tagData.getValue(TagData.REMOTE_ID) == 0;
|
||||||
|
|
||||||
|
if(noRemoteId && !manual)
|
||||||
|
return;
|
||||||
|
|
||||||
|
callback.started();
|
||||||
|
callback.incrementMax(100);
|
||||||
|
|
||||||
|
final AtomicInteger finisher = new AtomicInteger(3);
|
||||||
|
|
||||||
|
fetchTagData(tagData, noRemoteId, manual, callback, finisher);
|
||||||
|
|
||||||
|
if(!noRemoteId) {
|
||||||
|
fetchTasksForTag(tagData, manual, callback, finisher);
|
||||||
|
fetchUpdatesForTag(tagData, manual, callback, finisher);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.incrementProgress(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchTagData(final TagData tagData, final boolean noRemoteId,
|
||||||
|
final boolean manual, final SyncResultCallback callback,
|
||||||
|
final AtomicInteger finisher) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String oldName = tagData.getValue(TagData.NAME);
|
||||||
|
try {
|
||||||
|
actFmSyncService.fetchTag(tagData);
|
||||||
|
|
||||||
|
if(noRemoteId) {
|
||||||
|
fetchTasksForTag(tagData, manual, callback, finisher);
|
||||||
|
fetchUpdatesForTag(tagData, manual, callback, finisher);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!oldName.equals(tagData.getValue(TagData.NAME))) {
|
||||||
|
TagService.getInstance().rename(oldName,
|
||||||
|
tagData.getValue(TagData.NAME));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
exceptionService.reportError("sync-io", e); //$NON-NLS-1$
|
||||||
|
} catch (JSONException e) {
|
||||||
|
exceptionService.reportError("sync-json", e); //$NON-NLS-1$
|
||||||
|
} finally {
|
||||||
|
callback.incrementProgress(20);
|
||||||
|
if(finisher.decrementAndGet() == 0)
|
||||||
|
callback.finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchUpdatesForTag(TagData tagData, boolean manual, final SyncResultCallback callback,
|
||||||
|
final AtomicInteger finisher) {
|
||||||
|
actFmSyncService.fetchUpdatesForTag(tagData, manual, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
callback.incrementProgress(20);
|
||||||
|
if(finisher.decrementAndGet() == 0)
|
||||||
|
callback.finished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchTasksForTag(TagData tagData, boolean manual, final SyncResultCallback callback,
|
||||||
|
final AtomicInteger finisher) {
|
||||||
|
actFmSyncService.fetchTasksForTag(tagData, manual, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
callback.incrementProgress(30);
|
||||||
|
if(finisher.decrementAndGet() == 0)
|
||||||
|
callback.finished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 278 KiB |
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- xmlns:app="http://schemas.android.com/apk/res/com.viewpagerindicator.sample" -->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
>
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
android:id="@+id/pager"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<com.viewpagerindicator.CirclePageIndicator
|
||||||
|
android:id="@+id/indicator"
|
||||||
|
android:padding="15dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_alignBottom="@id/pager"
|
||||||
|
android:background="#00000000"
|
||||||
|
style="@style/CustomCirclePageIndicator"
|
||||||
|
/>
|
||||||
|
<!--
|
||||||
|
app:radius="10dp"
|
||||||
|
app:fillColor="#FF888888"
|
||||||
|
app:strokeColor="#FF000000"
|
||||||
|
app:strokeWidth="2dp" -->
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:paddingLeft="4dip"
|
||||||
|
android:paddingRight="4dip"
|
||||||
|
android:background="@drawable/welcome_walkthrough_fabric"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/logo"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="110dip"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:paddingBottom="10dip"
|
||||||
|
android:layout_marginTop="30dip"
|
||||||
|
android:text="Connect now\nto get started!"
|
||||||
|
android:textColor="#444444"
|
||||||
|
android:textSize="40dip"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDy="1"
|
||||||
|
android:shadowColor="@android:color/white" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/error"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#ff0000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="253dp"
|
||||||
|
android:paddingTop="5dip" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_later"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:paddingBottom="5dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="#ffffff" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/pw_login"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:layout_above="@id/login_later"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:layout_marginLeft="15dip"
|
||||||
|
android:layout_marginRight="15dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="@string/welcome_login_pw"/>
|
||||||
|
|
||||||
|
<com.facebook.android.LoginButton
|
||||||
|
android:id="@+id/fb_login"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:layout_above="@id/pw_login"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:layout_marginLeft="15dip"
|
||||||
|
android:layout_marginRight="15dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:drawableLeft="@drawable/facebook"
|
||||||
|
android:text="@string/actfm_ALA_fb_login" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/gg_login"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="45dip"
|
||||||
|
android:layout_above="@id/fb_login"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:layout_marginLeft="15dip"
|
||||||
|
android:layout_marginRight="15dip"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:drawableLeft="@drawable/google"
|
||||||
|
android:text="@string/actfm_ALA_gg_login" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tos"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="35dip"
|
||||||
|
android:layout_above="@id/gg_login"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip"
|
||||||
|
android:textSize="12.5sp"
|
||||||
|
android:textColor="#ffffff" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@drawable/welcome_walkthrough_fabric">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/welcome_walkthrough_title"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="27dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="Hello"
|
||||||
|
android:textColor="#444444"
|
||||||
|
android:textSize="40dip"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDy="1"
|
||||||
|
android:shadowColor="@android:color/white" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/welcome_walkthrough_image"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:src="@drawable/welcome_walkthrough_1"
|
||||||
|
android:scaleType="fitCenter"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/welcome_walkthrough_body"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="75dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:text="Hello"
|
||||||
|
android:textColor="#444444"
|
||||||
|
android:textSize="20dip"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDy="1"
|
||||||
|
android:shadowColor="@android:color/white" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="welcome_show_eula">Accept EULA to get started!</string>
|
||||||
|
|
||||||
|
<string name="welcome_title_1">Welcome to Astrid!</string>
|
||||||
|
<string name="welcome_title_2">Make lists</string>
|
||||||
|
<string name="welcome_title_3">Share lists</string>
|
||||||
|
<string name="welcome_title_4">Divvy up tasks</string>
|
||||||
|
<string name="welcome_title_5">Provide details</string>
|
||||||
|
<string name="welcome_title_6">Discover</string>
|
||||||
|
<string name="welcome_title_7">Login</string>
|
||||||
|
|
||||||
|
<string name="welcome_body_1">The perfect personal\nto-do list that works great\nwith friends</string>
|
||||||
|
<string name="welcome_body_2">Perfect for any list:\nto read, to watch, to buy,\nto visit, to do!</string>
|
||||||
|
<string name="welcome_body_3">Share lists\nwith friends, housemates,\nor your sweetheart!</string>
|
||||||
|
<string name="welcome_body_4">Never wonder who\'s\nbringing dessert!</string>
|
||||||
|
<string name="welcome_body_5">Tap to add notes,\nset reminders,\nand much more!</string>
|
||||||
|
<string name="welcome_body_6">Additional features,\nproductivity tips, and\nsuggestions from friends</string>
|
||||||
|
<string name="welcome_body_7">Login</string>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
package com.todoroo.astrid.helper;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.AlphaAnimation;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import com.todoroo.andlib.utility.AndroidUtilities;
|
||||||
|
import com.todoroo.astrid.service.SyncV2Service.SyncResultCallback;
|
||||||
|
|
||||||
|
public class ProgressBarSyncResultCallback implements SyncResultCallback {
|
||||||
|
|
||||||
|
private final ProgressBar progressBar;
|
||||||
|
private final Activity activity;
|
||||||
|
private final Runnable onFinished;
|
||||||
|
|
||||||
|
private final AtomicInteger providers = new AtomicInteger(0);
|
||||||
|
|
||||||
|
public ProgressBarSyncResultCallback(Activity activity,
|
||||||
|
int progressBarId, Runnable onFinished) {
|
||||||
|
this.progressBar = (ProgressBar) activity.findViewById(progressBarId);
|
||||||
|
this.activity = activity;
|
||||||
|
this.onFinished = onFinished;
|
||||||
|
progressBar.setProgress(0);
|
||||||
|
progressBar.setMax(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finished() {
|
||||||
|
if(providers.decrementAndGet() == 0) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressBar.setMax(100);
|
||||||
|
progressBar.setProgress(100);
|
||||||
|
AlphaAnimation animation = new AlphaAnimation(1, 0);
|
||||||
|
animation.setFillAfter(true);
|
||||||
|
animation.setDuration(1000L);
|
||||||
|
progressBar.startAnimation(animation);
|
||||||
|
|
||||||
|
onFinished.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
AndroidUtilities.sleepDeep(1000);
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incrementMax(final int incrementBy) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressBar.setMax(progressBar.getMax() + incrementBy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incrementProgress(final int incrementBy) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressBar.incrementProgressBy(incrementBy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void started() {
|
||||||
|
if(providers.incrementAndGet() == 1) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
AlphaAnimation animation = new AlphaAnimation(0, 1);
|
||||||
|
animation.setFillAfter(true);
|
||||||
|
animation.setDuration(1000L);
|
||||||
|
progressBar.startAnimation(animation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.todoroo.astrid.service;
|
||||||
|
|
||||||
|
import com.todoroo.astrid.actfm.sync.ActFmSyncV2Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SyncV2Service is a simplified synchronization interface for supporting
|
||||||
|
* next-generation sync interfaces such as Google Tasks and Astrid.com
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@astrid.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SyncV2Service {
|
||||||
|
|
||||||
|
public interface SyncResultCallback {
|
||||||
|
/**
|
||||||
|
* Increment max sync progress
|
||||||
|
* @param incrementBy
|
||||||
|
*/
|
||||||
|
public void incrementMax(int incrementBy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment current sync progress
|
||||||
|
* @param incrementBy
|
||||||
|
*/
|
||||||
|
public void incrementProgress(int incrementBy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider started sync
|
||||||
|
*/
|
||||||
|
public void started();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider finished sync
|
||||||
|
*/
|
||||||
|
public void finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface SyncV2Provider {
|
||||||
|
public boolean isActive();
|
||||||
|
public void synchronizeActiveTasks(boolean manual, SyncResultCallback callback);
|
||||||
|
public void synchronizeList(Object list, boolean manual, SyncResultCallback callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At present, sync provider interactions are handled through code. If
|
||||||
|
* there is enough interest, the Astrid team could create an interface
|
||||||
|
* for responding to sync requests through this new API.
|
||||||
|
*/
|
||||||
|
private final SyncV2Provider[] providers = new SyncV2Provider[] {
|
||||||
|
new ActFmSyncV2Provider()
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if synchronization is available
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
public boolean isActive() {
|
||||||
|
for(SyncV2Provider provider : providers) {
|
||||||
|
if(provider.isActive())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate synchronization of active tasks
|
||||||
|
*
|
||||||
|
* @param manual if manual sync
|
||||||
|
* @param callback result callback
|
||||||
|
*/
|
||||||
|
public void synchronizeActiveTasks(boolean manual, SyncResultCallback callback) {
|
||||||
|
for(SyncV2Provider provider : providers) {
|
||||||
|
if(provider.isActive())
|
||||||
|
provider.synchronizeActiveTasks(manual, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate synchronization of task list
|
||||||
|
*
|
||||||
|
* @param list list object
|
||||||
|
* @param manual if manual sync
|
||||||
|
* @param callback result callback
|
||||||
|
*/
|
||||||
|
public void synchronizeList(Object list, boolean manual, SyncResultCallback callback) {
|
||||||
|
for(SyncV2Provider provider : providers) {
|
||||||
|
if(provider.isActive())
|
||||||
|
provider.synchronizeList(list, manual, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,401 @@
|
|||||||
|
package com.todoroo.astrid.utility;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.google.ical.values.Frequency;
|
||||||
|
import com.google.ical.values.RRule;
|
||||||
|
import com.mdimension.jchronic.AstridChronic;
|
||||||
|
import com.mdimension.jchronic.Chronic;
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
|
||||||
|
|
||||||
|
public class TitleParser {
|
||||||
|
Task task;
|
||||||
|
ArrayList<String> tags;
|
||||||
|
|
||||||
|
public TitleParser(Task task, ArrayList<String> tags){
|
||||||
|
this.task = task;
|
||||||
|
this.tags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parse(){
|
||||||
|
repeatHelper(task);
|
||||||
|
dayHelper(task);
|
||||||
|
listHelper(task,tags);
|
||||||
|
priorityHelper(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void listHelper(Task task, ArrayList<String> tags) {
|
||||||
|
String inputText = task.getValue(Task.TITLE);
|
||||||
|
Pattern tagPattern = Pattern.compile("(\\s|^)#([^\\s]+)");
|
||||||
|
Pattern contextPattern = Pattern.compile("(\\s|^)(@[^\\s]+)");
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
Matcher m = tagPattern.matcher(inputText);
|
||||||
|
if(m.find()) {
|
||||||
|
tags.add(m.group(2));
|
||||||
|
} else {
|
||||||
|
m = contextPattern.matcher(inputText);
|
||||||
|
if(m.find()) {
|
||||||
|
tags.add(m.group(2));
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputText = inputText.substring(0, m.start()) + inputText.substring(m.end());
|
||||||
|
}
|
||||||
|
task.setValue(Task.TITLE, inputText.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
//helper method for priorityHelper. converts the string to a Task Importance
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
private static int str_to_priority(String priority_str) {
|
||||||
|
if (priority_str!=null)
|
||||||
|
priority_str.toLowerCase().trim();
|
||||||
|
int priority = Task.IMPORTANCE_DO_OR_DIE;
|
||||||
|
if ("0".equals(priority_str) || "!0".equals(priority_str) || "least".equals(priority_str) || "lowest".equals(priority_str))
|
||||||
|
priority = Task.IMPORTANCE_NONE;
|
||||||
|
if ("!".equals(priority_str) || "!1".equals(priority_str) || "bang".equals(priority_str) || "1".equals(priority_str) || "low".equals(priority_str))
|
||||||
|
priority = Task.IMPORTANCE_SHOULD_DO;
|
||||||
|
if ("!!".equals(priority_str) || "!2".equals(priority_str) || "bang bang".equals(priority_str) || "2".equals(priority_str) || "high".equals(priority_str))
|
||||||
|
priority = Task.IMPORTANCE_MUST_DO;
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
//priorityHelper parses the string and sets the Task's importance
|
||||||
|
private static void priorityHelper(Task task) {
|
||||||
|
String inputText = task.getValue(Task.TITLE);
|
||||||
|
String[] importanceStrings = {
|
||||||
|
"()((^|[^\\w!])!+|(^|[^\\w!])!\\d)($|[^\\w!])",
|
||||||
|
"()(?i)((\\s?bang){1,})$",
|
||||||
|
"(?i)(\\spriority\\s?(\\d)$)",
|
||||||
|
"(?i)(\\sbang\\s?(\\d)$)",
|
||||||
|
"(?i)()(\\shigh(est)?|\\slow(est)?|\\stop|\\sleast) ?priority$"
|
||||||
|
};
|
||||||
|
for (String importanceString:importanceStrings){
|
||||||
|
Pattern importancePattern= Pattern.compile(importanceString);
|
||||||
|
while (true){
|
||||||
|
Matcher m = importancePattern.matcher(inputText);
|
||||||
|
if(m.find()) {
|
||||||
|
task.setValue(Task.IMPORTANCE, str_to_priority(m.group(2).trim()));
|
||||||
|
inputText = inputText.substring(0, m.start()+1) + inputText.substring(m.end());
|
||||||
|
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task.setValue(Task.TITLE, inputText.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
//helper for dayHelper. Converts am/pm to an int 0/1.
|
||||||
|
private static int ampm_to_number(String am_pm_string) {
|
||||||
|
int time = Calendar.PM;
|
||||||
|
if (am_pm_string == null){
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
String text = am_pm_string.toLowerCase().trim();
|
||||||
|
if (text.equals ("am") || text.equals ("a.m") || text.equals("a"))
|
||||||
|
time = Calendar.AM;
|
||||||
|
if (text.equals ("pm") || text.equals ("p.m") || text.equals("p"))
|
||||||
|
time = Calendar.PM;
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------DATE--------------------------
|
||||||
|
//Handles setting the task's date.
|
||||||
|
//Day of week (e.g. Monday, Tuesday,..) is overridden by a set date (e.g. October 23 2013).
|
||||||
|
//Vague times (e.g. breakfast, night) are overridden by a set time (9 am, at 10, 17:00)
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
private static void dayHelper(Task task ) {
|
||||||
|
String inputText = task.getValue(Task.TITLE);
|
||||||
|
Calendar cal = null;
|
||||||
|
Boolean containsSpecificTime = false;
|
||||||
|
String[] days_of_week = {
|
||||||
|
"(?i)\\b(today)\\b",
|
||||||
|
"(?i)\\b(tomorrow)\\b",
|
||||||
|
"(?i)\\b(mon(day\\b|\\.))",
|
||||||
|
"(?i)\\b(tue(sday\\b|\\.))",
|
||||||
|
"(?i)\\b(wed(nesday\\b|\\.))",
|
||||||
|
"(?i)\\b(thu(rsday\\b|\\.))",
|
||||||
|
"(?i)\\b(fri(day\\b|\\.))",
|
||||||
|
"(?i)\\b(sat(urday\\b|\\.))",
|
||||||
|
"(?i)\\b(sun(day\\b|\\.))" };
|
||||||
|
|
||||||
|
for (String date : days_of_week){
|
||||||
|
Pattern pattern = Pattern.compile(date);
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
if (m.find()) {
|
||||||
|
Calendar dayCal = AstridChronic.parse(m.group(0)).getBeginCalendar();
|
||||||
|
cal = dayCal;
|
||||||
|
//then put it into task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] dates = {
|
||||||
|
"(?i)\\b(jan(\\.|uary))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(feb(\\.|ruary))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(mar(\\.|ch))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(apr(\\.|il))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(may())(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(jun(\\.|e))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(jul(\\.|y))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(aug(\\.|ust))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(sep(\\.|tember))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(oct(\\.|ober))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(nov(\\.|ember))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?",
|
||||||
|
"(?i)\\b(dec(\\.|ember))(\\s(3[0-1]|[0-2]?[0-9])),?( (\\d{4}|\\d{2}))?"};
|
||||||
|
|
||||||
|
// m.group(1) = "month"
|
||||||
|
//m.group(4) = "day"
|
||||||
|
for (String date: dates) {
|
||||||
|
Pattern pattern = Pattern.compile(date);
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
|
||||||
|
if (m.find()){
|
||||||
|
Calendar dateCal = Chronic.parse(m.group(1)).getBeginCalendar();
|
||||||
|
if (m.group(4) != null){
|
||||||
|
dateCal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(4)));
|
||||||
|
}
|
||||||
|
Calendar today = Calendar.getInstance();
|
||||||
|
if (m.group(5) != null){
|
||||||
|
dateCal.set(Calendar.YEAR, Integer.parseInt(m.group(5).trim()));
|
||||||
|
}
|
||||||
|
else if (today.get(Calendar.MONTH) - dateCal.get(Calendar.MONTH) > 1){ //if more than a month in the past
|
||||||
|
dateCal.set(Calendar.YEAR, dateCal.get(Calendar.YEAR)+1);
|
||||||
|
}
|
||||||
|
if (cal == null){
|
||||||
|
cal = dateCal;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
cal.set(Calendar.DAY_OF_MONTH, dateCal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
cal.set(Calendar.MONTH,dateCal.get(Calendar.MONTH) );
|
||||||
|
cal.set(Calendar.YEAR, dateCal.get(Calendar.YEAR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for dates in the format MM/DD
|
||||||
|
Pattern p = Pattern.compile("(?i)\\b(1[0-2]|0?[1-9])(\\/|-)(3[0-1]|[0-2]?[0-9])(\\/|-)?(\\d{4}|\\d{2})?");
|
||||||
|
Matcher match = p.matcher(inputText);
|
||||||
|
if (match.find()){
|
||||||
|
Calendar dCal = Calendar.getInstance();
|
||||||
|
setCalendarToDefaultTime(dCal);
|
||||||
|
dCal.set(Calendar.MONTH, Integer.parseInt(match.group(1).trim())-1);
|
||||||
|
dCal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(match.group(3)));
|
||||||
|
if (match.group(5) != null && !(match.group(5).trim()).equals(""))
|
||||||
|
{
|
||||||
|
String yearString = match.group(5);
|
||||||
|
if(match.group(5).length()==2)
|
||||||
|
yearString = "20" + match.group(5);
|
||||||
|
dCal.set(Calendar.YEAR, Integer.parseInt(yearString));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cal==null){
|
||||||
|
cal = dCal;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
cal.set(Calendar.DAY_OF_MONTH, dCal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
cal.set(Calendar.MONTH,dCal.get(Calendar.MONTH));
|
||||||
|
cal.set(Calendar.YEAR, dCal.get(Calendar.YEAR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<String, Integer> dayTimes = new HashMap<String, Integer>();
|
||||||
|
dayTimes.put("(?i)\\bbreakfast\\b", 8);
|
||||||
|
dayTimes.put("(?i)\\blunch\\b", 12);
|
||||||
|
dayTimes.put("(?i)\\bsupper\\b" ,18);
|
||||||
|
dayTimes.put("(?i)\\bdinner\\b",18);
|
||||||
|
dayTimes.put("(?i)\\bbrunch\\b", 10);
|
||||||
|
dayTimes.put("(?i)\\bmorning\\b", 8);
|
||||||
|
dayTimes.put("(?i)\\bafternoon\\b", 15);
|
||||||
|
dayTimes.put("(?i)\\bevening\\b" , 19);
|
||||||
|
dayTimes.put("(?i)\\bnight\\b" , 19);
|
||||||
|
dayTimes.put("(?i)\\bmidnight\\b" , 0);
|
||||||
|
dayTimes.put("(?i)\\bnoon\\b" , 12);
|
||||||
|
|
||||||
|
for (String dayTime: dayTimes.keySet()){
|
||||||
|
Pattern pattern = Pattern.compile(dayTime);
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
if (m.find()){
|
||||||
|
containsSpecificTime=true;
|
||||||
|
int timeHour = dayTimes.get(dayTime);
|
||||||
|
Calendar dayTimesCal = Calendar.getInstance();
|
||||||
|
setCalendarToDefaultTime(dayTimesCal);
|
||||||
|
dayTimesCal.set(Calendar.HOUR, timeHour);
|
||||||
|
if (cal == null) {
|
||||||
|
cal = dayTimesCal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setCalendarToDefaultTime(cal);
|
||||||
|
cal.set(Calendar.HOUR, timeHour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] times = {
|
||||||
|
//[time] am/pm
|
||||||
|
"(?i)(\\b)([01]?\\d):?([0-5]\\d)? ?([ap]\\.?m?\\.?)\\b",
|
||||||
|
//army time
|
||||||
|
"(?i)\\b(([0-2]?[0-9]):([0-5][0-9]))(\\b)",
|
||||||
|
//[int] o'clock
|
||||||
|
"(?i)\\b(([01]?\\d)() ?o'? ?clock) ?([ap]\\.?m\\.?)?\\b",
|
||||||
|
//at [int]
|
||||||
|
"(?i)(\\bat) ([01]?\\d)()($|\\D($|\\D))"
|
||||||
|
|
||||||
|
//m.group(2) holds the hour
|
||||||
|
//m.group(3) holds the minutes
|
||||||
|
//m.group(4) holds am/pm
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String time:times){
|
||||||
|
Pattern pattern = Pattern.compile(time);
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
if (m.find()){
|
||||||
|
containsSpecificTime = true;
|
||||||
|
Calendar today = Calendar.getInstance();
|
||||||
|
Calendar timeCal = Calendar.getInstance();
|
||||||
|
setCalendarToDefaultTime(timeCal);
|
||||||
|
timeCal.set(Calendar.HOUR, Integer.parseInt(m.group(2)));
|
||||||
|
|
||||||
|
if (m.group(3) != null && !m.group(3).trim().equals(""))
|
||||||
|
timeCal.set(Calendar.MINUTE, Integer.parseInt(m.group(3)));
|
||||||
|
else
|
||||||
|
timeCal.set(Calendar.MINUTE, 0);
|
||||||
|
if (Integer.parseInt(m.group(2)) <= 12)
|
||||||
|
timeCal.set(Calendar.AM_PM, ampm_to_number(m.group(4)));
|
||||||
|
|
||||||
|
//sets it to the next occurrence of that hour if no am/pm is provided. doesn't include military time
|
||||||
|
if ( Integer.parseInt(m.group(2))<= 12 && (m.group(4)==null || (m.group(4).trim()).equals(""))) {
|
||||||
|
while (timeCal.getTime().getTime() < today.getTime().getTime()){
|
||||||
|
timeCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY)+12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //if am/pm is provided and the time is in the past, set it to the next day. Military time included.
|
||||||
|
if (timeCal.get(Calendar.HOUR) !=0 && (timeCal.getTime().getTime() < today.getTime().getTime())) {
|
||||||
|
timeCal.set(Calendar.DAY_OF_MONTH, timeCal.get(Calendar.DAY_OF_MONTH) + 1);
|
||||||
|
}
|
||||||
|
if (timeCal.get(Calendar.HOUR) == 0){
|
||||||
|
timeCal.set(Calendar.HOUR, 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cal == null){
|
||||||
|
cal = timeCal;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
cal.set(Calendar.HOUR, timeCal.get(Calendar.HOUR));
|
||||||
|
cal.set(Calendar.MINUTE,timeCal.get(Calendar.MINUTE) );
|
||||||
|
cal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));
|
||||||
|
cal.set(Calendar.AM_PM, timeCal.get(Calendar.AM_PM));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cal!= null ){ //if at least one of the above has been called, write to task. else do nothing.
|
||||||
|
if (containsSpecificTime) {
|
||||||
|
task.setValue(Task.DUE_DATE, Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, cal.getTime().getTime()));
|
||||||
|
} else {
|
||||||
|
task.setValue(Task.DUE_DATE, Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, cal.getTime().getTime()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------DATE--------------------------
|
||||||
|
|
||||||
|
//Parses through the text and sets the frequency of the task.
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
private static void repeatHelper(Task task) {
|
||||||
|
String inputText = task.getValue(Task.TITLE);
|
||||||
|
HashMap<String, Frequency> repeatTimes = new HashMap<String, Frequency>();
|
||||||
|
repeatTimes.put("(?i)\\bevery ?\\w{0,6} days?\\b" , Frequency.DAILY);
|
||||||
|
repeatTimes.put("(?i)\\bevery ?\\w{0,6} ?nights?\\b" , Frequency.DAILY);
|
||||||
|
repeatTimes.put("(?i)\\bevery ?\\w{0,6} ?mornings?\\b" , Frequency.DAILY);
|
||||||
|
repeatTimes.put("(?i)\\bevery ?\\w{0,6} ?evenings?\\b" , Frequency.DAILY);
|
||||||
|
repeatTimes.put("(?i)\\bevery ?\\w{0,6} ?afternoons?\\b" , Frequency.DAILY);
|
||||||
|
repeatTimes.put("(?i)\\bevery \\w{0,6} ?weeks?\\b", Frequency.WEEKLY);
|
||||||
|
repeatTimes.put("(?i)\\bevery \\w{0,6} ?(mon|tues|wednes|thurs|fri|satur|sun)days?\\b", Frequency.WEEKLY);
|
||||||
|
repeatTimes.put("(?i)\\bevery \\w{0,6} ?months?\\b", Frequency.MONTHLY);
|
||||||
|
repeatTimes.put("(?i)\\bevery \\w{0,6} ?years?\\b", Frequency.YEARLY);
|
||||||
|
|
||||||
|
HashMap<String, Frequency> repeatTimesIntervalOne = new HashMap<String, Frequency>();
|
||||||
|
//pre-determined intervals of 1
|
||||||
|
repeatTimesIntervalOne.put( "(?i)\\bdaily\\b" , Frequency.DAILY);
|
||||||
|
repeatTimesIntervalOne.put( "(?i)\\beveryday\\b" , Frequency.DAILY);
|
||||||
|
repeatTimesIntervalOne.put( "(?i)\\bweekly\\b" , Frequency.WEEKLY);
|
||||||
|
repeatTimesIntervalOne.put( "(?i)\\bmonthly\\b" ,Frequency.MONTHLY);
|
||||||
|
repeatTimesIntervalOne.put( "(?i)\\byearly\\b" , Frequency.YEARLY);
|
||||||
|
|
||||||
|
for (String repeatTime:repeatTimes.keySet()){
|
||||||
|
Pattern pattern = Pattern.compile(repeatTime);
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
if (m.find()){
|
||||||
|
Frequency rtime = repeatTimes.get(repeatTime);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(rtime);
|
||||||
|
rrule.setInterval(findInterval(inputText));
|
||||||
|
task.setValue(Task.RECURRENCE, rrule.toIcal());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String repeatTimeIntervalOne:repeatTimesIntervalOne.keySet()){
|
||||||
|
Pattern pattern = Pattern.compile(repeatTimeIntervalOne);
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
if (m.find()) {
|
||||||
|
Frequency rtime = repeatTimesIntervalOne.get(repeatTimeIntervalOne);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(rtime);
|
||||||
|
rrule.setInterval(1);
|
||||||
|
String thing = rrule.toIcal();
|
||||||
|
task.setValue(Task.RECURRENCE, thing);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//helper method for repeatHelper.
|
||||||
|
private static int findInterval(String inputText) {
|
||||||
|
HashMap<String,Integer> words_to_num = new HashMap<String, Integer>();
|
||||||
|
String[] words = new String[] {
|
||||||
|
"one", "two", "three", "four", "five", "six",
|
||||||
|
"seven", "eight", "nine", "ten", "eleven", "twelve"
|
||||||
|
};
|
||||||
|
for(int i = 0; i < words.length; i++) {
|
||||||
|
words_to_num.put(words[i], i+1);
|
||||||
|
words_to_num.put(Integer.toString(i + 1), i + 1);
|
||||||
|
}
|
||||||
|
words_to_num.put("other" , 2);
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("(?i)\\bevery (\\w*)\\b");
|
||||||
|
int interval = 1;
|
||||||
|
Matcher m = pattern.matcher(inputText);
|
||||||
|
if (m.find() && m.group(1)!=null){
|
||||||
|
String interval_str = m.group(1);
|
||||||
|
if (words_to_num.containsKey(interval_str))
|
||||||
|
interval = words_to_num.get(interval_str);
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
interval = Integer.parseInt(interval_str);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// Ah well
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//helper method for DayHelper. Resets the time on the calendar to 00:00:00 am
|
||||||
|
private static void setCalendarToDefaultTime(Calendar cal){
|
||||||
|
cal.set(Calendar.HOUR, 0);
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
cal.set(Calendar.MINUTE, 0);
|
||||||
|
cal.set(Calendar.SECOND, 0);
|
||||||
|
cal.set(Calendar.AM_PM, Calendar.AM);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,123 @@
|
|||||||
|
package com.todoroo.astrid.welcome.tutorial;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
|
||||||
|
public class ViewPagerAdapter extends PagerAdapter
|
||||||
|
{
|
||||||
|
private static int[] images = new int[]
|
||||||
|
{
|
||||||
|
R.drawable.welcome_walkthrough_1,
|
||||||
|
R.drawable.welcome_walkthrough_2,
|
||||||
|
R.drawable.welcome_walkthrough_3,
|
||||||
|
R.drawable.welcome_walkthrough_4,
|
||||||
|
R.drawable.welcome_walkthrough_5,
|
||||||
|
R.drawable.welcome_walkthrough_6,
|
||||||
|
R.drawable.welcome_screen
|
||||||
|
};
|
||||||
|
private static int[] title = new int[]
|
||||||
|
{
|
||||||
|
R.string.welcome_title_1,
|
||||||
|
R.string.welcome_title_2,
|
||||||
|
R.string.welcome_title_3,
|
||||||
|
R.string.welcome_title_4,
|
||||||
|
R.string.welcome_title_5,
|
||||||
|
R.string.welcome_title_6,
|
||||||
|
R.string.welcome_title_7,
|
||||||
|
};
|
||||||
|
private static int[] body = new int[]
|
||||||
|
{
|
||||||
|
R.string.welcome_body_1,
|
||||||
|
R.string.welcome_body_2,
|
||||||
|
R.string.welcome_body_3,
|
||||||
|
R.string.welcome_body_4,
|
||||||
|
R.string.welcome_body_5,
|
||||||
|
R.string.welcome_body_6,
|
||||||
|
R.string.welcome_body_7,
|
||||||
|
};
|
||||||
|
private static int[] layouts = new int[]
|
||||||
|
{
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_page,
|
||||||
|
R.layout.welcome_walkthrough_login_page,
|
||||||
|
|
||||||
|
};
|
||||||
|
private final Context context;
|
||||||
|
public WelcomeWalkthrough parent;
|
||||||
|
|
||||||
|
public ViewPagerAdapter( Context context )
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount()
|
||||||
|
{
|
||||||
|
return layouts.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object instantiateItem( View pager, int position )
|
||||||
|
{
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
|
||||||
|
View pageView = inflater.inflate(layouts[position], null, true);
|
||||||
|
pageView.setLayoutParams( new ViewGroup.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT));
|
||||||
|
|
||||||
|
if (position != getCount()-1){
|
||||||
|
ImageView imageView = (ImageView) pageView.findViewById(R.id.welcome_walkthrough_image);
|
||||||
|
imageView.setImageResource(images[position]);
|
||||||
|
|
||||||
|
TextView titleView = (TextView) pageView.findViewById(R.id.welcome_walkthrough_title);
|
||||||
|
titleView.setText(title[position]);
|
||||||
|
TextView bodyView = (TextView) pageView.findViewById(R.id.welcome_walkthrough_body);
|
||||||
|
bodyView.setText(body[position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
((ViewPager)pager).addView( pageView, 0 );
|
||||||
|
parent.pageScrolled(position, pageView);
|
||||||
|
return pageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyItem( View pager, int position, Object view )
|
||||||
|
{
|
||||||
|
((ViewPager)pager).removeView( (View)view );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isViewFromObject( View view, Object object )
|
||||||
|
{
|
||||||
|
return view.equals( object );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishUpdate( View view ) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreState( Parcelable p, ClassLoader c ) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Parcelable saveState() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startUpdate( View view ) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
|
||||||
|
package com.todoroo.astrid.welcome.tutorial;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
import com.todoroo.andlib.utility.DialogUtilities;
|
||||||
|
import com.todoroo.astrid.actfm.ActFmLoginActivity;
|
||||||
|
import com.todoroo.astrid.activity.Eula;
|
||||||
|
import com.todoroo.astrid.welcome.WelcomeLogin;
|
||||||
|
import com.viewpagerindicator.CirclePageIndicator;
|
||||||
|
import com.viewpagerindicator.PageIndicator;
|
||||||
|
|
||||||
|
public class WelcomeWalkthrough extends ActFmLoginActivity {
|
||||||
|
ViewPager mPager;
|
||||||
|
ViewPagerAdapter mAdapter;
|
||||||
|
PageIndicator mIndicator;
|
||||||
|
View currentView;
|
||||||
|
int currentPage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
//setContentView(R.layout.welcome_walkthrough);
|
||||||
|
|
||||||
|
mAdapter = new ViewPagerAdapter(this);
|
||||||
|
mAdapter.parent = this;
|
||||||
|
|
||||||
|
mPager = (ViewPager)findViewById(R.id.pager);
|
||||||
|
mPager.setAdapter(mAdapter);
|
||||||
|
|
||||||
|
mIndicator = (CirclePageIndicator)findViewById(R.id.indicator);
|
||||||
|
mIndicator.setViewPager(mPager);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected int getContentViewResource() {
|
||||||
|
return R.layout.welcome_walkthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getTitleResource() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
public void pageScrolled(int position, View view){
|
||||||
|
Log.d(null, "Updated ui");
|
||||||
|
currentView = view;
|
||||||
|
currentPage = position;
|
||||||
|
if (position == mAdapter.getCount()-1) {
|
||||||
|
initializeUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initializeUI() {
|
||||||
|
if(mAdapter == null)
|
||||||
|
return;
|
||||||
|
if(currentPage == mAdapter.getCount()-1){
|
||||||
|
super.initializeUI();
|
||||||
|
setupTermsOfService();
|
||||||
|
setupLoginLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SpannableString getLinkStringWithCustomInterval(String base, String linkComponent,
|
||||||
|
int start, int endOffset, final OnClickListener listener) {
|
||||||
|
SpannableString link = new SpannableString (String.format("%s %s", //$NON-NLS-1$
|
||||||
|
base, linkComponent));
|
||||||
|
ClickableSpan linkSpan = new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View widget) {
|
||||||
|
listener.onClick(widget);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint ds) {
|
||||||
|
ds.setUnderlineText(true);
|
||||||
|
ds.setColor(Color.rgb(255, 255, 255));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
link.setSpan(linkSpan, start, link.length() + endOffset, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
protected void setupTermsOfService() {
|
||||||
|
TextView tos = (TextView)currentView.findViewById(R.id.tos);
|
||||||
|
tos.setOnClickListener(showTosListener);
|
||||||
|
|
||||||
|
String tosBase = getString(R.string.welcome_login_tos_base);
|
||||||
|
String tosLink = getString(R.string.welcome_login_tos_link);
|
||||||
|
SpannableString link = getLinkStringWithCustomInterval(tosBase, tosLink, tosBase.length() + 2, -1, showTosListener);
|
||||||
|
tos.setText(link);
|
||||||
|
}
|
||||||
|
protected void setupPWLogin() {
|
||||||
|
Button pwLogin = (Button) findViewById(R.id.pw_login);
|
||||||
|
pwLogin.setOnClickListener(signUpListener);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
protected void setupWalkthroughLogin() {
|
||||||
|
Button loginButton = (Button)currentView.findViewById(R.id.walkthrough_login);
|
||||||
|
loginButton.setOnClickListener(showWalkthroughLoginListener);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
protected void setupLoginLater() {
|
||||||
|
TextView loginLater = (TextView)currentView.findViewById(R.id.login_later);
|
||||||
|
loginLater.setOnClickListener(loginLaterListener);
|
||||||
|
String loginLaterBase = getString(R.string.welcome_login_later);
|
||||||
|
SpannableString loginLaterLink = new SpannableString(String.format("%s", loginLaterBase)); //$NON-NLS-1$
|
||||||
|
ClickableSpan laterSpan = new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View widget) {
|
||||||
|
loginLaterListener.onClick(widget);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint ds) {
|
||||||
|
ds.setUnderlineText(true);
|
||||||
|
ds.setColor(Color.rgb(255, 255, 255));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loginLaterLink.setSpan(laterSpan, 0, loginLaterBase.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
loginLater.setText(loginLaterLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final OnClickListener showTosListener = new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Eula.showEulaBasic(WelcomeWalkthrough.this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private void showWelcomeLoginActivty() {
|
||||||
|
Intent showWelcomeLogin = new Intent(this, WelcomeLogin.class);
|
||||||
|
showWelcomeLogin.putExtra(ActFmLoginActivity.SHOW_TOAST, false);
|
||||||
|
startActivity(showWelcomeLogin);
|
||||||
|
}
|
||||||
|
protected final OnClickListener showWalkthroughLoginListener = new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showWelcomeLoginActivty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected final OnClickListener loginLaterListener = new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View arg0) {
|
||||||
|
String title = getString(R.string.welcome_login_confirm_later_title);
|
||||||
|
String confirmLater = getString(R.string.welcome_login_confirm_later_dialog);
|
||||||
|
DialogUtilities.okCancelCustomDialog(WelcomeWalkthrough.this, title, confirmLater,
|
||||||
|
R.string.welcome_login_confirm_later_ok,
|
||||||
|
R.string.welcome_login_confirm_later_cancel,
|
||||||
|
android.R.drawable.ic_dialog_alert,
|
||||||
|
null, confirmLaterListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DialogInterface.OnClickListener confirmLaterListener = new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,509 @@
|
|||||||
|
package com.todoroo.andlib.utility;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.google.ical.values.Frequency;
|
||||||
|
import com.google.ical.values.RRule;
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
import com.todoroo.astrid.data.Task;
|
||||||
|
import com.todoroo.astrid.service.TaskService;
|
||||||
|
import com.todoroo.astrid.test.DatabaseTestCase;
|
||||||
|
|
||||||
|
public class TitleParserTest extends DatabaseTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
Preferences.setStringFromInteger(R.string.p_default_urgency_key, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** test that completing a task w/ no regular expressions creates a simple task with no date, no repeat, no lists*/
|
||||||
|
public void testNoRegexes() throws Exception{
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), nothing.getValue(Task.RECURRENCE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tests correct date is parsed **/
|
||||||
|
public void testMonthDate() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String[] titleMonthStrings = {
|
||||||
|
"Jan.", "January",
|
||||||
|
"Feb.", "February",
|
||||||
|
"Mar.", "March",
|
||||||
|
"Apr.", "April",
|
||||||
|
"May", "May",
|
||||||
|
"Jun.", "June",
|
||||||
|
"Jul.", "July",
|
||||||
|
"Aug.", "August",
|
||||||
|
"Sep.", "September",
|
||||||
|
"Oct.", "October",
|
||||||
|
"Nov.", "November",
|
||||||
|
"Dec.", "December"
|
||||||
|
};
|
||||||
|
for (int i = 0; i < 23; i++) {
|
||||||
|
String testTitle = "Jog on " + titleMonthStrings[i] + " 12.";
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMonth(), i/2);
|
||||||
|
assertEquals(date.getDate(), 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMonthSlashDay() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
for (int i = 1; i < 13; i++) {
|
||||||
|
String testTitle = "Jog on " + i + "/12/13";
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMonth(), i-1);
|
||||||
|
assertEquals(date.getDate(), 12);
|
||||||
|
assertEquals(date.getYear(), 113);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testArmyTime() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String testTitle = "Jog on 23:21.";
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMinutes(), 21);
|
||||||
|
assertEquals(date.getHours(), 23);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_AM_PM() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String testTitle = "Jog at 8:33 PM.";
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMinutes(), 33);
|
||||||
|
assertEquals(date.getHours(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_at_hour() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String testTitle = "Jog at 8 PM.";
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMinutes(), 0);
|
||||||
|
assertEquals(date.getHours(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_oclock_AM() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String testTitle = "Jog at 8 o'clock AM.";
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMinutes(), 0);
|
||||||
|
assertEquals(date.getHours(), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_several_forms_of_eight() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String[] testTitles = {
|
||||||
|
"Jog 8 AM",
|
||||||
|
"Jog 8 o'clock AM",
|
||||||
|
"at 8:00 AM"
|
||||||
|
};
|
||||||
|
for (String testTitle: testTitles) {
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMinutes(), 0);
|
||||||
|
assertEquals(date.getHours(), 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_several_forms_of_1230PM() {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
Task nothing = new Task();
|
||||||
|
String[] testTitles = {
|
||||||
|
"Jog 12:30 PM",
|
||||||
|
"at 12:30 PM",
|
||||||
|
"Do something on 12:30 PM",
|
||||||
|
"Jog at 12:30 PM Friday"
|
||||||
|
|
||||||
|
};
|
||||||
|
for (String testTitle: testTitles) {
|
||||||
|
insertTitleAddTask(testTitle, task, taskService);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getMinutes(), 30);
|
||||||
|
assertEquals(date.getHours(), 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertTitleAddTask(String title, Task task, TaskService taskService) {
|
||||||
|
task.setValue(Task.TITLE, title);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------Days begin----------------//
|
||||||
|
public void testDays() throws Exception{
|
||||||
|
Calendar today = Calendar.getInstance();
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, "Jog today");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
Date date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getDay()+1, today.get(Calendar.DAY_OF_WEEK));
|
||||||
|
//Calendar starts 1-6, date.getDay() starts at 0
|
||||||
|
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog tomorrow");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getDay()+1, today.get(Calendar.DAY_OF_WEEK)+1);
|
||||||
|
|
||||||
|
String[] days = {
|
||||||
|
"sunday",
|
||||||
|
"monday",
|
||||||
|
"tuesday",
|
||||||
|
"wednesday",
|
||||||
|
"thursday",
|
||||||
|
"friday",
|
||||||
|
"saturday",
|
||||||
|
};
|
||||||
|
String[] abrevDays = {
|
||||||
|
"sun.",
|
||||||
|
"mon.",
|
||||||
|
"tue.",
|
||||||
|
"wed.",
|
||||||
|
"thu.",
|
||||||
|
"fri.",
|
||||||
|
"sat."
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 1; i <= 6; i++){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog "+ days[i]);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getDay(), i);
|
||||||
|
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog "+ abrevDays[i]);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
assertEquals(date.getDay(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------Days end----------------//
|
||||||
|
|
||||||
|
|
||||||
|
//----------------Priority begin----------------//
|
||||||
|
/** tests all words using priority 0 */
|
||||||
|
public void testPriority0() throws Exception {
|
||||||
|
String[] acceptedStrings = {
|
||||||
|
"priority 0",
|
||||||
|
"least priority",
|
||||||
|
"lowest priority",
|
||||||
|
"bang 0"
|
||||||
|
};
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
for (String acceptedString:acceptedStrings){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedString); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_LEAST);
|
||||||
|
}
|
||||||
|
for (String acceptedString:acceptedStrings){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, acceptedString + " jog"); //test at beginning of task. should not set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertNotSame((int)task.getValue(Task.IMPORTANCE),(int)Task.IMPORTANCE_LEAST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPriority1() throws Exception {
|
||||||
|
String[] acceptedStringsAtEnd = {
|
||||||
|
"priority 1",
|
||||||
|
"low priority",
|
||||||
|
"bang",
|
||||||
|
"bang 1"
|
||||||
|
};
|
||||||
|
String[] acceptedStringsAnywhere = {
|
||||||
|
"!1",
|
||||||
|
"!"
|
||||||
|
};
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
for (String acceptedStringAtEnd:acceptedStringsAtEnd){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedStringAtEnd); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_SHOULD_DO);
|
||||||
|
}
|
||||||
|
for (String acceptedStringAtEnd:acceptedStringsAtEnd){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, acceptedStringAtEnd + " jog"); //test at beginning of task. should not set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_SHOULD_DO);
|
||||||
|
}
|
||||||
|
for (String acceptedStringAnywhere:acceptedStringsAnywhere){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedStringAnywhere); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_SHOULD_DO);
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, acceptedStringAnywhere + " jog"); //test at beginning of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_SHOULD_DO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPriority2() throws Exception {
|
||||||
|
String[] acceptedStringsAtEnd = {
|
||||||
|
"priority 2",
|
||||||
|
"high priority",
|
||||||
|
"bang bang",
|
||||||
|
"bang 2"
|
||||||
|
};
|
||||||
|
String[] acceptedStringsAnywhere = {
|
||||||
|
"!2",
|
||||||
|
"!!"
|
||||||
|
};
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
for (String acceptedStringAtEnd:acceptedStringsAtEnd){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedStringAtEnd); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_MUST_DO);
|
||||||
|
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, acceptedStringAtEnd + " jog"); //test at beginning of task. should not set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertNotSame((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_MUST_DO);
|
||||||
|
}
|
||||||
|
for (String acceptedStringAnywhere:acceptedStringsAnywhere){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedStringAnywhere); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_MUST_DO);
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, acceptedStringAnywhere + " jog"); //test at beginning of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_MUST_DO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPriority3() throws Exception {
|
||||||
|
String[] acceptedStringsAtEnd = {
|
||||||
|
"priority 3",
|
||||||
|
"highest priority",
|
||||||
|
"bang bang bang",
|
||||||
|
"bang 3",
|
||||||
|
"bang bang bang bang bang bang bang"
|
||||||
|
};
|
||||||
|
String[] acceptedStringsAnywhere = {
|
||||||
|
"!3",
|
||||||
|
"!!!",
|
||||||
|
"!6",
|
||||||
|
"!!!!!!!!!!!!!"
|
||||||
|
};
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
for (String acceptedStringAtEnd:acceptedStringsAtEnd){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedStringAtEnd); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_DO_OR_DIE);
|
||||||
|
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, acceptedStringAtEnd + " jog"); //test at beginning of task. should not set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertNotSame((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_DO_OR_DIE);
|
||||||
|
}
|
||||||
|
for (String acceptedStringAnywhere:acceptedStringsAnywhere){
|
||||||
|
task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog " + acceptedStringAnywhere); //test at end of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_DO_OR_DIE);
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, acceptedStringAnywhere + " jog"); //test at beginning of task. should set importance.
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals((int)task.getValue(Task.IMPORTANCE), (int)Task.IMPORTANCE_DO_OR_DIE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------Priority end----------------//
|
||||||
|
|
||||||
|
|
||||||
|
//----------------Repeats begin----------------//
|
||||||
|
/** test daily repeat from due date, but with no due date set */
|
||||||
|
public void testDailyWithNoDueDate() throws Exception {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog daily");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(Frequency.DAILY);
|
||||||
|
rrule.setInterval(1);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, "Jog every day");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
|
||||||
|
for (int i = 1; i <= 12; i++){
|
||||||
|
task.setValue(Task.TITLE, "Jog every " + i + " days.");
|
||||||
|
rrule.setInterval(i);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
task = new Task();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** test weekly repeat from due date, with no due date & time set */
|
||||||
|
public void testWeeklyWithNoDueDate() throws Exception {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog weekly");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(Frequency.WEEKLY);
|
||||||
|
rrule.setInterval(1);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, "Jog every week");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
|
||||||
|
for (int i = 1; i <= 12; i++){
|
||||||
|
task.setValue(Task.TITLE, "Jog every " + i + " weeks");
|
||||||
|
rrule.setInterval(i);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
task = new Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** test hourly repeat from due date, with no due date but no time */
|
||||||
|
public void testMonthlyFromNoDueDate() throws Exception {
|
||||||
|
TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog monthly");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(Frequency.MONTHLY);
|
||||||
|
rrule.setInterval(1);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, "Jog every month");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
|
||||||
|
for (int i = 1; i <= 12; i++){
|
||||||
|
task.setValue(Task.TITLE, "Jog every " + i + " months");
|
||||||
|
rrule.setInterval(i);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertFalse(task.hasDueTime());
|
||||||
|
assertFalse(task.hasDueDate());
|
||||||
|
task = new Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDailyFromDueDate() throws Exception { TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog daily starting from today");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(Frequency.DAILY);
|
||||||
|
rrule.setInterval(1);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertTrue(task.hasDueDate());
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, "Jog every day starting from today");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertTrue(task.hasDueDate());
|
||||||
|
|
||||||
|
for (int i = 1; i <= 12; i++){
|
||||||
|
task.setValue(Task.TITLE, "Jog every " + i + " days starting from today");
|
||||||
|
rrule.setInterval(i);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertTrue(task.hasDueDate());
|
||||||
|
task = new Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWeeklyFromDueDate() throws Exception { TaskService taskService = new TaskService();
|
||||||
|
Task task = new Task();
|
||||||
|
task.setValue(Task.TITLE, "Jog weekly starting from today");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
RRule rrule = new RRule();
|
||||||
|
rrule.setFreq(Frequency.WEEKLY);
|
||||||
|
rrule.setInterval(1);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertTrue(task.hasDueDate());
|
||||||
|
|
||||||
|
task.setValue(Task.TITLE, "Jog every week starting from today");
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertTrue(task.hasDueDate());
|
||||||
|
|
||||||
|
for (int i = 1; i <= 12; i++){
|
||||||
|
task.setValue(Task.TITLE, "Jog every " + i + " weeks starting from today");
|
||||||
|
rrule.setInterval(i);
|
||||||
|
taskService.quickAdd(task);
|
||||||
|
assertEquals(task.getValue(Task.RECURRENCE), rrule.toIcal());
|
||||||
|
assertTrue(task.hasDueDate());
|
||||||
|
task = new Task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------Repeats end----------------//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
#Android generated
|
||||||
|
bin
|
||||||
|
gen
|
||||||
|
|
||||||
|
#IntelliJ IDEA
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
#Maven
|
||||||
|
target
|
||||||
|
release.properties
|
||||||
|
pom.xml.*
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
Change Log
|
||||||
|
==========
|
||||||
|
|
||||||
|
Version 2.2.2 *(2011-12-31)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fix incorrect `R.java` imports in all of the sample activities.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.2.1 *(2011-12-31)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* New `setTypeface(Typeface)` and `getTypeface()` methods for title indicator.
|
||||||
|
(Thanks Dimitri Fedorov)
|
||||||
|
* Added styled tab indicator sample.
|
||||||
|
* Support for widths other than those that could be measured exactly.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.2.0 *(2011-12-13)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Default title indicator style is now 'underline'.
|
||||||
|
* Title indicator now allows specifying an `OnCenterItemClickListener` which
|
||||||
|
will give you callbacks when the current item title has been clicked.
|
||||||
|
(Thanks Chris Banes)
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.1.0 *(2011-11-30)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Indicators now have a `notifyDataSetChanged` method which should be called
|
||||||
|
when changes are made to the adapter.
|
||||||
|
* Fix: Avoid `NullPointerException`s when the `ViewPager` is not immediately
|
||||||
|
bound to the indicator.
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.0.0 *(2011-11-20)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* New `TabPageIndicator`! Uses the Ice Cream Sandwich-style action bar tabs
|
||||||
|
which fill the width of the view when there are only a few tabs or provide
|
||||||
|
horizontal animated scrolling when there are many.
|
||||||
|
* Update to link against ACLv4r4. This will now be required in all implementing
|
||||||
|
applications.
|
||||||
|
* Allow dragging the title and circle indicators to drag the pager.
|
||||||
|
* Remove orientation example as the DirectionalViewPager library has not been
|
||||||
|
updated to ACLv4r4.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.2.1 *(2011-10-20)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Maven 3 is now required when building from the command line.
|
||||||
|
|
||||||
|
* Update to support ADT 14.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.2.0 *(2011-10-04)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Move to `com.viewpagerindicator` package.
|
||||||
|
* Move maven group and artifact to `com.viewpagerindicator:library`.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.1.0 *(2011-10-02)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Package changed from `com.jakewharton.android.viewpagerindicator` to
|
||||||
|
`com.jakewharton.android.view`.
|
||||||
|
* Add vertical orientation support to the circle indicator.
|
||||||
|
* Fix: Corrected drawing bug where a single frame would be drawn as if the
|
||||||
|
pager had completed its scroll when in fact it was still scrolling.
|
||||||
|
(Thanks SimonVT!)
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.0.1 *(2011-09-15)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fade selected title color to normal text color during the swipe to and from
|
||||||
|
the center position.
|
||||||
|
* Fix: Ensure both the indicator and footer line are updated when changing the
|
||||||
|
footer color via the `setFooterColor` method.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.0.0 *(2011-08-07)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Initial release.
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
Android ViewPagerIndicator
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Port of [Patrik Åkerfeldt][1]'s paging indicators that are compatible with the
|
||||||
|
ViewPager from the [Android Compatibility Library][2] and
|
||||||
|
[ActionBarSherlock][3].
|
||||||
|
|
||||||
|
Try out the sample application [on the Android Market][10].
|
||||||
|
|
||||||
|
![ViewPagerIndicator Sample Screenshots][9]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
*For a working implementation of this project see the `sample/` folder.*
|
||||||
|
|
||||||
|
1. Include one of the widgets in your view. This should usually be placed
|
||||||
|
adjacent to the `ViewPager` it represents.
|
||||||
|
|
||||||
|
<com.viewpagerindicator.TitlePageIndicator
|
||||||
|
android:id="@+id/titles"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent" />
|
||||||
|
|
||||||
|
2. In your `onCreate` method (or `onCreateView` for a fragment), bind the
|
||||||
|
indicator to the `ViewPager`.
|
||||||
|
|
||||||
|
//Set the pager with an adapter
|
||||||
|
ViewPager pager = (ViewPager)findViewById(R.id.pager);
|
||||||
|
pager.setAdapter(new TestAdapter(getSupportFragmentManager()));
|
||||||
|
|
||||||
|
//Bind the title indicator to the adapter
|
||||||
|
TitlePageIndicator titleIndicator = (TitlePageIndicator)findViewById(R.id.titles);
|
||||||
|
titleIndicator.setViewPager(pager);
|
||||||
|
|
||||||
|
*Note*: If you are using `TitlePageIndicator` your adapter must implement
|
||||||
|
`TitleProvider`.
|
||||||
|
|
||||||
|
3. *(Optional)* If you use an `OnPageChangeListener` with your view pager
|
||||||
|
you should set it in the indicator rather than on the pager directly.
|
||||||
|
|
||||||
|
//continued from above
|
||||||
|
titleIndicator.setOnPageChangeListener(mPageChangeListener);
|
||||||
|
|
||||||
|
|
||||||
|
Theming
|
||||||
|
-------
|
||||||
|
|
||||||
|
There are three ways to style the look of the indicators.
|
||||||
|
|
||||||
|
1. **Theme XML**. An attribute for each type of indicator is provided in which
|
||||||
|
you can specify a custom style.
|
||||||
|
2. **Layout XML**. Through the use of a custom namespace you can include any
|
||||||
|
desired styles.
|
||||||
|
3. **Object methods**. Both styles have getters and setters for each style
|
||||||
|
attribute which can be changed at any point.
|
||||||
|
|
||||||
|
Each indicator has a demo which creates the same look using each of these
|
||||||
|
methods.
|
||||||
|
|
||||||
|
|
||||||
|
Including In Your Project
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Android-ViewPagerIndicator is presented as an [Android library project][7]. A
|
||||||
|
standalone JAR is not possible due to the theming capabilities offered by the
|
||||||
|
indicator widgets.
|
||||||
|
|
||||||
|
You can include this project by [referencing it as a library project][8] in
|
||||||
|
Eclipse or ant.
|
||||||
|
|
||||||
|
If you are a Maven user you can easily include the library by specifying it as
|
||||||
|
a dependency:
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>library</artifactId>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
<type>apklib</type>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
You must also include the following repository:
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>com.jakewharton</id>
|
||||||
|
<url>http://r.jakewharton.com/maven/release</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This project depends on the `ViewPager` class which is available in the
|
||||||
|
[Android Compatibility Library][2] or [ActionBarSherlock][3]. Details for
|
||||||
|
including one of those libraries is available on their respecitve web sites.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Developed By
|
||||||
|
============
|
||||||
|
|
||||||
|
* Jake Wharton - <jakewharton@gmail.com>
|
||||||
|
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
* [Patrik Åkerfeldt][1] - Author of [ViewFlow][4], a precursor to the ViewPager,
|
||||||
|
which supports paged views and is the original source of both the title
|
||||||
|
and circle indicators.
|
||||||
|
* [Francisco Figueiredo Jr.][5] - Idea and [first implementation][6] for
|
||||||
|
fragment support via ViewPager.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
Copyright 2011 Patrik Åkerfeldt
|
||||||
|
Copyright 2011 Francisco Figueiredo Jr.
|
||||||
|
Copyright 2011 Jake Wharton
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[1]: https://github.com/pakerfeldt
|
||||||
|
[2]: http://developer.android.com/sdk/compatibility-library.html
|
||||||
|
[3]: http://actionbarsherlock.com
|
||||||
|
[4]: https://github.com/pakerfeldt/android-viewflow
|
||||||
|
[5]: https://github.com/franciscojunior
|
||||||
|
[6]: https://gist.github.com/1122947
|
||||||
|
[7]: http://developer.android.com/guide/developing/projects/projects-eclipse.html
|
||||||
|
[8]: http://developer.android.com/guide/developing/projects/projects-eclipse.html#ReferencingLibraryProject
|
||||||
|
[9]: https://raw.github.com/JakeWharton/Android-ViewPagerIndicator/master/sample/screens.png
|
||||||
|
[10]: https://market.android.com/details?id=com.viewpagerindicator.sample
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="gen"/>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
|
<classpathentry kind="lib" path="eclibs/android-support-v4.jar"/>
|
||||||
|
<classpathentry kind="output" path="bin/classes"/>
|
||||||
|
</classpath>
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>viewPagerIndicator</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.viewpagerindicator"
|
||||||
|
android:versionCode="26"
|
||||||
|
android:versionName="2.2.2">
|
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="4" />
|
||||||
|
</manifest>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
# specify alternate libs folder because of conflicting jar
|
||||||
|
jar.libs.dir=eclibs
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="library" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||||
|
It contains the path to the SDK. It should *NOT* be checked into
|
||||||
|
Version Control Systems. -->
|
||||||
|
<property file="local.properties" />
|
||||||
|
|
||||||
|
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||||
|
'android' tool to add properties to it.
|
||||||
|
This is the place to change some Ant specific build properties.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
source.dir
|
||||||
|
The name of the source directory. Default is 'src'.
|
||||||
|
out.dir
|
||||||
|
The name of the output directory. Default is 'bin'.
|
||||||
|
|
||||||
|
For other overridable properties, look at the beginning of the rules
|
||||||
|
files in the SDK, at tools/ant/build.xml
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should
|
||||||
|
be updated using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="ant.properties" />
|
||||||
|
|
||||||
|
<!-- The project.properties file is created and updated by the 'android'
|
||||||
|
tool, as well as ADT.
|
||||||
|
|
||||||
|
This contains project specific properties such as project target, and library
|
||||||
|
dependencies. Lower level build properties are stored in ant.properties
|
||||||
|
(or in .classpath for Eclipse projects).
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems. -->
|
||||||
|
<loadproperties srcFile="project.properties" />
|
||||||
|
|
||||||
|
<!-- quick check on sdk.dir -->
|
||||||
|
<fail
|
||||||
|
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||||
|
unless="sdk.dir"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||||
|
in between standard targets -->
|
||||||
|
<!--
|
||||||
|
<target name="-pre-build">
|
||||||
|
</target>
|
||||||
|
<target name="-pre-compile">
|
||||||
|
</target>
|
||||||
|
|
||||||
|
/* This is typically used for code obfuscation.
|
||||||
|
Compiled code location: ${out.classes.absolute.dir}
|
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||||
|
<target name="-post-compile">
|
||||||
|
</target>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Import the actual build file.
|
||||||
|
|
||||||
|
To customize existing targets, there are two options:
|
||||||
|
- Customize only one target:
|
||||||
|
- copy/paste the target into this file, *before* the
|
||||||
|
<import> task.
|
||||||
|
- customize it to your needs.
|
||||||
|
- Customize the whole content of build.xml
|
||||||
|
- copy/paste the content of the rules files (minus the top node)
|
||||||
|
into this file, replacing the <import> task.
|
||||||
|
- customize to your needs.
|
||||||
|
|
||||||
|
***********************
|
||||||
|
****** IMPORTANT ******
|
||||||
|
***********************
|
||||||
|
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||||
|
in order to avoid having your file be overridden by tools such as "android update project"
|
||||||
|
-->
|
||||||
|
<!-- version-tag: 1 -->
|
||||||
|
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Check Configuration 1.2//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
|
||||||
|
|
||||||
|
<module name="Checker">
|
||||||
|
<!--module name="NewlineAtEndOfFile"/-->
|
||||||
|
<module name="FileLength"/>
|
||||||
|
<module name="FileTabCharacter"/>
|
||||||
|
|
||||||
|
<!-- Trailing spaces -->
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="\s+$"/>
|
||||||
|
<property name="message" value="Line has trailing spaces."/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="TreeWalker">
|
||||||
|
<property name="cacheFile" value="${checkstyle.cache.file}"/>
|
||||||
|
|
||||||
|
<!-- Checks for Javadoc comments. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
|
||||||
|
<!--module name="JavadocMethod"/-->
|
||||||
|
<!--module name="JavadocType"/-->
|
||||||
|
<!--module name="JavadocVariable"/-->
|
||||||
|
<!--module name="JavadocStyle"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for Naming Conventions. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_naming.html -->
|
||||||
|
<module name="ConstantName"/>
|
||||||
|
<module name="LocalFinalVariableName"/>
|
||||||
|
<module name="LocalVariableName"/>
|
||||||
|
<module name="MemberName"/>
|
||||||
|
<module name="MethodName"/>
|
||||||
|
<module name="PackageName"/>
|
||||||
|
<module name="ParameterName"/>
|
||||||
|
<module name="StaticVariableName"/>
|
||||||
|
<module name="TypeName"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for imports -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_import.html -->
|
||||||
|
<module name="AvoidStarImport"/>
|
||||||
|
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
|
||||||
|
<module name="RedundantImport"/>
|
||||||
|
<module name="UnusedImports"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for Size Violations. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_sizes.html -->
|
||||||
|
<!--module name="LineLength"/-->
|
||||||
|
<!--module name="MethodLength"/-->
|
||||||
|
<!--module name="ParameterNumber"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for whitespace -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||||
|
<!--module name="EmptyForIteratorPad"/-->
|
||||||
|
<!--module name="MethodParamPad"/-->
|
||||||
|
<!--module name="NoWhitespaceAfter"/-->
|
||||||
|
<!--module name="NoWhitespaceBefore"/-->
|
||||||
|
<!--module name="OperatorWrap"/-->
|
||||||
|
<!--module name="ParenPad"/-->
|
||||||
|
<!--module name="TypecastParenPad"/-->
|
||||||
|
<!--module name="WhitespaceAfter"/-->
|
||||||
|
<!--module name="WhitespaceAround"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Modifier Checks -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_modifiers.html -->
|
||||||
|
<!--module name="ModifierOrder"/-->
|
||||||
|
<!--module name="RedundantModifier"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for blocks. You know, those {}'s -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_blocks.html -->
|
||||||
|
<!--module name="AvoidNestedBlocks"/-->
|
||||||
|
<!--module name="EmptyBlock"/-->
|
||||||
|
<!--module name="LeftCurly"/-->
|
||||||
|
<!--module name="NeedBraces"/-->
|
||||||
|
<!--module name="RightCurly"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Checks for common coding problems -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_coding.html -->
|
||||||
|
<!--module name="AvoidInlineConditionals"/-->
|
||||||
|
<!--module name="DoubleCheckedLocking"/--> <!-- MY FAVOURITE -->
|
||||||
|
<!--module name="EmptyStatement"/-->
|
||||||
|
<!--module name="EqualsHashCode"/-->
|
||||||
|
<!--module name="HiddenField"/-->
|
||||||
|
<!--module name="IllegalInstantiation"/-->
|
||||||
|
<!--module name="InnerAssignment"/-->
|
||||||
|
<!--module name="MagicNumber"/-->
|
||||||
|
<!--module name="MissingSwitchDefault"/-->
|
||||||
|
<!--module name="RedundantThrows"/-->
|
||||||
|
<!--module name="SimplifyBooleanExpression"/-->
|
||||||
|
<!--module name="SimplifyBooleanReturn"/-->
|
||||||
|
|
||||||
|
<!-- Checks for class design -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_design.html -->
|
||||||
|
<!--module name="DesignForExtension"/-->
|
||||||
|
<!--module name="FinalClass"/-->
|
||||||
|
<!--module name="HideUtilityClassConstructor"/-->
|
||||||
|
<!--module name="InterfaceIsType"/-->
|
||||||
|
<!--module name="VisibilityModifier"/-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Miscellaneous other checks. -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_misc.html -->
|
||||||
|
<!--module name="ArrayTypeStyle"/-->
|
||||||
|
<!--module name="FinalParameters"/-->
|
||||||
|
<!--module name="TodoComment"/-->
|
||||||
|
<!--module name="UpperEll"/-->
|
||||||
|
</module>
|
||||||
|
</module>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>library</artifactId>
|
||||||
|
<name>Android-ViewPagerIndicator</name>
|
||||||
|
<packaging>apklib</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.viewpagerindicator</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>android</groupId>
|
||||||
|
<artifactId>android</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>android.support</groupId>
|
||||||
|
<artifactId>compatibility-v4</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
|
<artifactId>maven-android-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<configLocation>${project.basedir}/checkstyle.xml</configLocation>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>checkstyle</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
-optimizationpasses 5
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
-dontpreverify
|
||||||
|
-verbose
|
||||||
|
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
|
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class com.android.vending.licensing.ILicensingService
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system use,
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
|
||||||
|
android.library=true
|
||||||
|
# Project target.
|
||||||
|
target=android-14
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="false" android:color="@color/vpi__bright_foreground_disabled_holo_dark"/>
|
||||||
|
<item android:state_window_focused="false" android:color="@color/vpi__bright_foreground_holo_dark"/>
|
||||||
|
<item android:state_pressed="true" android:color="@color/vpi__bright_foreground_holo_dark"/>
|
||||||
|
<item android:state_selected="true" android:color="@color/vpi__bright_foreground_holo_dark"/>
|
||||||
|
<!--item android:state_activated="true" android:color="@color/vpi__bright_foreground_holo_dark"/-->
|
||||||
|
<item android:color="@color/vpi__bright_foreground_holo_dark"/> <!-- not selected -->
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="false" android:color="@color/vpi__bright_foreground_disabled_holo_light"/>
|
||||||
|
<item android:state_window_focused="false" android:color="@color/vpi__bright_foreground_holo_light"/>
|
||||||
|
<item android:state_pressed="true" android:color="@color/vpi__bright_foreground_holo_light"/>
|
||||||
|
<item android:state_selected="true" android:color="@color/vpi__bright_foreground_holo_light"/>
|
||||||
|
<!--item android:state_activated="true" android:color="@color/vpi__bright_foreground_holo_light"/-->
|
||||||
|
<item android:color="@color/vpi__bright_foreground_holo_light"/> <!-- not selected -->
|
||||||
|
|
||||||
|
</selector>
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 146 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 150 B |
|
After Width: | Height: | Size: 150 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 155 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 166 B |
|
After Width: | Height: | Size: 149 B |
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- Non focused states -->
|
||||||
|
<item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_holo" />
|
||||||
|
<item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_holo" />
|
||||||
|
|
||||||
|
<!-- Focused states -->
|
||||||
|
<item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_focused_holo" />
|
||||||
|
<item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_focused_holo" />
|
||||||
|
|
||||||
|
<!-- Pressed -->
|
||||||
|
<!-- Non focused states -->
|
||||||
|
<item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
|
||||||
|
<item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
|
||||||
|
|
||||||
|
<!-- Focused states -->
|
||||||
|
<item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
|
||||||
|
<item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
|
||||||
|
</selector>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<view
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
class="com.viewpagerindicator.TabPageIndicator$TabView"
|
||||||
|
style="?attr/vpiTabPageIndicatorStyle">
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
style="?attr/vpiTabTextStyle" />
|
||||||
|
</view>
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 Patrik Åkerfeldt
|
||||||
|
Copyright (C) 2011 Jake Wharton
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="ViewPagerIndicator">
|
||||||
|
<!-- Style of the circle indicator. -->
|
||||||
|
<attr name="vpiCirclePageIndicatorStyle" format="reference"/>
|
||||||
|
|
||||||
|
<!-- Style of the title indicator. -->
|
||||||
|
<attr name="vpiTitlePageIndicatorStyle" format="reference"/>
|
||||||
|
|
||||||
|
<!-- Style of the tab indicator. -->
|
||||||
|
<attr name="vpiTabPageIndicatorStyle" format="reference"/>
|
||||||
|
<!-- Style of the text in a tab. -->
|
||||||
|
<attr name="vpiTabTextStyle" format="reference"/>
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="CirclePageIndicator">
|
||||||
|
<!-- Whether or not the indicators should be centered. -->
|
||||||
|
<attr name="centered" format="boolean" />
|
||||||
|
<!-- Color of the filled circle that represents the current page. -->
|
||||||
|
<attr name="fillColor" format="color" />
|
||||||
|
<!-- Orientation of the indicator. -->
|
||||||
|
<attr name="orientation">
|
||||||
|
<enum name="horizontal" value="0" />
|
||||||
|
<enum name="vertical" value="1" />
|
||||||
|
</attr>
|
||||||
|
<!-- Radius of the circles. This is also the spacing between circles. -->
|
||||||
|
<attr name="radius" format="dimension" />
|
||||||
|
<!-- Whether or not the selected indicator snaps to the circles. -->
|
||||||
|
<attr name="snap" format="boolean" />
|
||||||
|
<!-- Color of the open circles. -->
|
||||||
|
<attr name="strokeColor" format="color" />
|
||||||
|
<!-- Width of the stroke used to draw the circles. -->
|
||||||
|
<attr name="strokeWidth" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="TitlePageIndicator">
|
||||||
|
<!-- Screen edge padding. -->
|
||||||
|
<attr name="clipPadding" format="dimension" />
|
||||||
|
<!-- Color of the footer line and indicator. -->
|
||||||
|
<attr name="footerColor" format="color" />
|
||||||
|
<!-- Height of the footer line. -->
|
||||||
|
<attr name="footerLineHeight" format="dimension" />
|
||||||
|
<!-- Style of the indicator. Default is triangle. -->
|
||||||
|
<attr name="footerIndicatorStyle">
|
||||||
|
<enum name="none" value="0" />
|
||||||
|
<enum name="triangle" value="1" />
|
||||||
|
<enum name="underline" value="2" />
|
||||||
|
</attr>
|
||||||
|
<!-- Height of the indicator above the footer line. -->
|
||||||
|
<attr name="footerIndicatorHeight" format="dimension" />
|
||||||
|
<!-- Left and right padding of the underline indicator. -->
|
||||||
|
<attr name="footerIndicatorUnderlinePadding" format="dimension" />
|
||||||
|
<!-- Padding between the bottom of the title and the footer. -->
|
||||||
|
<attr name="footerPadding" format="dimension" />
|
||||||
|
<!-- Color of the selected title. -->
|
||||||
|
<attr name="selectedColor" format="color" />
|
||||||
|
<!-- Whether or not the selected item is displayed as bold. -->
|
||||||
|
<attr name="selectedBold" format="boolean" />
|
||||||
|
<!-- Color of regular titles. -->
|
||||||
|
<attr name="textColor" format="color" />
|
||||||
|
<!-- Size of title text. -->
|
||||||
|
<attr name="textSize" format="dimension" />
|
||||||
|
<!-- Padding between titles when bumping into each other. -->
|
||||||
|
<attr name="titlePadding" format="dimension" />
|
||||||
|
<!-- Padding between titles and the top of the View. -->
|
||||||
|
<attr name="topPadding" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<color name="vpi__background_holo_dark">#ff000000</color>
|
||||||
|
<color name="vpi__background_holo_light">#fff3f3f3</color>
|
||||||
|
<color name="vpi__bright_foreground_holo_dark">@color/vpi__background_holo_light</color>
|
||||||
|
<color name="vpi__bright_foreground_holo_light">@color/vpi__background_holo_dark</color>
|
||||||
|
<color name="vpi__bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
|
||||||
|
<color name="vpi__bright_foreground_disabled_holo_light">#ffb2b2b2</color>
|
||||||
|
<color name="vpi__bright_foreground_inverse_holo_dark">@color/vpi__bright_foreground_holo_light</color>
|
||||||
|
<color name="vpi__bright_foreground_inverse_holo_light">@color/vpi__bright_foreground_holo_dark</color>
|
||||||
|
</resources>
|
||||||