diff --git a/.gitignore b/.gitignore index cfa9589..7e632a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,42 @@ -bin/* -UI/bin/* -UI/Demo/bin/* -UI/Demo/gen/* -gen/* -.settings/* -*.class +.DS_Store + +# built application files *.apk *.ap_ -libs/* + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ +apk/ + +# imported libraries +libs/ + +# Local configuration file (sdk path, etc) +local.properties +.settings + +# Eclipse project files +.classpath +.project + +# Android Studio +.idea/ +.gradle +gradle +/*/local.properties +/*/out +/*/*/build +build +/*/*/production +*.iml +*.iws +*.ipr +*~ +*.swp \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index fa4e93d..4985cdf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "UI/color-picker"] - path = UI/color-picker +[submodule "color-picker"] + path = color-picker url = https://github.com/dmfs/color-picker.git diff --git a/Demo/build.gradle b/Demo/build.gradle new file mode 100644 index 0000000..9f9b963 --- /dev/null +++ b/Demo/build.gradle @@ -0,0 +1,23 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 21 + buildToolsVersion "21.1.2" + + defaultConfig { + applicationId "com.schedjoules.demo" + minSdkVersion 14 + targetSdkVersion 19 + } + + buildTypes { + release { + minifyEnabled true + proguardFiles 'proguard.cfg' + } + } +} + +dependencies { + compile project(':UI') +} diff --git a/UI/Demo/proguard.cfg b/Demo/proguard.cfg similarity index 100% rename from UI/Demo/proguard.cfg rename to Demo/proguard.cfg diff --git a/UI/Demo/AndroidManifest.xml b/Demo/src/main/AndroidManifest.xml similarity index 88% rename from UI/Demo/AndroidManifest.xml rename to Demo/src/main/AndroidManifest.xml index 14cdc24..002ff40 100644 --- a/UI/Demo/AndroidManifest.xml +++ b/Demo/src/main/AndroidManifest.xml @@ -3,11 +3,11 @@ package="com.schedjoules.demo" android:installLocation="internalOnly" android:versionCode="106" - android:versionName="1" > + android:versionName="1"> + android:targetSdkVersion="21" /> @@ -24,7 +24,7 @@ - + @@ -38,10 +38,11 @@ android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme" > + android:theme="@style/AppTheme"> + android:label="@string/title_activity_home" + android:theme="@style/AppThemeToolBar"> @@ -50,12 +51,11 @@ - + android:label="@string/app_name"> + android:parentActivityName="org.dmfs.webcal.MainActivity"> + android:label="@string/activity_title_events_preview"> @@ -75,7 +75,7 @@ + android:process=":sync"> @@ -87,7 +87,7 @@ + android:process=":auth"> @@ -98,8 +98,7 @@ - + android:exported="false"> - + android:process=":provider"> - + android:process=":previewprovider"> - + android:label="@string/title_activity_preferences"> - + diff --git a/UI/Demo/src/com/schedjoules/demo/SecretProvider.java b/Demo/src/main/java/com/schedjoules/demo/SecretProvider.java similarity index 100% rename from UI/Demo/src/com/schedjoules/demo/SecretProvider.java rename to Demo/src/main/java/com/schedjoules/demo/SecretProvider.java diff --git a/UI/Demo/res/drawable-hdpi/ic_launcher.png b/Demo/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from UI/Demo/res/drawable-hdpi/ic_launcher.png rename to Demo/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/UI/Demo/res/drawable-ldpi/ic_launcher.png b/Demo/src/main/res/drawable-ldpi/ic_launcher.png similarity index 100% rename from UI/Demo/res/drawable-ldpi/ic_launcher.png rename to Demo/src/main/res/drawable-ldpi/ic_launcher.png diff --git a/UI/Demo/res/drawable-mdpi/ic_launcher.png b/Demo/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from UI/Demo/res/drawable-mdpi/ic_launcher.png rename to Demo/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/UI/Demo/res/drawable-xhdpi/ic_launcher.png b/Demo/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from UI/Demo/res/drawable-xhdpi/ic_launcher.png rename to Demo/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/UI/Demo/res/drawable-xxhdpi/ic_launcher.png b/Demo/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from UI/Demo/res/drawable-xxhdpi/ic_launcher.png rename to Demo/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/UI/Demo/res/drawable-xxxhdpi/ic_launcher.png b/Demo/src/main/res/drawable-xxxhdpi/ic_launcher.png similarity index 100% rename from UI/Demo/res/drawable-xxxhdpi/ic_launcher.png rename to Demo/src/main/res/drawable-xxxhdpi/ic_launcher.png diff --git a/UI/Demo/res/drawable/miniicon.png b/Demo/src/main/res/drawable/miniicon.png similarity index 100% rename from UI/Demo/res/drawable/miniicon.png rename to Demo/src/main/res/drawable/miniicon.png diff --git a/UI/Demo/res/values-de/strings.xml b/Demo/src/main/res/values-de/strings.xml similarity index 100% rename from UI/Demo/res/values-de/strings.xml rename to Demo/src/main/res/values-de/strings.xml diff --git a/UI/Demo/res/values-es/strings.xml b/Demo/src/main/res/values-es/strings.xml similarity index 100% rename from UI/Demo/res/values-es/strings.xml rename to Demo/src/main/res/values-es/strings.xml diff --git a/UI/Demo/res/values-fr/strings.xml b/Demo/src/main/res/values-fr/strings.xml similarity index 100% rename from UI/Demo/res/values-fr/strings.xml rename to Demo/src/main/res/values-fr/strings.xml diff --git a/UI/Demo/res/values-it/strings.xml b/Demo/src/main/res/values-it/strings.xml similarity index 100% rename from UI/Demo/res/values-it/strings.xml rename to Demo/src/main/res/values-it/strings.xml diff --git a/UI/Demo/res/values-nl/strings.xml b/Demo/src/main/res/values-nl/strings.xml similarity index 100% rename from UI/Demo/res/values-nl/strings.xml rename to Demo/src/main/res/values-nl/strings.xml diff --git a/UI/Demo/res/values-pt/strings.xml b/Demo/src/main/res/values-pt/strings.xml similarity index 100% rename from UI/Demo/res/values-pt/strings.xml rename to Demo/src/main/res/values-pt/strings.xml diff --git a/UI/Demo/res/values-v11/styles.xml b/Demo/src/main/res/values-v11/styles.xml similarity index 100% rename from UI/Demo/res/values-v11/styles.xml rename to Demo/src/main/res/values-v11/styles.xml diff --git a/UI/Demo/res/values-v14/styles.xml b/Demo/src/main/res/values-v14/styles.xml similarity index 100% rename from UI/Demo/res/values-v14/styles.xml rename to Demo/src/main/res/values-v14/styles.xml diff --git a/UI/Demo/res/values-v16/content_provider_settings.xml b/Demo/src/main/res/values-v16/content_provider_settings.xml similarity index 100% rename from UI/Demo/res/values-v16/content_provider_settings.xml rename to Demo/src/main/res/values-v16/content_provider_settings.xml diff --git a/UI/Demo/res/values/content_provider_settings.xml b/Demo/src/main/res/values/content_provider_settings.xml similarity index 100% rename from UI/Demo/res/values/content_provider_settings.xml rename to Demo/src/main/res/values/content_provider_settings.xml diff --git a/UI/Demo/res/values/defaults.xml b/Demo/src/main/res/values/defaults.xml similarity index 100% rename from UI/Demo/res/values/defaults.xml rename to Demo/src/main/res/values/defaults.xml diff --git a/UI/Demo/res/values/schedjoules_constants.xml b/Demo/src/main/res/values/schedjoules_constants.xml similarity index 100% rename from UI/Demo/res/values/schedjoules_constants.xml rename to Demo/src/main/res/values/schedjoules_constants.xml diff --git a/UI/Demo/res/values/schedjoules_sdk.xml b/Demo/src/main/res/values/schedjoules_sdk.xml similarity index 100% rename from UI/Demo/res/values/schedjoules_sdk.xml rename to Demo/src/main/res/values/schedjoules_sdk.xml diff --git a/UI/Demo/res/values/strings.xml b/Demo/src/main/res/values/strings.xml similarity index 100% rename from UI/Demo/res/values/strings.xml rename to Demo/src/main/res/values/strings.xml diff --git a/UI/Demo/res/values/styles.xml b/Demo/src/main/res/values/styles.xml similarity index 100% rename from UI/Demo/res/values/styles.xml rename to Demo/src/main/res/values/styles.xml diff --git a/UI/Demo/res/xml/authenticator.xml b/Demo/src/main/res/xml/authenticator.xml similarity index 100% rename from UI/Demo/res/xml/authenticator.xml rename to Demo/src/main/res/xml/authenticator.xml diff --git a/UI/Demo/res/xml/syncadapter.xml b/Demo/src/main/res/xml/syncadapter.xml similarity index 100% rename from UI/Demo/res/xml/syncadapter.xml rename to Demo/src/main/res/xml/syncadapter.xml diff --git a/UI/.classpath b/UI/.classpath deleted file mode 100644 index d016696..0000000 --- a/UI/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/UI/.project b/UI/.project deleted file mode 100644 index 5c66eac..0000000 --- a/UI/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - SchedJoules-SDK - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/UI/.settings/org.eclipse.jdt.core.prefs b/UI/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b080d2d..0000000 --- a/UI/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/UI/Demo/.classpath b/UI/Demo/.classpath deleted file mode 100644 index 7bc01d9..0000000 --- a/UI/Demo/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/UI/Demo/.project b/UI/Demo/.project deleted file mode 100644 index 959c35b..0000000 --- a/UI/Demo/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - SchedJoules-SDK-Demo - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/UI/Demo/.settings/org.eclipse.jdt.core.prefs b/UI/Demo/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b080d2d..0000000 --- a/UI/Demo/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/UI/Demo/proguard-project.txt b/UI/Demo/proguard-project.txt deleted file mode 100644 index f2fe155..0000000 --- a/UI/Demo/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/UI/Demo/project.properties b/UI/Demo/project.properties deleted file mode 100644 index 2d09542..0000000 --- a/UI/Demo/project.properties +++ /dev/null @@ -1,16 +0,0 @@ -# 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 edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-19 -android.library.reference.1=.. -proguard.config=proguard.cfg diff --git a/UI/build.gradle b/UI/build.gradle new file mode 100644 index 0000000..87eb243 --- /dev/null +++ b/UI/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 21 + buildToolsVersion '21.1.2' + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 19 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} + +dependencies { + compile 'com.android.support:appcompat-v7:21.0.+' + compile 'com.google.android.gms:play-services:7.0.0' + compile files('libs/android-retention-magic-1.2.2.jar') + compile files('libs/async-tools-1.1.jar') + compile files('libs/schedjoules-sdk.jar') + compile project(':colorpicker') +} diff --git a/UI/color-picker b/UI/color-picker deleted file mode 160000 index 67f7451..0000000 --- a/UI/color-picker +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 67f74518851b3b851ca5c63672a58fb68121c4f3 diff --git a/UI/gen/.gitignore b/UI/gen/.gitignore deleted file mode 100644 index 24eb708..0000000 --- a/UI/gen/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/com -/org -/.gitignore diff --git a/UI/libs/android-support-v4.jar b/UI/libs/android-support-v4.jar deleted file mode 100644 index 9056828..0000000 Binary files a/UI/libs/android-support-v4.jar and /dev/null differ diff --git a/UI/proguard-project.txt b/UI/proguard-project.txt deleted file mode 100644 index f2b2405..0000000 --- a/UI/proguard-project.txt +++ /dev/null @@ -1,37 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - --keep class * extends java.util.ListResourceBundle { - protected Object[][] getContents(); -} - --keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { - public static final *** NULL; -} - --keepnames @com.google.android.gms.common.annotation.KeepName class * --keepclassmembernames class * { - @ccom.google.android.gms.common.annotation.KeepName *; -} - --keepnames class * implements android.os.Parcelable { - public static final ** CREATOR; -} \ No newline at end of file diff --git a/UI/proguard.cfg b/UI/proguard.cfg deleted file mode 100644 index b500559..0000000 --- a/UI/proguard.cfg +++ /dev/null @@ -1,101 +0,0 @@ --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable --dontwarn android.support.** - --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 ; -} - --keepclasseswithmembernames class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembernames class * { - public (android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} - --keep public class * extends org.dmfs.android.authenticator.AuthSchemeHandler --keep public class * extends org.dmfs.mimedir.Profile --keep public class * extends org.dmfs.mimedir.MimeDirEntity - --keepclassmembers class * extends org.dmfs.android.authenticator.AuthSchemeHandler { - public (android.content.Context, android.net.Uri); -} - --keepclassmembers class * extends org.dmfs.mimedir.** { - public (...); -} - --keep class * implements org.dmfs.android.authenticator.obfuscater.Obfuscater$IObfuscaterProvider - --keep class * implements org.dmfs.android.calendarcontent.secrets.ISecretProvider - --keep class * extends org.dmfs.android.calendarcontent.servicehelper.AbstractServiceHelper - --keepclassmembers class * extends org.dmfs.android.calendarcontent.servicehelper.AbstractServiceHelper { - public (...); -} - --keepclassmembers class * implements org.dmfs.sync.entities.SyncEntity { - public (...); -} - -# this is required to keep the Annotations --keepattributes *Annotation* - -# keep relevant members in Activities --keepclassmembers class * extends android.app.Activity -{ - # optional, keep TAG fields if you use them for automatic namespacing - # you don't need this line if don't use the "permanent" feature or - # if you set the namespace like so: - # @Retain(permanent = true, classNS = TAG) - # or - # @Retain(permanent = true, classNS = "someNameSpace") - java.lang.String TAG; - - # optional, keep names of retained fields - # you don't need this line if don't use the "permanent" feature or - # if you set the key manually like in @Retain(key = "someKey"); - @org.dmfs.android.retentionmagic.annotations.* ; - - private long mId; -} - -# same for Fragments --keepclassmembers class * extends android.app.Fragment -{ - java.lang.String TAG; - @org.dmfs.android.retentionmagic.annotations.* ; - private long mId; -} - -# same for support library Fragments --keepclassmembers class * extends android.support.v4.app.Fragment -{ - java.lang.String TAG; - @org.dmfs.android.retentionmagic.annotations.* ; - private long mId; -} \ No newline at end of file diff --git a/UI/project.properties b/UI/project.properties deleted file mode 100644 index e6dc99e..0000000 --- a/UI/project.properties +++ /dev/null @@ -1,17 +0,0 @@ -# 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 edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-21 -android.library=true -android.library.reference.1=../../google-play-services_lib -android.library.reference.2=../../libraries/color-picker diff --git a/UI/res/layout/activity_home.xml b/UI/res/layout/activity_home.xml deleted file mode 100644 index cfa22aa..0000000 --- a/UI/res/layout/activity_home.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/UI/res/layout/categories_list.xml b/UI/res/layout/categories_list.xml deleted file mode 100644 index 10121cb..0000000 --- a/UI/res/layout/categories_list.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - \ No newline at end of file diff --git a/UI/res/layout/fragment_pager.xml b/UI/res/layout/fragment_pager.xml deleted file mode 100644 index 65a6c69..0000000 --- a/UI/res/layout/fragment_pager.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/UI/AndroidManifest.xml b/UI/src/main/AndroidManifest.xml similarity index 91% rename from UI/AndroidManifest.xml rename to UI/src/main/AndroidManifest.xml index b396544..660cce8 100644 --- a/UI/AndroidManifest.xml +++ b/UI/src/main/AndroidManifest.xml @@ -3,11 +3,11 @@ package="org.dmfs.webcal" android:installLocation="internalOnly" android:versionCode="106" - android:versionName="1" > + android:versionName="1"> + android:targetSdkVersion="21" /> @@ -27,7 +27,6 @@ - + android:theme="@style/AppTheme"> diff --git a/UI/src/com/android/vending/billing/IInAppBillingService.aidl b/UI/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl similarity index 100% rename from UI/src/com/android/vending/billing/IInAppBillingService.aidl rename to UI/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl diff --git a/UI/assets/.gitignore b/UI/src/main/assets/.gitignore similarity index 100% rename from UI/assets/.gitignore rename to UI/src/main/assets/.gitignore diff --git a/UI/src/main/java/org/dmfs/webcal/ActionBarActivity.java b/UI/src/main/java/org/dmfs/webcal/ActionBarActivity.java new file mode 100644 index 0000000..71d97ad --- /dev/null +++ b/UI/src/main/java/org/dmfs/webcal/ActionBarActivity.java @@ -0,0 +1,74 @@ +package org.dmfs.webcal; + +import org.dmfs.android.retentionmagic.RetentionMagic; + +import android.content.SharedPreferences; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; + + +/** + * Provides {@link org.dmfs.android.retentionmagic.RetentionMagic} functionality for {@link android.support.v7.app.ActionBarActivity} + * + * @author Tobias Reinsch + * + */ +public class ActionBarActivity extends android.support.v7.app.ActionBarActivity +{ + private SharedPreferences mPrefs; + + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + mPrefs = getSharedPreferences(getPackageName() + ".sharedPrefences", 0); + + RetentionMagic.init(this, getIntent().getExtras()); + + if (savedInstanceState == null) + { + RetentionMagic.init(this, mPrefs); + } + else + { + RetentionMagic.restore(this, savedInstanceState); + } + } + + + @Override + protected void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + RetentionMagic.store(this, outState); + } + + + @Override + protected void onPause() + { + super.onPause(); + /* + * On older SDK version we have to store permanent data in onPause(), because there is no guarantee that onStop() will be called. + */ + if (VERSION.SDK_INT < VERSION_CODES.HONEYCOMB) + { + RetentionMagic.persist(this, mPrefs); + } + } + + + @Override + protected void onStop() + { + super.onStop(); + if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) + { + RetentionMagic.persist(this, mPrefs); + } + } + +} diff --git a/UI/src/org/dmfs/webcal/DummyAuthenticatorActivity.java b/UI/src/main/java/org/dmfs/webcal/DummyAuthenticatorActivity.java similarity index 100% rename from UI/src/org/dmfs/webcal/DummyAuthenticatorActivity.java rename to UI/src/main/java/org/dmfs/webcal/DummyAuthenticatorActivity.java diff --git a/UI/src/org/dmfs/webcal/EventsPreviewActivity.java b/UI/src/main/java/org/dmfs/webcal/EventsPreviewActivity.java similarity index 69% rename from UI/src/org/dmfs/webcal/EventsPreviewActivity.java rename to UI/src/main/java/org/dmfs/webcal/EventsPreviewActivity.java index fff9383..351a780 100644 --- a/UI/src/org/dmfs/webcal/EventsPreviewActivity.java +++ b/UI/src/main/java/org/dmfs/webcal/EventsPreviewActivity.java @@ -17,51 +17,72 @@ package org.dmfs.webcal; -import org.dmfs.android.retentionmagic.FragmentActivity; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import org.dmfs.android.retentionmagic.annotations.Parameter; +import org.dmfs.webcal.IBillingActivity.OnInventoryListener; import org.dmfs.webcal.fragments.EventsPreviewDetailFragment; import org.dmfs.webcal.utils.Event; +import org.dmfs.webcal.utils.billing.IabHelper; +import org.dmfs.webcal.utils.billing.Inventory; -import android.app.ActionBar; import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBar; import android.text.TextUtils; import android.view.MenuItem; /** * An Activity that presents the details of an event to the user. - * + * * @author Marten Gajda */ -public class EventsPreviewActivity extends FragmentActivity +public class EventsPreviewActivity extends ActionBarActivity { + private final static int REQUEST_CODE_LAUNCH_PURCHASE_FLOW = 10004; + private final static long MAX_INVENTORY_AGE = 90L * 60L * 1000L; // 90 minutes + private static final String EXTRA_CALENDAR_NAME = "org.dmfs.webcal.EventsPreviewActivity.CALENDAR_NAME"; private static final String EXTRA_CALENDAR_IMAGE = "org.dmfs.webcal.EventsPreviewActivity.CALENDAR_IMAGE_URL"; private static final String EXTRA_PREVIEW_EVENT = "org.dmfs.webcal.EventsPreviewActivity.PREVIEW_EVENT"; private static final String EXTRA_PAGE_TITLE = "org.dmfs.webcal.EventsPreviewActivity.PAGE_TITLE"; + private static final String EXTRA_CONTENT_ITEM_URI = "org.dmfs.webcal.EventsPreviewActivity.CONTENT_ITEM_URI"; private static final String CONTENT_TYPE_EVENT = "vnd.android.cursor.item/event"; - + @Parameter(key = EXTRA_PREVIEW_EVENT) + Event mEvent = null; @Parameter(key = EXTRA_CALENDAR_NAME) private String mCalendarName; - @Parameter(key = EXTRA_CALENDAR_IMAGE) private long mCalendarIconId; - - @Parameter(key = EXTRA_PREVIEW_EVENT) - Event mEvent = null; - @Parameter(key = EXTRA_PAGE_TITLE) private String mTitle = null; + @Parameter(key = EXTRA_CONTENT_ITEM_URI) + private Uri mContentItemUri; + + /* + * The fields below have been copied from {@link MainActivity}. We should find a way to remove that duplicate code. + */ + private List> mBillingCallbacks = null; + private List mMoreItemSkus = Collections.synchronizedList(new ArrayList()); + private IabHelper mIabHelper; + private boolean mIabHelperReady = false; + private Inventory mInventoryCache = null; + private long mInventoryTime = 0; + /** * Shows a details view for the given event. - * + * * @param context * A {@link Context}. * @param event @@ -73,13 +94,14 @@ public class EventsPreviewActivity extends FragmentActivity * @param title * The title of the page. */ - public static void show(Context context, Event event, String calendarName, long mIconId, String title) + public static void show(Context context, Event event, String calendarName, long mIconId, String title, Uri contentItemUri) { Intent intent = new Intent(context, EventsPreviewActivity.class); intent.putExtra(EXTRA_CALENDAR_NAME, calendarName); intent.putExtra(EXTRA_CALENDAR_IMAGE, mIconId); intent.putExtra(EXTRA_PREVIEW_EVENT, event); intent.putExtra(EXTRA_PAGE_TITLE, title); + intent.putExtra(EXTRA_CONTENT_ITEM_URI, contentItemUri); context.startActivity(intent); } @@ -94,12 +116,11 @@ protected void onCreate(Bundle savedInstanceState) { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); - transaction.add(R.id.events_preview_fragment_container, - EventsPreviewDetailFragment.newInstance(mEvent, mCalendarName, mCalendarIconId, mTitle)); + transaction.add(R.id.events_preview_fragment_container, EventsPreviewDetailFragment.newInstance(mEvent, mCalendarName, mCalendarIconId, mTitle)); transaction.commit(); } - ActionBar actionBar = getActionBar(); + ActionBar actionBar = getSupportActionBar(); if (TextUtils.equals(mTitle, mCalendarName)) { @@ -113,7 +134,7 @@ protected void onCreate(Bundle savedInstanceState) } // Show the Up button in the action bar. - getActionBar().setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); } diff --git a/UI/src/org/dmfs/webcal/IBillingActivity.java b/UI/src/main/java/org/dmfs/webcal/IBillingActivity.java similarity index 100% rename from UI/src/org/dmfs/webcal/IBillingActivity.java rename to UI/src/main/java/org/dmfs/webcal/IBillingActivity.java diff --git a/UI/src/org/dmfs/webcal/MainActivity.java b/UI/src/main/java/org/dmfs/webcal/MainActivity.java similarity index 96% rename from UI/src/org/dmfs/webcal/MainActivity.java rename to UI/src/main/java/org/dmfs/webcal/MainActivity.java index cc1e555..142e03d 100644 --- a/UI/src/org/dmfs/webcal/MainActivity.java +++ b/UI/src/main/java/org/dmfs/webcal/MainActivity.java @@ -57,6 +57,7 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v7.widget.Toolbar; import android.util.Log; import com.schedjoules.analytics.Analytics; @@ -70,43 +71,43 @@ public class MainActivity extends NavbarActivity implements CategoryNavigator, IBillingActivity, OnIabSetupFinishedListener, QueryInventoryFinishedListener, LoaderCallbacks { + public static final String SUBCATEGORY_EXTRA = "org.dmfs.webcal.SUBCATEGORY_EXTRA"; private final static int REQUEST_CODE_LAUNCH_PURCHASE_FLOW = 10003; private final static int REQUEST_CODE_LAUNCH_SUBSCRIPTION_FLOW = 10004; - /** * The interval in milliseconds to retry to load the inventory in case of an error. **/ private static final long RELOAD_INVENTORY_INTERVAL = 15000; - private final static long MAX_ANALYTICS_AGE = 60L * 1000L; // 1 minute - - public static final String SUBCATEGORY_EXTRA = "org.dmfs.webcal.SUBCATEGORY_EXTRA"; - - private FragmentManager mFragmentManager; - /** * List of callbacks for inventory results. */ private final List> mBillingCallbacks = Collections .synchronizedList(new ArrayList>(8)); - private final List mMoreItemSkus = Collections.synchronizedList(new ArrayList()); + private final Handler mHandler = new Handler(); + /** + * A {@link Runnable} that triggers the inventory loading. + * + */ + private final Runnable mReloadInventoryRunnable = new Runnable() + { + @Override + public void run() + { + refreshInventory(); + } + }; + protected FragmentManager mFragmentManager; + @Retain + protected long mSelectedItemId = 0; /** * Helper for billing services. */ private IabHelper mIabHelper; - private boolean mIabHelperReady = false; - private Inventory mInventoryCache = null; - @Retain - private long mSelectedItemId = 0; - - @Retain(key = "firststart", permanent = true, classNS = "MainActivity") - private boolean mFirstStart = true; - - private final Handler mHandler = new Handler(); @Override @@ -114,7 +115,10 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); - setupNavbar(); + + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + setupNavbar(toolbar); mFragmentManager = getSupportFragmentManager(); @@ -129,12 +133,6 @@ else if (mSelectedItemId >= 0) setNavigationSelectionById(mSelectedItemId); } - if (mFirstStart) - { - mFirstStart = false; - openDrawer(); - } - if (savedInstanceState == null) { Analytics.sessionStart("MAIN"); @@ -246,7 +244,11 @@ public void openCalendar(long id, long icon) mFragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); Fragment contentFragment = mFragmentManager.findFragmentById(R.id.content); - String title = contentFragment.getArguments().getString(PagerFragment.ARG_PAGE_TITLE); + String title = ""; + if (contentFragment != null) + { + title = contentFragment.getArguments().getString(PagerFragment.ARG_PAGE_TITLE); + } CalendarItemFragment fragment = CalendarItemFragment.newInstance(this, id, title, icon); fragmentTransaction.replace(R.id.content, fragment); fragmentTransaction.addToBackStack(""); @@ -411,6 +413,7 @@ public void onQueryInventoryFinished(IabResult result, Inventory inv) { if (result.isSuccess()) { + Log.v(TAG, "got new inventory "); mInventoryCache = inv; notifyInventoryListeners(); } @@ -424,36 +427,6 @@ public void onQueryInventoryFinished(IabResult result, Inventory inv) } } - /** - * A {@link Runnable} that triggers a transmission of analytics hits at least every {@value #MAX_INVENTORY_AGE} milliseconds. - * - * @see #MAX_ANALYTICS_AGE - */ - private final Runnable mAnalyticsTrigger = new Runnable() - { - - @Override - public void run() - { - Analytics.triggerSendBatch(); - mHandler.postDelayed(mAnalyticsTrigger, MAX_ANALYTICS_AGE); - } - }; - - /** - * A {@link Runnable} that triggers the inventory loading. - * - */ - private final Runnable mReloadInventoryRunnable = new Runnable() - { - - @Override - public void run() - { - refreshInventory(); - } - }; - @Override public void refreshInventory() @@ -651,11 +624,13 @@ public Loader onCreateLoader(int loaderId, Bundle extras) @Override public void onLoadFinished(Loader loader, Cursor cursor) { + Log.v("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "load finished"); if (cursor != null && cursor.moveToFirst()) { String subscriptionId = cursor.getString(1); if (subscriptionId != null && !mMoreItemSkus.contains(subscriptionId)) { + Log.v(TAG, "got new subscription id " + subscriptionId); mMoreItemSkus.add(subscriptionId); refreshInventory(); } @@ -667,4 +642,21 @@ public void onLoadFinished(Loader loader, Cursor cursor) public void onLoaderReset(Loader arg0) { } + + /** + * A {@link Runnable} that triggers a transmission of analytics hits at least every {@value #MAX_INVENTORY_AGE} milliseconds. + * + * @see #MAX_ANALYTICS_AGE + */ + private final Runnable mAnalyticsTrigger = new Runnable() + { + + @Override + public void run() + { + Analytics.triggerSendBatch(); + mHandler.postDelayed(mAnalyticsTrigger, MAX_ANALYTICS_AGE); + } + }; + } diff --git a/UI/src/org/dmfs/webcal/NavbarActivity.java b/UI/src/main/java/org/dmfs/webcal/NavbarActivity.java similarity index 95% rename from UI/src/org/dmfs/webcal/NavbarActivity.java rename to UI/src/main/java/org/dmfs/webcal/NavbarActivity.java index e5e8e6b..e07d5c0 100644 --- a/UI/src/org/dmfs/webcal/NavbarActivity.java +++ b/UI/src/main/java/org/dmfs/webcal/NavbarActivity.java @@ -17,16 +17,15 @@ package org.dmfs.webcal; -import org.dmfs.android.retentionmagic.FragmentActivity; - import android.content.Context; import android.content.res.Configuration; import android.database.DataSetObserver; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.Toolbar; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.Menu; @@ -40,7 +39,7 @@ import android.widget.TextView; -public abstract class NavbarActivity extends FragmentActivity implements ListView.OnItemClickListener +public abstract class NavbarActivity extends ActionBarActivity implements ListView.OnItemClickListener { protected static final String TAG = "NavbarActivity"; protected DrawerLayout mDrawerLayout; @@ -48,7 +47,7 @@ public abstract class NavbarActivity extends FragmentActivity implements ListVie private ActionBarDrawerToggle mDrawerToggle; - protected void setupNavbar() + protected void setupNavbar(Toolbar toolbar) { mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.left_drawer); @@ -77,7 +76,7 @@ protected void setupNavbar() MenuAdapter menuAdapter = new MenuAdapter(this, R.layout.navdrawer_item, android.R.id.title, menu); mDrawerList.setAdapter(menuAdapter); - mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) + mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) { @Override public void onDrawerClosed(View drawerView) @@ -101,8 +100,6 @@ public void onDrawerOpened(View drawerView) mDrawerLayout.setDrawerListener(mDrawerToggle); mDrawerList.setOnItemClickListener(this); - getActionBar().setDisplayHomeAsUpEnabled(true); - getActionBar().setHomeButtonEnabled(true); } diff --git a/UI/src/org/dmfs/webcal/PreferencesActivity.java b/UI/src/main/java/org/dmfs/webcal/PreferencesActivity.java similarity index 84% rename from UI/src/org/dmfs/webcal/PreferencesActivity.java rename to UI/src/main/java/org/dmfs/webcal/PreferencesActivity.java index 977894d..274729f 100644 --- a/UI/src/org/dmfs/webcal/PreferencesActivity.java +++ b/UI/src/main/java/org/dmfs/webcal/PreferencesActivity.java @@ -17,15 +17,13 @@ package org.dmfs.webcal; -import org.dmfs.webcal.fragments.PreferencesFragment; - -import android.app.ActionBar; import android.os.Bundle; -import android.support.v4.app.FragmentActivity; import android.view.MenuItem; +import org.dmfs.webcal.fragments.PreferencesFragment; + -public class PreferencesActivity extends FragmentActivity +public class PreferencesActivity extends ActionBarActivity { @Override @@ -34,8 +32,7 @@ protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_preferences); getFragmentManager().beginTransaction().replace(R.id.pref_fragment_container, new PreferencesFragment()).commit(); - ActionBar actionBar = getActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); } diff --git a/UI/src/org/dmfs/webcal/adapters/EventListAdapter.java b/UI/src/main/java/org/dmfs/webcal/adapters/EventListAdapter.java similarity index 100% rename from UI/src/org/dmfs/webcal/adapters/EventListAdapter.java rename to UI/src/main/java/org/dmfs/webcal/adapters/EventListAdapter.java diff --git a/UI/src/org/dmfs/webcal/adapters/MixedNavigationAdapter.java b/UI/src/main/java/org/dmfs/webcal/adapters/MixedNavigationAdapter.java similarity index 100% rename from UI/src/org/dmfs/webcal/adapters/MixedNavigationAdapter.java rename to UI/src/main/java/org/dmfs/webcal/adapters/MixedNavigationAdapter.java diff --git a/UI/src/org/dmfs/webcal/adapters/SectionTitlesAdapter.java b/UI/src/main/java/org/dmfs/webcal/adapters/SectionTitlesAdapter.java similarity index 100% rename from UI/src/org/dmfs/webcal/adapters/SectionTitlesAdapter.java rename to UI/src/main/java/org/dmfs/webcal/adapters/SectionTitlesAdapter.java diff --git a/UI/src/org/dmfs/webcal/adapters/SectionsPagerAdapter.java b/UI/src/main/java/org/dmfs/webcal/adapters/SectionsPagerAdapter.java similarity index 100% rename from UI/src/org/dmfs/webcal/adapters/SectionsPagerAdapter.java rename to UI/src/main/java/org/dmfs/webcal/adapters/SectionsPagerAdapter.java diff --git a/UI/src/org/dmfs/webcal/fragments/ActionBarFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/ActionBarFragment.java similarity index 90% rename from UI/src/org/dmfs/webcal/fragments/ActionBarFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/ActionBarFragment.java index db53d7e..4ec58c0 100644 --- a/UI/src/org/dmfs/webcal/fragments/ActionBarFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/ActionBarFragment.java @@ -17,12 +17,14 @@ package org.dmfs.webcal.fragments; +import android.view.View; + import org.dmfs.android.retentionmagic.SupportFragment; public abstract class ActionBarFragment extends SupportFragment { - public abstract void setupActionBar(); + public abstract void setupActionBar(View view); } diff --git a/UI/src/org/dmfs/webcal/fragments/CalendarItemFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/CalendarItemFragment.java similarity index 98% rename from UI/src/org/dmfs/webcal/fragments/CalendarItemFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/CalendarItemFragment.java index 8923839..9a45f26 100644 --- a/UI/src/org/dmfs/webcal/fragments/CalendarItemFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/CalendarItemFragment.java @@ -39,7 +39,6 @@ import org.dmfs.webcal.utils.Event; import org.dmfs.webcal.utils.ProtectedBackgroundJob; -import android.app.ActionBar; import android.app.Activity; import android.content.ContentUris; import android.content.ContentValues; @@ -54,6 +53,8 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; import android.text.format.DateUtils; import android.text.format.Time; import android.util.Log; @@ -94,94 +95,110 @@ public class CalendarItemFragment extends SubscribeableItemFragment implements L */ private final static String[] PROJECTION = new String[] { CalendarContentContract.ContentItem.TITLE, CalendarContentContract.ContentItem.ICON_ID, CalendarContentContract.ContentItem.URL, ContentItem.STARRED, ContentItem._ID }; - + private final Place mWaitingForCalendarItem = new Place(1); + private final Place mWaitingForCalendarSubscription = new Place(1); + private final Place mWaitingForPayment = new Place(1); + private final Place mDone = new Place(); /** - * Column indices of the {@link CalendarItemFragment#PROJECTION} we use. + * This {@link Transition} is fired whenever the payment status changes or when a free trial is started or ends. */ - private interface COLUMNS + private Transition mPaymentStatusUpdated = new Transition(mWaitingForPayment, mWaitingForPayment, mDone) { - int TITLE = 0; - int ICON = 1; - int URL = 2; - int STARRED = 3; - @SuppressWarnings("unused") - int ID = 4; - } - + @Override + protected void execute(Void data) + { + // nothing to do, this just enables the mDone place to update the UI + } + }; + private final Handler mHandler = new Handler(); + /** + * Runnable that shows the progress indicator loading of the calendar takes longer than {@value #PROGRESS_INDICATOR_DELAY} milliseconds. + * + * @see #PROGRESS_INDICATOR_DELAY + */ + private final Runnable mProgressIndicator = new Runnable() + { + @Override + public void run() + { + mProgressBar.setVisibility(View.VISIBLE); + } + }; /** * The id of the calendar item. */ private long mId; - /** * The content {@link Uri} of the calendar item. */ @Parameter(key = ARG_CONTENT_URI) private Uri mContentUri; - /** * The title of the calendar item. */ @Parameter(key = ARG_TITLE) private String mTitle; - /** * The icon is initialized with the icon passed to {@link #newInstance(Uri, String, long)} or {@link #newInstance(Context, long, String, long)}. If the * calendar has it's own icon, it replaces the initial icon later on. */ @Parameter(key = ARG_ICON) private long mIcon; - /** * The current sync status of the calendar. */ private boolean mSynced = false; - /** * The current favorite status of the calendar. */ private boolean mStarred; - /** * The {@link Uri} of the calendar subscription, if there is any. */ private Uri mSubscriptionUri; + /** + * A {@link Transition} that's fired whenever the calendar subscription has been loaded. + */ + private Transition mSubscriptionLoaded = new Transition(mWaitingForCalendarSubscription, mWaitingForCalendarSubscription, mDone) + { + + @Override + protected void execute(Cursor cursor) + { + // the subscription has been loaded (or not) + if (cursor != null && cursor.moveToFirst()) + { + // we have a subscription + + // get the id + long id = cursor.getLong(cursor.getColumnIndex(SubscribedCalendars._ID)); + + // build the Uri + mSubscriptionUri = SubscribedCalendars.getItemContentUri(getActivity(), id); + + // get the sync status + mSynced = cursor.getInt(cursor.getColumnIndex(SubscribedCalendars.SYNC_ENABLED)) > 0; + } + + // set the sync switch accordingly + mTitleFragment.setSwitchChecked(mSynced); + // invalidate options to show/hide settings option + getActivity().invalidateOptionsMenu(); + } + }; /** * The name of the calendar. */ private String mCalendarName; - /** * The actual URL of the calendar data. */ private URI mCalendarUrl; - private CalendarTitleFragment mTitleFragment; - private ProgressBar mProgressBar; private EventListAdapter mListAdapter; private ActionBar mActionBar; - private SectionTitlesAdapter mSectionAdapter; - private ListView mListView; - - private final Place mWaitingForCalendarItem = new Place(1); - private final Place mWaitingForCalendarSubscription = new Place(1); - private final Place mWaitingForPayment = new Place(1); - private final Place mDone = new Place(); - - /** - * This {@link Transition} is fired whenever the payment status changes or when a free trial is started or ends. - */ - private Transition mPaymentStatusUpdated = new Transition(mWaitingForPayment, mWaitingForPayment, mDone) - { - @Override - protected void execute(Void data) - { - // nothing to do, this just enables the mDone place to update the UI - } - }; - /** * This {@link Transition} is fired whenever the calendar item is (re-) loaded. */ @@ -242,39 +259,8 @@ protected void execute(Cursor cursor) } } }; - - /** - * A {@link Transition} that's fired whenever the calendar subscription has been loaded. - */ - private Transition mSubscriptionLoaded = new Transition(mWaitingForCalendarSubscription, mWaitingForCalendarSubscription, mDone) - { - - @Override - protected void execute(Cursor cursor) - { - // the subscription has been loaded (or not) - if (cursor != null && cursor.moveToFirst()) - { - // we have a subscription - - // get the id - long id = cursor.getLong(cursor.getColumnIndex(SubscribedCalendars._ID)); - - // build the Uri - mSubscriptionUri = SubscribedCalendars.getItemContentUri(getActivity(), id); - - // get the sync status - mSynced = cursor.getInt(cursor.getColumnIndex(SubscribedCalendars.SYNC_ENABLED)) > 0; - } - - // set the sync switch accordingly - mTitleFragment.setSwitchChecked(mSynced); - - // invalidate options to show/hide settings option - getActivity().invalidateOptionsMenu(); - } - }; - + private SectionTitlesAdapter mSectionAdapter; + private ListView mListView; /** * This {@link Transition} is fired after {@link #mPaymentStatusUpdated} and {@link #mSubscriptionLoaded} are fired. */ @@ -286,17 +272,21 @@ protected void execute(Void data) mTitleFragment.enableSwitch(isPurchased() || inFreeTrial()); } }.setAutoFire(true); - /** * The {@link PetriNet} engine. */ private PetriNet mPetriNet = new PetriNet(mPaymentStatusUpdated, mItemLoaded, mSubscriptionLoaded, mEnableSwitch); - private final Handler mHandler = new Handler(); + + + public CalendarItemFragment() + { + // Obligatory unparameterized constructor + } /** * Create a new CalendarItemFragment. - * + * * @param contentUri * The content {@link Uri} of the calendar item. * @param title @@ -319,7 +309,7 @@ public static CalendarItemFragment newInstance(Uri contentUri, String title, lon /** * Create a new CalendarItemFragment. - * + * * @param context * A {@link Context}. * @param id @@ -336,22 +326,6 @@ public static CalendarItemFragment newInstance(Context context, long id, String } - public CalendarItemFragment() - { - // Obligatory unparameterized constructor - } - - - @Override - public void onAttach(final Activity activity) - { - super.onAttach(activity); - mActionBar = activity.getActionBar(); - mActionBar.removeAllTabs(); - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - - @Override public View onCreateItemView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -441,7 +415,7 @@ public void onResume() super.onResume(); // setup action bar, we do that here to be sure that it already has been created - mActionBar = getActivity().getActionBar(); + mActionBar = ((ActionBarActivity) getActivity()).getSupportActionBar(); mActionBar.setTitle(mCalendarName); mActionBar.setSubtitle(mTitle); } @@ -717,7 +691,8 @@ public void onItemClick(AdapterView listView, View view, int position, long i Event event = new Event(start, end, cursor.getString(cursor.getColumnIndex(WebCalReaderContract.Events.TITLE)), cursor.getString(cursor .getColumnIndex(WebCalReaderContract.Events.DESCRIPTION)), cursor.getString(cursor.getColumnIndex(WebCalReaderContract.Events.LOCATION))); - EventsPreviewActivity.show(getActivity(), event, mCalendarName, mIcon, mTitle); + Context context = getActivity(); + EventsPreviewActivity.show(context, event, mCalendarName, mIcon, mTitle, mContentUri); } @@ -774,16 +749,15 @@ public void onPaymentStatusChange() } /** - * Runnable that shows the progress indicator loading of the calendar takes longer than {@value #PROGRESS_INDICATOR_DELAY} milliseconds. - * - * @see #PROGRESS_INDICATOR_DELAY + * Column indices of the {@link CalendarItemFragment#PROJECTION} we use. */ - private final Runnable mProgressIndicator = new Runnable() + private interface COLUMNS { - @Override - public void run() - { - mProgressBar.setVisibility(View.VISIBLE); - } - }; + int TITLE = 0; + int ICON = 1; + int URL = 2; + int STARRED = 3; + @SuppressWarnings("unused") + int ID = 4; + } } diff --git a/UI/src/org/dmfs/webcal/fragments/CalendarSettingsFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/CalendarSettingsFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/CalendarSettingsFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/CalendarSettingsFragment.java index 746cc4e..53b128b 100644 --- a/UI/src/org/dmfs/webcal/fragments/CalendarSettingsFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/CalendarSettingsFragment.java @@ -52,7 +52,7 @@ /** * A fragment that shows the settings for a specific calendar. - * + * * @author Marten Gajda */ public class CalendarSettingsFragment extends SupportDialogFragment implements OnClickListener, ColorDialogResultListener, OnTextInputListener, @@ -99,9 +99,15 @@ public class CalendarSettingsFragment extends SupportDialogFragment implements O private Uri mSubscriptionUri; + public CalendarSettingsFragment() + { + // Required empty public constructor + } + + /** * Use this factory method to create a new instance of this fragment using the provided parameters. - * + * * @return A new instance of fragment CalendarSettingFragment. */ public static CalendarSettingsFragment newInstance(Uri subscriptionUri) @@ -114,12 +120,6 @@ public static CalendarSettingsFragment newInstance(Uri subscriptionUri) } - public CalendarSettingsFragment() - { - // Required empty public constructor - } - - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { diff --git a/UI/src/org/dmfs/webcal/fragments/CalendarTitleFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/CalendarTitleFragment.java similarity index 100% rename from UI/src/org/dmfs/webcal/fragments/CalendarTitleFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/CalendarTitleFragment.java diff --git a/UI/src/org/dmfs/webcal/fragments/CategoriesListFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/CategoriesListFragment.java similarity index 98% rename from UI/src/org/dmfs/webcal/fragments/CategoriesListFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/CategoriesListFragment.java index b70a362..624bd5b 100644 --- a/UI/src/org/dmfs/webcal/fragments/CategoriesListFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/CategoriesListFragment.java @@ -46,7 +46,7 @@ /** * A fragment that shows all items of a specific section of a page. These items represent either pages or calendars. - * + * * @author Marten Gajda */ public class CategoriesListFragment extends SupportFragment implements OnItemClickListener, LoaderCallbacks @@ -76,17 +76,6 @@ public class CategoriesListFragment extends SupportFragment implements OnItemCli @Retain private Uri mPurchasedItem = null; - /** - * An interface to be implemented by the parent activity of this fragment. It provides methods to navigate to a specific page or calendar. - */ - public interface CategoryNavigator - { - public void openCategory(long id, String title, long icon); - - - public void openCalendar(long id, long icon); - } - public static CategoriesListFragment newInstance(long sectionId, long parentItemId, int sectionPos, long iconId) { @@ -133,7 +122,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa * For now we keep it that way until we find a proper solution */ LoaderManager loaderManager = getParentFragment().getLoaderManager(); - loaderManager.initLoader((int) (-4 * 1000000 + mSectionId), null, this); + loaderManager.initLoader((int) (mSectionId), null, this); return mListView; } @@ -217,4 +206,15 @@ public int getSectionPos() { return mSectionPos; } + + /** + * An interface to be implemented by the parent activity of this fragment. It provides methods to navigate to a specific page or calendar. + */ + public interface CategoryNavigator + { + public void openCategory(long id, String title, long icon); + + + public void openCalendar(long id, long icon); + } } diff --git a/UI/src/org/dmfs/webcal/fragments/EventsPreviewDetailFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/EventsPreviewDetailFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/EventsPreviewDetailFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/EventsPreviewDetailFragment.java index 0cbe722..3e15957 100644 --- a/UI/src/org/dmfs/webcal/fragments/EventsPreviewDetailFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/EventsPreviewDetailFragment.java @@ -41,7 +41,7 @@ /** * A fragment that shows the details of an event. - * + * * @author Marten Gajda */ public class EventsPreviewDetailFragment extends SupportFragment @@ -66,9 +66,15 @@ public class EventsPreviewDetailFragment extends SupportFragment private String mTitle; + public EventsPreviewDetailFragment() + { + // Required empty public constructor + } + + /** * Create a new {@link EventsPreviewDetailFragment} for the given {@link Event}, calendar name, icon and page title. - * + * * @param event * The {@link Event}. * @param calendarName @@ -92,12 +98,6 @@ public static EventsPreviewDetailFragment newInstance(Event event, String calend } - public EventsPreviewDetailFragment() - { - // Required empty public constructor - } - - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { diff --git a/UI/src/org/dmfs/webcal/fragments/GenericListFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/GenericListFragment.java similarity index 95% rename from UI/src/org/dmfs/webcal/fragments/GenericListFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/GenericListFragment.java index 4fd7dd9..b88f71e 100644 --- a/UI/src/org/dmfs/webcal/fragments/GenericListFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/GenericListFragment.java @@ -21,11 +21,11 @@ import org.dmfs.android.calendarcontent.provider.CalendarContentContract.ContentItem; import org.dmfs.android.calendarcontent.provider.CalendarContentContract.SubscribedCalendars; import org.dmfs.android.retentionmagic.annotations.Parameter; +import org.dmfs.webcal.ActionBarActivity; import org.dmfs.webcal.R; import org.dmfs.webcal.adapters.MixedNavigationAdapter; import org.dmfs.webcal.fragments.CategoriesListFragment.CategoryNavigator; -import android.app.ActionBar; import android.app.Activity; import android.database.Cursor; import android.net.Uri; @@ -34,6 +34,7 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v7.app.ActionBar; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -49,25 +50,22 @@ *

* TODO: the synced calendars in "My Calendars" use a different id column. We need a better way to deal with that. *

- * + * * @author Marten Gajda */ public class GenericListFragment extends ActionBarFragment implements OnItemClickListener, LoaderCallbacks { - private static final String TAG = "GenericListFragment"; public static final String ARG_URI = "uri"; public static final String ARG_TITLE = "title"; public static final String ARG_EMPTY_MESSAGE = "empty_message"; public static final String ARG_PROJECTION = "projection"; public static final String ARG_SHOW_STARS = "show_stars"; - public final static String[] PROJECTION = new String[] { CalendarContentContract.ContentItem._ID, CalendarContentContract.SubscribedCalendars.CALENDAR_NAME, CalendarContentContract.ContentItem.TYPE, CalendarContentContract.ContentItem.ICON_ID, ContentItem.SEASON, ContentItem.STARRED, CalendarContentContract.SubscribedCalendars.ITEM_ID }; - public final static String[] PROJECTION2 = new String[] { CalendarContentContract.ContentItem._ID, CalendarContentContract.ContentItem.TITLE, CalendarContentContract.ContentItem.TYPE, CalendarContentContract.ContentItem.ICON_ID, ContentItem.SEASON, ContentItem.STARRED }; - + private static final String TAG = "GenericListFragment"; @Parameter(key = ARG_URI) private Uri mUri; @@ -132,7 +130,6 @@ public void onResume() { mListView.setSelectionFromTop(mFirstItem, mPosFromTop); } - setupActionBar(); } @@ -148,6 +145,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(this); + setupActionBar(result); + FragmentActivity activity = getActivity(); /* @@ -237,16 +236,14 @@ else if (CalendarContentContract.ContentItem.TYPE_CALENDAR.equals(itemType)) @Override - public void setupActionBar() + public void setupActionBar(View view) { if (getParentFragment() == null) // the topmost fragment owns the action bar { - ActionBar ab = getActivity().getActionBar(); - ab.removeAllTabs(); - ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - FragmentActivity activity = getActivity(); + ActionBar ab = ((ActionBarActivity) getActivity()).getSupportActionBar(); + ActionBarActivity activity = (ActionBarActivity) getActivity(); activity.setTitle(mTitle); - activity.getActionBar().setTitle(mTitle); + ab.setTitle(mTitle); } } diff --git a/UI/src/org/dmfs/webcal/fragments/InputTextDialogFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/InputTextDialogFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/InputTextDialogFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/InputTextDialogFragment.java index 1c32ae5..37a0a74 100644 --- a/UI/src/org/dmfs/webcal/fragments/InputTextDialogFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/InputTextDialogFragment.java @@ -40,7 +40,7 @@ /** * A simple prompt for text input. - * + * * @author Marten Gajda */ public class InputTextDialogFragment extends SupportDialogFragment implements OnEditorActionListener @@ -48,24 +48,21 @@ public class InputTextDialogFragment extends SupportDialogFragment implements On private final static String ARG_TITLE_ID = "title_id"; private final static String ARG_INITIAL_TEXT = "initial_text"; - - public interface OnTextInputListener - { - void onTextInput(String inputText); - } - @Parameter(key = ARG_TITLE_ID) private int mTitleId; - @Parameter(key = ARG_INITIAL_TEXT) private String mInitialText; - private EditText mEditText; + public InputTextDialogFragment() + { + } + + /** * Create a {@link InputTextDialogFragment} with the given title and initial text value. - * + * * @param titleId * The resource id of the title. * @param initalText @@ -83,11 +80,6 @@ public static InputTextDialogFragment newInstance(int titleId, String initalText } - public InputTextDialogFragment() - { - } - - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { @@ -176,4 +168,9 @@ else if (activity instanceof OnTextInputListener) return false; } + public interface OnTextInputListener + { + void onTextInput(String inputText); + } + } diff --git a/UI/src/org/dmfs/webcal/fragments/MessageDialogFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/MessageDialogFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/MessageDialogFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/MessageDialogFragment.java index d92c550..e2a5234 100644 --- a/UI/src/org/dmfs/webcal/fragments/MessageDialogFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/MessageDialogFragment.java @@ -35,7 +35,7 @@ /** * A simple message dialog. - * + * * @author Marten Gajda */ public class MessageDialogFragment extends SupportDialogFragment @@ -51,9 +51,14 @@ public class MessageDialogFragment extends SupportDialogFragment private String mMessageText; + public MessageDialogFragment() + { + } + + /** * Create a {@link MessageDialogFragment} with the given title and message text value and show it. - * + * * @param manager * A {@link FragmentManager}. * @param titleId @@ -73,11 +78,6 @@ public static void show(FragmentManager manager, int titleId, String messageText } - public MessageDialogFragment() - { - } - - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { diff --git a/UI/src/org/dmfs/webcal/fragments/PagerFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/PagerFragment.java similarity index 68% rename from UI/src/org/dmfs/webcal/fragments/PagerFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/PagerFragment.java index 7ebef73..87f5984 100644 --- a/UI/src/org/dmfs/webcal/fragments/PagerFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/PagerFragment.java @@ -21,17 +21,15 @@ import org.dmfs.android.calendarcontent.provider.CalendarContentContract.ContentItem; import org.dmfs.android.retentionmagic.annotations.Parameter; import org.dmfs.android.retentionmagic.annotations.Retain; +import org.dmfs.webcal.ActionBarActivity; import org.dmfs.webcal.R; import org.dmfs.webcal.adapters.SectionsPagerAdapter; import org.dmfs.webcal.utils.BitmapUtils; import org.dmfs.webcal.utils.ImageProxy; import org.dmfs.webcal.utils.ImageProxy.ImageAvailableListener; +import org.dmfs.webcal.views.TabBarLayout; -import android.app.ActionBar; -import android.app.ActionBar.Tab; -import android.app.ActionBar.TabListener; import android.app.Activity; -import android.app.FragmentTransaction; import android.content.ContentUris; import android.content.Context; import android.content.SharedPreferences; @@ -46,7 +44,7 @@ import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; -import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -58,19 +56,17 @@ /** * A fragment that contains a pager to present the sections of a page item to the user. It takes a {@link Uri} or a page item id. - * + * * @author Marten Gajda */ -public class PagerFragment extends ActionBarFragment implements LoaderCallbacks, TabListener, OnPageChangeListener, OnSharedPreferenceChangeListener, - ImageAvailableListener +public class PagerFragment extends ActionBarFragment implements LoaderCallbacks, OnSharedPreferenceChangeListener, ImageAvailableListener { - private final static String TAG = "PagerFragment"; - - private final static String ARG_SECTIONS_URI = "uri"; /** * FIXME: we should not publish this internal field. */ public static final String ARG_PAGE_TITLE = "title"; + private final static String TAG = "PagerFragment"; + private final static String ARG_SECTIONS_URI = "uri"; private static final String ARG_PAGE_ICON = "icon"; private final static int ID_URL_LOADER = 0; @@ -91,7 +87,6 @@ public class PagerFragment extends ActionBarFragment implements LoaderCallbacks< /** * The id is used to store the selected tab for this page, don't remove it. */ - @SuppressWarnings("unused") private long mId; @Retain(permanent = true, classNS = TAG, instanceNSField = "mId", key = "selectedTab") @@ -99,10 +94,12 @@ public class PagerFragment extends ActionBarFragment implements LoaderCallbacks< private ProgressBar mProgressBar; + private TabBarLayout mTabLayout; + /** * Create a new {@link PagerFragment} for the given sections {@link Uri}. - * + * * @param sectionsUri * A {@link Uri} that points to the sections to show. * @param pageTitle @@ -125,7 +122,7 @@ public static PagerFragment newInstance(Uri sectionsUri, String pageTitle, long /** * Create a new {@link PagerFragment} for the given page id. - * + * * @param context * A {@link Context}. * @param pageId @@ -145,7 +142,8 @@ public static PagerFragment newInstance(Context context, long pageId, String pag @Override public void onCreate(Bundle savedInstanceState) { - // get the id before we call super.onCreate, because it's used to retrieve the id of the section to show first + // get the id before we call super.onCreate, because it's used to + // retrieve the id of the section to show first mId = ContentUris.parseId(mUri); super.onCreate(savedInstanceState); } @@ -162,7 +160,8 @@ public void onAttach(Activity activity) @Override public void onDetach() { - // avoid to get notifications for changes in the shared preferences that we caused ourselves (because the active section has been stored) + // avoid to get notifications for changes in the shared preferences that + // we caused ourselves (because the active section has been stored) Activity activity = getActivity(); activity.getSharedPreferences(activity.getPackageName() + "_preferences", 0).unregisterOnSharedPreferenceChangeListener(this); super.onDetach(); @@ -177,6 +176,17 @@ public void onStart() } + @Override + public void onStop() + { + if (mViewPager != null) + { + mSelectedTab = mViewPager.getCurrentItem(); + } + super.onStop(); + } + + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -184,33 +194,18 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mProgressBar = (ProgressBar) returnView.findViewById(android.R.id.progress); mMessageText = (TextView) returnView.findViewById(android.R.id.message); + mTabLayout = (TabBarLayout) returnView.findViewById(R.id.tab_bar); mAdapter = new SectionsPagerAdapter(getChildFragmentManager(), mIcon); mViewPager = (ViewPager) returnView.findViewById(R.id.pager); - mViewPager.setOnPageChangeListener(this); mViewPager.setAdapter(mAdapter); + setupActionBar(returnView); + // start loading the pages getLoaderManager().initLoader(ID_URL_LOADER, null, this); - // set the page title and clear the subtitle if any - ActionBar actionBar = getActivity().getActionBar(); - actionBar.setTitle(mTitle); - actionBar.setSubtitle(null); - - // load the icon and set it if we get any, otherwise insert a placeholder and set it later - Drawable icon = ImageProxy.getInstance(this.getActivity()).getImage(mIcon, this); - if (icon != null) - { - // we need to pre-scale the icon, apparently Android doesn't do that for us - actionBar.setIcon(BitmapUtils.scaleDrawable(getResources(), (BitmapDrawable) icon, 36, 36)); - } - else - { - actionBar.setIcon(new ColorDrawable(getResources().getColor(android.R.color.transparent))); - } - return returnView; } @@ -225,29 +220,45 @@ public Loader onCreateLoader(int id, Bundle extras) @Override public void onLoadFinished(Loader cursorLoader, Cursor cursor) { + // update adapter mAdapter.swapCursor(cursor); + if (cursor == null) { - // this indicates an error when loading the page, show an error message + // this indicates an error when loading the page, show an error + // message mMessageText.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.GONE); mViewPager.setVisibility(View.GONE); + mTabLayout.setVisibility(View.GONE); + } else if (cursor.getCount() > 0) { - // indicates the page has been loaded, hide progress indicator and show pager + // indicates the page has been loaded, hide progress indicator and + // show pager mMessageText.setVisibility(View.GONE); mProgressBar.setVisibility(View.GONE); mViewPager.setVisibility(View.VISIBLE); - setupActionBarTabs(); + mViewPager.setVisibility(View.VISIBLE); + + if (cursor.getCount() > 1) + { + mTabLayout.setVisibility(View.VISIBLE); + populateTabBar(); + + if (cursor.getCount() > mSelectedTab) + { + mViewPager.setCurrentItem(mSelectedTab); + } + + } } else { - // all pages must have at least one section, 0 results means we're still waiting for the page to load, show a progress indicator - Activity activity = getActivity(); + // all pages must have at least one section, 0 results means we're + // still waiting for the page to load, show a progress indicator mProgressBar.setVisibility(View.VISIBLE); - activity.getActionBar().removeAllTabs(); - activity.getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); } } @@ -256,6 +267,7 @@ else if (cursor.getCount() > 0) public void onLoaderReset(Loader cursorLoader) { mAdapter.swapCursor(null); + mViewPager.invalidate(); } @@ -265,126 +277,50 @@ public void imageAvailable(long mIconId, Drawable drawable) if (isAdded()) { // the image has been loaded, scale it and update the ActionBar - getActivity().getActionBar().setIcon(BitmapUtils.scaleDrawable(getResources(), (BitmapDrawable) drawable, 36, 36)); + ((ActionBarActivity) getActivity()).getSupportActionBar().setIcon(BitmapUtils.scaleDrawable(getResources(), (BitmapDrawable) drawable, 36, 36)); } } @Override - public void setupActionBar() + public void setupActionBar(View view) { - if (mAdapter != null) - { - setupActionBarTabs(); - } - } - - - /** - * Configures the tabs on the action bar. - */ - private void setupActionBarTabs() - { - ActionBar actionBar = getActivity().getActionBar(); - - int tabCount = actionBar.getTabCount(); - int pageCount = mAdapter.getCount(); - - // replace titles and listeners of existing tabs - int i = 0; - for (; i < tabCount && i < pageCount; ++i) - { - final Tab tab = actionBar.getTabAt(i); - tab.setText(mAdapter.getPageTitle(i)); - tab.setTabListener(this); - } - - // add missing tabs - for (; i < pageCount; ++i) - { - actionBar.addTab(actionBar.newTab().setText(mAdapter.getPageTitle(i)).setTabListener(this)); - } - - // remove remaining tabs - for (; i < tabCount; --tabCount) - { - actionBar.removeTabAt(i); - } - - if (pageCount > 1) - { - int selection = mSelectedTab; - // changing the navigation mode might trigger a call to onTabSelected overriding mSelectedTab with a wrong value, so save it - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - mSelectedTab = selection; - if (selection < pageCount) - { - mViewPager.setCurrentItem(selection, false); - } - } - else - { - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - } - - - @Override - public void onTabReselected(Tab arg0, FragmentTransaction arg1) - { - // nothing to do - } + // set the page title and clear the subtitle if any + Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar); + toolbar.setTitle(mTitle); + toolbar.setSubtitle(null); - @Override - public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) - { - mSelectedTab = tab.getPosition(); - if (mSelectedTab != mViewPager.getCurrentItem()) - { - mViewPager.setCurrentItem(tab.getPosition()); - } - } + // we are disabling the icon for now, as this better matches the material design + // displayToolbarIcon(toolbar); - - @Override - public void onTabUnselected(Tab arg0, FragmentTransaction arg1) - { - // nothing to do } - @Override - public void onPageSelected(int position) + private void displayToolbarIcon(Toolbar toolbar) { - Activity activity = getActivity(); - if (activity == null) + // load the icon and set it if we get any, otherwise insert a + // placeholder and set it later + Drawable icon = ImageProxy.getInstance(this.getActivity()).getImage(mIcon, this); + if (icon != null) { - // nothing to do - return; + // we need to pre-scale the icon, apparently Android doesn't do that + // for us + toolbar.setLogo(BitmapUtils.scaleDrawable(getResources(), (BitmapDrawable) icon, 36, 36)); } - - ActionBar actionBar = activity.getActionBar(); - - if (actionBar != null && position != actionBar.getSelectedNavigationIndex()) + else { - mSelectedTab = position; - actionBar.setSelectedNavigationItem(position); + toolbar.setLogo(new ColorDrawable(getResources().getColor(android.R.color.transparent))); } - } - - @Override - public void onPageScrollStateChanged(int arg0) - { - // nothing to do } - @Override - public void onPageScrolled(int arg0, float arg1, int arg2) + private void populateTabBar() { - // nothing to do + // Give the SlidingTabLayout the ViewPager, this must be done AFTER the ViewPager has had + // it's PagerAdapter set. + mTabLayout.setViewPager(mViewPager); } diff --git a/UI/src/org/dmfs/webcal/fragments/PreferencesFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/PreferencesFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/PreferencesFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/PreferencesFragment.java index 1150612..67901b0 100644 --- a/UI/src/org/dmfs/webcal/fragments/PreferencesFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/PreferencesFragment.java @@ -43,7 +43,29 @@ public class PreferencesFragment extends PreferenceFragment { private static final String TAG = "WebcalPrefsFragment"; + /** + * {@link OnPreferenceChangeListener} to update dependencies and summary of ListPreferences + */ + private final OnPreferenceChangeListener PrefUpdater = new OnPreferenceChangeListener() + { + public boolean onPreferenceChange(Preference preference, Object newValue) + { + if (ListPreference.class.isInstance(preference)) + { + ListPreference pref = (ListPreference) preference; + pref.setSummary(pref.getEntries()[pref.findIndexOfValue((String) newValue)]); + } + else if (EditTextPreference.class.isInstance(preference)) + { + EditTextPreference pref = (EditTextPreference) preference; + pref.setSummary((String) newValue); + } + + return true; + } + + }; private String[] mCountryNames; private String[] mCountryCodes; @@ -84,7 +106,7 @@ public void onCreate(Bundle savedInstanceState) /** * Build the country list and sort it by name. This method populates {@link #mCountryCodes} and {@link #mCountryNames}. - * + * * @throws UnsupportedEncodingException * @throws NotFoundException * @throws IOException @@ -139,30 +161,6 @@ private void getCountries() throws UnsupportedEncodingException, NotFoundExcepti } - /** - * {@link OnPreferenceChangeListener} to update dependencies and summary of ListPreferences - */ - private final OnPreferenceChangeListener PrefUpdater = new OnPreferenceChangeListener() - { - - public boolean onPreferenceChange(Preference preference, Object newValue) - { - if (ListPreference.class.isInstance(preference)) - { - ListPreference pref = (ListPreference) preference; - pref.setSummary(pref.getEntries()[pref.findIndexOfValue((String) newValue)]); - } - else if (EditTextPreference.class.isInstance(preference)) - { - EditTextPreference pref = (EditTextPreference) preference; - pref.setSummary((String) newValue); - } - - return true; - } - - }; - private static class Country implements Comparable { final String name; diff --git a/UI/src/org/dmfs/webcal/fragments/PurchaseDialogFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/PurchaseDialogFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/PurchaseDialogFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/PurchaseDialogFragment.java index d30a37f..b845c82 100644 --- a/UI/src/org/dmfs/webcal/fragments/PurchaseDialogFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/PurchaseDialogFragment.java @@ -40,7 +40,7 @@ * This dialog only presents the user with an option to purchase, it doesn't launch the actual purchase flow. That's left to the listener when * {@link OnPurchaseListener#onPurchase(boolean)} is called. *

- * + * * @author Marten Gajda */ public class PurchaseDialogFragment extends SupportDialogFragment implements OnClickListener @@ -48,35 +48,18 @@ public class PurchaseDialogFragment extends SupportDialogFragment implements OnC private final static String ARG_ENABLE_FREE_TRIAL = "enableFreeTrial"; private final static String ARG_PRICE = "price"; - - /** - * A listener for purchase events. - */ - public interface OnPurchaseListener - { - - /** - * Called when the user hits the button to purchase or to take the free trial. - * - * @param freeTrial - * If the user has chosen to take the free trial. - */ - public void onPurchase(boolean freeTrial); - } - @Parameter(key = ARG_ENABLE_FREE_TRIAL) private boolean mEnableFreeTrial; - @Parameter(key = ARG_PRICE) private String mPrice; /** * Create a {@link PurchaseDialogFragment}. - * + * * @param enableFreeTrial * Whether to allow to take a free trial. - * + * * @param price * The price of the product. * @return A new {@link PurchaseDialogFragment}. @@ -153,7 +136,7 @@ else if (id == R.id.cancel_button) /** * Notifies the parent Fragment or Activity (which ever implements {@link OnPurchaseListener}) about the purchase. - * + * * @param freeTrial * Indicates that the user has chosen the free trial. */ @@ -177,4 +160,19 @@ else if (parentActivity instanceof OnPurchaseListener) listener.onPurchase(freeTrial); } } + + /** + * A listener for purchase events. + */ + public interface OnPurchaseListener + { + + /** + * Called when the user hits the button to purchase or to take the free trial. + * + * @param freeTrial + * If the user has chosen to take the free trial. + */ + public void onPurchase(boolean freeTrial); + } } diff --git a/UI/src/org/dmfs/webcal/fragments/SubscribeableItemFragment.java b/UI/src/main/java/org/dmfs/webcal/fragments/SubscribeableItemFragment.java similarity index 99% rename from UI/src/org/dmfs/webcal/fragments/SubscribeableItemFragment.java rename to UI/src/main/java/org/dmfs/webcal/fragments/SubscribeableItemFragment.java index adca954..a7de5c9 100644 --- a/UI/src/org/dmfs/webcal/fragments/SubscribeableItemFragment.java +++ b/UI/src/main/java/org/dmfs/webcal/fragments/SubscribeableItemFragment.java @@ -52,7 +52,7 @@ /** * A Fragment that shows a header to initiate the subscription flow. It's a wrapper for another fragment that doesn't need to care about payments & stuff. - * + * * @author Marten Gajda */ public abstract class SubscribeableItemFragment extends SupportFragment implements OnClickListener, OnInventoryListener, OnIabPurchaseFinishedListener, @@ -75,9 +75,6 @@ public abstract class SubscribeableItemFragment extends SupportFragment implemen private Place mWaitingForInventory = new Place(1); private Place mWaitingForPaymentStatus = new Place(1); private Place mWaitingForUpdateView = new Place(); - - private boolean mIsPurchased = false; - /** * This {@link Transition} is fired when the inventory has been updated. */ @@ -99,7 +96,15 @@ protected void execute(Inventory inventory) } } }; - + private Transition mHandleOnCreateView = new Transition(1, mWaitingForUpdateView) + { + @Override + protected void execute(Void param) + { + // nothing to do + } + }; + private boolean mIsPurchased = false; /** * This {@link Transition} is fired when the payment status has been loaded from the SDK. */ @@ -135,16 +140,6 @@ protected void execute(Cursor cursor) onPaymentStatusChange(); } }; - - private Transition mHandleOnCreateView = new Transition(1, mWaitingForUpdateView) - { - @Override - protected void execute(Void param) - { - // nothing to do - } - }; - private Transition mHandleUpdateView = new Transition(3, mWaitingForUpdateView, 2, mWaitingForUpdateView) { @Override @@ -176,6 +171,39 @@ protected void execute(Void param) private PetriNet mPetriNet = new PetriNet(mInventoryUpdated, mPaymentStatusUpdated, mHandleOnCreateView, mHandleUpdateView); + /** + * Remove parts from the product title we don't want to present to the user, like the app title. The Google service dialog will show them for us. + * + * @param productTitle + * The raw product title as returned by Google. + * @return The sanitized product title. + */ + private static String sanitizeGoogleProductTitle(String productTitle) + { + if (productTitle != null) + { + // remove any white space, just in case ... + productTitle = productTitle.trim(); + + if (productTitle.startsWith("Sync ")) + { + productTitle = productTitle.substring(5); + } + + // remove "()" at the end of the product title, Google adds it automatically but we don't want to show it + if (productTitle.endsWith(")")) + { + int idx = productTitle.lastIndexOf("("); + if (idx > 0) + { + productTitle = productTitle.substring(0, idx).trim(); + } + } + } + return productTitle; + } + + @Override public void onAttach(final Activity activity) { @@ -236,7 +264,7 @@ public void onResume() // we need this to update the UI if the free trial expired between onPause and onResume mHandler.post(mTrialButtonUpdater); - } + }; @Override @@ -244,7 +272,7 @@ public void onPause() { super.onPause(); mHandler.removeCallbacks(mTrialButtonUpdater); - }; + } @Override @@ -394,6 +422,31 @@ else if (show && v != null && v.getVisibility() != View.VISIBLE) } } + + /** + * Replace the unlock button by a buy button or vice versa. + * + * @param showBuyNow + * true to show the buy button. + */ + private void swapButtons(boolean showBuyNow) + { + mUnlockButton.setVisibility(showBuyNow ? View.GONE : View.VISIBLE); + mBuyButton.setVisibility(showBuyNow ? View.VISIBLE : View.GONE); + } + + + public abstract void onPaymentStatusChange(); + + + public abstract void onPurchase(boolean success, boolean freeTrial); + + + public abstract String getItemTitle(); + + + public abstract String getGoogleSubscriptionId(); + private final Runnable mTrialButtonUpdater = new Runnable() { @Override @@ -435,61 +488,4 @@ else if (mTrialExpiryTime > now) } }; - - /** - * Replace the unlock button by a buy button or vice versa. - * - * @param showBuyNow - * true to show the buy button. - */ - private void swapButtons(boolean showBuyNow) - { - mUnlockButton.setVisibility(showBuyNow ? View.GONE : View.VISIBLE); - mBuyButton.setVisibility(showBuyNow ? View.VISIBLE : View.GONE); - } - - - /** - * Remove parts from the product title we don't want to present to the user, like the app title. The Google service dialog will show them for us. - * - * @param productTitle - * The raw product title as returned by Google. - * @return The sanitized product title. - */ - private static String sanitizeGoogleProductTitle(String productTitle) - { - if (productTitle != null) - { - // remove any white space, just in case ... - productTitle = productTitle.trim(); - - if (productTitle.startsWith("Sync ")) - { - productTitle = productTitle.substring(5); - } - - // remove "()" at the end of the product title, Google adds it automatically but we don't want to show it - if (productTitle.endsWith(")")) - { - int idx = productTitle.lastIndexOf("("); - if (idx > 0) - { - productTitle = productTitle.substring(0, idx).trim(); - } - } - } - return productTitle; - } - - - public abstract void onPaymentStatusChange(); - - - public abstract void onPurchase(boolean success, boolean freeTrial); - - - public abstract String getItemTitle(); - - - public abstract String getGoogleSubscriptionId(); -} \ No newline at end of file +} diff --git a/UI/src/org/dmfs/webcal/push/PushHelperService.java b/UI/src/main/java/org/dmfs/webcal/push/PushHelperService.java similarity index 100% rename from UI/src/org/dmfs/webcal/push/PushHelperService.java rename to UI/src/main/java/org/dmfs/webcal/push/PushHelperService.java diff --git a/UI/src/org/dmfs/webcal/push/PushReceiver.java b/UI/src/main/java/org/dmfs/webcal/push/PushReceiver.java similarity index 100% rename from UI/src/org/dmfs/webcal/push/PushReceiver.java rename to UI/src/main/java/org/dmfs/webcal/push/PushReceiver.java diff --git a/UI/src/org/dmfs/webcal/utils/BitmapUtils.java b/UI/src/main/java/org/dmfs/webcal/utils/BitmapUtils.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/BitmapUtils.java rename to UI/src/main/java/org/dmfs/webcal/utils/BitmapUtils.java diff --git a/UI/src/org/dmfs/webcal/utils/EmptyService.java b/UI/src/main/java/org/dmfs/webcal/utils/EmptyService.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/EmptyService.java rename to UI/src/main/java/org/dmfs/webcal/utils/EmptyService.java diff --git a/UI/src/org/dmfs/webcal/utils/Event.java b/UI/src/main/java/org/dmfs/webcal/utils/Event.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/Event.java rename to UI/src/main/java/org/dmfs/webcal/utils/Event.java diff --git a/UI/src/org/dmfs/webcal/utils/ExpandAnimation.java b/UI/src/main/java/org/dmfs/webcal/utils/ExpandAnimation.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/ExpandAnimation.java rename to UI/src/main/java/org/dmfs/webcal/utils/ExpandAnimation.java diff --git a/UI/src/org/dmfs/webcal/utils/ImageLoaderQueue.java b/UI/src/main/java/org/dmfs/webcal/utils/ImageLoaderQueue.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/ImageLoaderQueue.java rename to UI/src/main/java/org/dmfs/webcal/utils/ImageLoaderQueue.java diff --git a/UI/src/org/dmfs/webcal/utils/ImageProxy.java b/UI/src/main/java/org/dmfs/webcal/utils/ImageProxy.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/ImageProxy.java rename to UI/src/main/java/org/dmfs/webcal/utils/ImageProxy.java diff --git a/UI/src/org/dmfs/webcal/utils/ProtectedBackgroundJob.java b/UI/src/main/java/org/dmfs/webcal/utils/ProtectedBackgroundJob.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/ProtectedBackgroundJob.java rename to UI/src/main/java/org/dmfs/webcal/utils/ProtectedBackgroundJob.java diff --git a/UI/src/org/dmfs/webcal/utils/PurchasedItemCache.java b/UI/src/main/java/org/dmfs/webcal/utils/PurchasedItemCache.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/PurchasedItemCache.java rename to UI/src/main/java/org/dmfs/webcal/utils/PurchasedItemCache.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/Base64.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/Base64.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/Base64.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/Base64.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/Base64DecoderException.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/Base64DecoderException.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/Base64DecoderException.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/Base64DecoderException.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/IabException.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/IabException.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/IabException.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/IabException.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/IabHelper.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/IabHelper.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/IabHelper.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/IabHelper.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/IabResult.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/IabResult.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/IabResult.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/IabResult.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/Inventory.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/Inventory.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/Inventory.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/Inventory.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/Purchase.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/Purchase.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/Purchase.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/Purchase.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/Security.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/Security.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/Security.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/Security.java diff --git a/UI/src/org/dmfs/webcal/utils/billing/SkuDetails.java b/UI/src/main/java/org/dmfs/webcal/utils/billing/SkuDetails.java similarity index 100% rename from UI/src/org/dmfs/webcal/utils/billing/SkuDetails.java rename to UI/src/main/java/org/dmfs/webcal/utils/billing/SkuDetails.java diff --git a/UI/src/org/dmfs/webcal/views/RemoteImageView.java b/UI/src/main/java/org/dmfs/webcal/views/RemoteImageView.java similarity index 100% rename from UI/src/org/dmfs/webcal/views/RemoteImageView.java rename to UI/src/main/java/org/dmfs/webcal/views/RemoteImageView.java diff --git a/UI/src/main/java/org/dmfs/webcal/views/TabBar.java b/UI/src/main/java/org/dmfs/webcal/views/TabBar.java new file mode 100644 index 0000000..a4ee68d --- /dev/null +++ b/UI/src/main/java/org/dmfs/webcal/views/TabBar.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2014 SchedJoules + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dmfs.webcal.views; + +import org.dmfs.webcal.R; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.widget.LinearLayout; + + +public class TabBar extends LinearLayout +{ + private static final int BOTTOM_DIVIDER_HEIGHT = 0; + private static final byte BOTTOM_DIVIDER_TRANSPARENCY = 0x26; + private static final int INDICATOR_HEIGHT = 3; + private static final int DIVIDER_WIDTH = 8; + private static final byte DIVIDER_TRANSPARENCY = 0x20; + private static final float DIVIDER_HEIGHT = 0; + + private final int mBottomDividerHeight; + private final Paint mBottomDividerPaint; + + private final int mSelectedIndicatorThickness; + private final Paint mSelectedIndicatorPaint; + + private final int mBottomDividerColor; + + private final Paint mDividerPaint; + private final float mDividerHeight; + + private int mSelectedPosition; + private float mSelectionOffset; + + private final ColorizerImpl mColorizer; + + + TabBar(Context context) + { + this(context, null); + } + + + TabBar(Context context, AttributeSet attrs) + { + super(context, attrs); + setWillNotDraw(false); + + final float density = getResources().getDisplayMetrics().density; + + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(R.attr.color, outValue, true); + final int themeColorPrimary = outValue.data; + + context.getTheme().resolveAttribute(R.attr.colorAccent, outValue, true); + final int themeColorAccent = outValue.data; + + mBottomDividerColor = setColorAlpha(themeColorPrimary, BOTTOM_DIVIDER_TRANSPARENCY); + + mColorizer = new ColorizerImpl(); + mColorizer.setIndicatorColors(themeColorAccent); + mColorizer.setDividerColors(setColorAlpha(themeColorAccent, DIVIDER_TRANSPARENCY)); + + mBottomDividerHeight = (int) (BOTTOM_DIVIDER_HEIGHT * density); + mBottomDividerPaint = new Paint(); + mBottomDividerPaint.setColor(mBottomDividerColor); + + mSelectedIndicatorThickness = (int) (INDICATOR_HEIGHT * density); + mSelectedIndicatorPaint = new Paint(); + + mDividerHeight = DIVIDER_HEIGHT; + mDividerPaint = new Paint(); + mDividerPaint.setStrokeWidth((int) (DIVIDER_WIDTH * density)); + } + + + void setSelectedIndicatorColors(int... colors) + { + mColorizer.setIndicatorColors(colors); + invalidate(); + } + + + void setDividerColors(int... colors) + { + mColorizer.setDividerColors(colors); + invalidate(); + } + + + void onViewPagerPageChanged(int position, float positionOffset) + { + mSelectedPosition = position; + mSelectionOffset = positionOffset; + invalidate(); + } + + + @Override + protected void onDraw(Canvas canvas) + { + final int height = getHeight(); + final int childCount = getChildCount(); + final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height); + + // Thick colored underline below the current selection + if (childCount > 0) + { + View selectedTitle = getChildAt(mSelectedPosition); + int left = selectedTitle.getLeft(); + int right = selectedTitle.getRight(); + int color = mColorizer.getIndicatorColor(mSelectedPosition); + + if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) + { + int nextColor = mColorizer.getIndicatorColor(mSelectedPosition + 1); + if (color != nextColor) + { + color = blendColors(nextColor, color, mSelectionOffset); + } + + // Draw the selection partway between the tabs + View nextTitle = getChildAt(mSelectedPosition + 1); + left = (int) (mSelectionOffset * nextTitle.getLeft() + (1.0f - mSelectionOffset) * left); + right = (int) (mSelectionOffset * nextTitle.getRight() + (1.0f - mSelectionOffset) * right); + } + + mSelectedIndicatorPaint.setColor(color); + + canvas.drawRect(left, height - mSelectedIndicatorThickness, right, height, mSelectedIndicatorPaint); + } + + // Thin underline along the entire bottom edge + canvas.drawRect(0, height - mBottomDividerHeight, getWidth(), height, mBottomDividerPaint); + + // Vertical separators between the titles && set title alpha + int separatorTop = (height - dividerHeightPx) / 2; + for (int i = 0; i < childCount; i++) + { + View child = getChildAt(i); + + if (child == getChildAt(mSelectedPosition) && mSelectionOffset == 0) + { + child.setAlpha(1); + } + else + { + child.setAlpha(0.6f); + } + + // don't draw separator for the last element + if (i != childCount - 1) + { + mDividerPaint.setColor(mColorizer.getDividerColor(i)); + canvas.drawLine(child.getRight(), separatorTop, child.getRight(), separatorTop + dividerHeightPx, mDividerPaint); + } + + } + } + + + /** + * Set the alpha value of the {@code color} to be the given {@code alpha} value. + */ + private static int setColorAlpha(int color, byte alpha) + { + return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); + } + + + /** + * Blend {@code color1} and {@code color2} using the given ratio. + * + * @param ratio + * of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 0.0 will return {@code color2}. + */ + private static int blendColors(int color1, int color2, float ratio) + { + final float inverseRation = 1f - ratio; + float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); + float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); + float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); + return Color.rgb((int) r, (int) g, (int) b); + } + + private static class ColorizerImpl implements TabBarLayout.Colorizer + { + private int[] mIndicatorColors; + private int[] mDividerColors; + + + @Override + public final int getIndicatorColor(int position) + { + return mIndicatorColors[position % mIndicatorColors.length]; + } + + + @Override + public final int getDividerColor(int position) + { + return mDividerColors[position % mDividerColors.length]; + } + + + void setIndicatorColors(int... colors) + { + mIndicatorColors = colors; + } + + + void setDividerColors(int... colors) + { + mDividerColors = colors; + } + } + +} diff --git a/UI/src/main/java/org/dmfs/webcal/views/TabBarLayout.java b/UI/src/main/java/org/dmfs/webcal/views/TabBarLayout.java new file mode 100644 index 0000000..9ffde84 --- /dev/null +++ b/UI/src/main/java/org/dmfs/webcal/views/TabBarLayout.java @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2014 SchedJoules + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dmfs.webcal.views; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Build; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; +import android.widget.TextView; + + +public class TabBarLayout extends HorizontalScrollView +{ + + private static final int LABEL_MARGIN_LEFT = 24; + private static final int TAB_PADDING = 16; + private static final int LABEL_TEXT_SIZE = 12; + + private int mLabelMarginLeft; + private TabBar mTabBar; + + private int mTabViewLayoutId; + private int mTabViewTextViewId; + + private ViewPager mViewPager; + private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; + private boolean mDistributeEvenly = true; + private SparseArray mContentDescriptions = new SparseArray(); + + + public TabBarLayout(Context context) + { + this(context, null); + } + + + public TabBarLayout(Context context, AttributeSet attrs) + { + this(context, attrs, 0); + } + + + public TabBarLayout(Context context, AttributeSet attrs, int defStyle) + { + super(context, attrs, defStyle); + + setFillViewport(true); + setHorizontalScrollBarEnabled(false); + + mLabelMarginLeft = (int) (LABEL_MARGIN_LEFT * getResources().getDisplayMetrics().density); + + mTabBar = new TabBar(context); + addView(mTabBar, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + } + + + /** + * Sets the colors to be used for indicating the selected tab. These colors are treated as a circular array. Providing one color will mean that all tabs are + * indicated with the same color. + */ + public void setSelectedIndicatorColors(int... colors) + { + mTabBar.setSelectedIndicatorColors(colors); + } + + + /** + * Sets the colors to be used for tab dividers. These colors are treated as a circular array. Providing one color will mean that all tabs are indicated with + * the same color. + */ + public void setDividerColors(int... colors) + { + mTabBar.setDividerColors(colors); + } + + + /** + * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are required to set any {@link ViewPager.OnPageChangeListener} + * through this method. This is so that the layout can update it's scroll position correctly. + * + * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) + */ + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) + { + mViewPagerPageChangeListener = listener; + } + + + /** + * Set the custom layout to be inflated for the tab views. + * + * @param layoutResId + * Layout id to be inflated + * @param textViewId + * id of the {@link android.widget.TextView} in the inflated view + */ + public void setCustomTabView(int layoutResId, int textViewId) + { + mTabViewLayoutId = layoutResId; + mTabViewTextViewId = textViewId; + } + + + /** + * Sets the associated view pager. Note that the assumption here is that the pager content (number of tabs and tab titles) does not change after this call + * has been made. + */ + public void setViewPager(ViewPager viewPager) + { + mTabBar.removeAllViews(); + + mViewPager = viewPager; + if (viewPager != null) + { + viewPager.setOnPageChangeListener(new InternalViewPagerListener()); + populateTabStrip(); + } + } + + + /** + * Create a default view to be used for tabs. This is called if a custom tab view is not set via {@link #setCustomTabView(int, int)}. + */ + protected TextView createDefaultTabView(Context context) + { + TextView textView = new TextView(context); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, LABEL_TEXT_SIZE); + textView.setTypeface(Typeface.DEFAULT_BOLD); + textView.setTextColor(Color.WHITE); + textView.setSingleLine(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + { + // If we're running on Honeycomb or newer, then we can use the Theme's + // selectableItemBackground to ensure that the View has a pressed state + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true); + textView.setBackgroundResource(outValue.resourceId); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) + { + // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style + textView.setAllCaps(true); + } + + int padding = (int) (TAB_PADDING * getResources().getDisplayMetrics().density); + textView.setPadding(padding, padding, padding, padding); + + return textView; + } + + + private void populateTabStrip() + { + + final PagerAdapter adapter = mViewPager.getAdapter(); + final View.OnClickListener tabClickListener = new TabClickListener(); + int count = adapter.getCount(); + if (count == 0) + { + setVisibility(View.GONE); + } + else + { + setVisibility(View.VISIBLE); + } + + for (int i = 0; i < count; i++) + { + View tabView = null; + TextView tabTitleView = null; + if (mTabViewLayoutId != 0) + { + // If there is a custom tab view layout id set, try and inflate it + tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabBar, false); + tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId); + } + if (tabView == null) + { + tabView = createDefaultTabView(getContext()); + } + if (tabTitleView == null && TextView.class.isInstance(tabView)) + { + tabTitleView = (TextView) tabView; + } + + tabTitleView.setText(adapter.getPageTitle(i)); + tabView.setOnClickListener(tabClickListener); + String desc = mContentDescriptions.get(i, null); + if (desc != null) + { + tabView.setContentDescription(desc); + } + mTabBar.addView(tabView); + + if (mDistributeEvenly) + { + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); + if (lp != null) + { + lp.weight = 1; + } + + } + } + } + + + public void notifyDataSetChanged() + { + populateTabStrip(); + + } + + + @Override + protected void onAttachedToWindow() + { + super.onAttachedToWindow(); + + if (mViewPager != null) + { + scrollToTab(mViewPager.getCurrentItem(), 0); + } + } + + + private void scrollToTab(int tabIndex, int positionOffset) + { + final int tabStripChildCount = mTabBar.getChildCount(); + if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) + { + return; + } + + View selectedChild = mTabBar.getChildAt(tabIndex); + if (selectedChild != null) + { + int targetScrollX = selectedChild.getLeft() + positionOffset; + + if (tabIndex > 0 || positionOffset > 0) + { + // If we're not at the first child and are mid-scroll, make sure we obey the offset + targetScrollX -= mLabelMarginLeft; + } + + scrollTo(targetScrollX, 0); + } + } + + public interface Colorizer + { + int getIndicatorColor(int position); + + + int getDividerColor(int position); + + } + + private class InternalViewPagerListener implements ViewPager.OnPageChangeListener + { + private int mScrollState; + + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) + { + int tabStripChildCount = mTabBar.getChildCount(); + if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) + { + return; + } + + mTabBar.onViewPagerPageChanged(position, positionOffset); + + View selectedTitle = mTabBar.getChildAt(position); + int extraOffset = (selectedTitle != null) ? (int) (positionOffset * selectedTitle.getWidth()) : 0; + scrollToTab(position, extraOffset); + + if (mViewPagerPageChangeListener != null) + { + mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + } + + + @Override + public void onPageScrollStateChanged(int state) + { + mScrollState = state; + + if (mViewPagerPageChangeListener != null) + { + mViewPagerPageChangeListener.onPageScrollStateChanged(state); + } + } + + + @Override + public void onPageSelected(int position) + { + if (mScrollState == ViewPager.SCROLL_STATE_IDLE) + { + mTabBar.onViewPagerPageChanged(position, 0f); + scrollToTab(position, 0); + } + + if (mViewPagerPageChangeListener != null) + { + mViewPagerPageChangeListener.onPageSelected(position); + } + } + + } + + private class TabClickListener implements View.OnClickListener + { + @Override + public void onClick(View v) + { + for (int i = 0; i < mTabBar.getChildCount(); i++) + { + if (v == mTabBar.getChildAt(i)) + { + mViewPager.setCurrentItem(i); + return; + } + } + } + } + +} diff --git a/UI/res/color/text_color_free_trial.xml b/UI/src/main/res/color/text_color_free_trial.xml similarity index 100% rename from UI/res/color/text_color_free_trial.xml rename to UI/src/main/res/color/text_color_free_trial.xml diff --git a/UI/res/drawable-hdpi/drawer_shadow.9.png b/UI/src/main/res/drawable-hdpi/drawer_shadow.9.png similarity index 100% rename from UI/res/drawable-hdpi/drawer_shadow.9.png rename to UI/src/main/res/drawable-hdpi/drawer_shadow.9.png diff --git a/UI/res/drawable-hdpi/ic_24_analytics_black50.png b/UI/src/main/res/drawable-hdpi/ic_24_analytics_black50.png similarity index 100% rename from UI/res/drawable-hdpi/ic_24_analytics_black50.png rename to UI/src/main/res/drawable-hdpi/ic_24_analytics_black50.png diff --git a/UI/res/drawable-hdpi/ic_24_country_black50.png b/UI/src/main/res/drawable-hdpi/ic_24_country_black50.png similarity index 100% rename from UI/res/drawable-hdpi/ic_24_country_black50.png rename to UI/src/main/res/drawable-hdpi/ic_24_country_black50.png diff --git a/UI/res/drawable-hdpi/ic_24_settings_white.png b/UI/src/main/res/drawable-hdpi/ic_24_settings_white.png similarity index 100% rename from UI/res/drawable-hdpi/ic_24_settings_white.png rename to UI/src/main/res/drawable-hdpi/ic_24_settings_white.png diff --git a/UI/res/drawable-hdpi/ic_action_new_event_dark.png b/UI/src/main/res/drawable-hdpi/ic_action_new_event_dark.png similarity index 100% rename from UI/res/drawable-hdpi/ic_action_new_event_dark.png rename to UI/src/main/res/drawable-hdpi/ic_action_new_event_dark.png diff --git a/UI/res/drawable-hdpi/ic_action_new_event_light.png b/UI/src/main/res/drawable-hdpi/ic_action_new_event_light.png similarity index 100% rename from UI/res/drawable-hdpi/ic_action_new_event_light.png rename to UI/src/main/res/drawable-hdpi/ic_action_new_event_light.png diff --git a/UI/res/drawable-hdpi/ic_action_settings_dark.png b/UI/src/main/res/drawable-hdpi/ic_action_settings_dark.png similarity index 100% rename from UI/res/drawable-hdpi/ic_action_settings_dark.png rename to UI/src/main/res/drawable-hdpi/ic_action_settings_dark.png diff --git a/UI/res/drawable-hdpi/ic_action_settings_light.png b/UI/src/main/res/drawable-hdpi/ic_action_settings_light.png similarity index 100% rename from UI/res/drawable-hdpi/ic_action_settings_light.png rename to UI/src/main/res/drawable-hdpi/ic_action_settings_light.png diff --git a/UI/res/drawable-hdpi/ic_allcalendars.png b/UI/src/main/res/drawable-hdpi/ic_allcalendars.png similarity index 100% rename from UI/res/drawable-hdpi/ic_allcalendars.png rename to UI/src/main/res/drawable-hdpi/ic_allcalendars.png diff --git a/UI/res/drawable-hdpi/ic_drawer.png b/UI/src/main/res/drawable-hdpi/ic_drawer.png similarity index 100% rename from UI/res/drawable-hdpi/ic_drawer.png rename to UI/src/main/res/drawable-hdpi/ic_drawer.png diff --git a/UI/res/drawable-hdpi/ic_faq.png b/UI/src/main/res/drawable-hdpi/ic_faq.png similarity index 100% rename from UI/res/drawable-hdpi/ic_faq.png rename to UI/src/main/res/drawable-hdpi/ic_faq.png diff --git a/UI/res/drawable-hdpi/ic_favouites.png b/UI/src/main/res/drawable-hdpi/ic_favouites.png similarity index 100% rename from UI/res/drawable-hdpi/ic_favouites.png rename to UI/src/main/res/drawable-hdpi/ic_favouites.png diff --git a/UI/res/drawable-hdpi/ic_feedback.png b/UI/src/main/res/drawable-hdpi/ic_feedback.png similarity index 100% rename from UI/res/drawable-hdpi/ic_feedback.png rename to UI/src/main/res/drawable-hdpi/ic_feedback.png diff --git a/UI/res/drawable-hdpi/ic_mycalendars.png b/UI/src/main/res/drawable-hdpi/ic_mycalendars.png similarity index 100% rename from UI/res/drawable-hdpi/ic_mycalendars.png rename to UI/src/main/res/drawable-hdpi/ic_mycalendars.png diff --git a/UI/res/drawable-hdpi/ic_settings.png b/UI/src/main/res/drawable-hdpi/ic_settings.png similarity index 100% rename from UI/res/drawable-hdpi/ic_settings.png rename to UI/src/main/res/drawable-hdpi/ic_settings.png diff --git a/UI/res/drawable-ldpi/ic_24_analytics_black50.png b/UI/src/main/res/drawable-ldpi/ic_24_analytics_black50.png similarity index 100% rename from UI/res/drawable-ldpi/ic_24_analytics_black50.png rename to UI/src/main/res/drawable-ldpi/ic_24_analytics_black50.png diff --git a/UI/res/drawable-ldpi/ic_24_country_black50.png b/UI/src/main/res/drawable-ldpi/ic_24_country_black50.png similarity index 100% rename from UI/res/drawable-ldpi/ic_24_country_black50.png rename to UI/src/main/res/drawable-ldpi/ic_24_country_black50.png diff --git a/UI/res/drawable-ldpi/ic_24_settings_white.png b/UI/src/main/res/drawable-ldpi/ic_24_settings_white.png similarity index 100% rename from UI/res/drawable-ldpi/ic_24_settings_white.png rename to UI/src/main/res/drawable-ldpi/ic_24_settings_white.png diff --git a/UI/res/drawable-mdpi/drawer_shadow.9.png b/UI/src/main/res/drawable-mdpi/drawer_shadow.9.png similarity index 100% rename from UI/res/drawable-mdpi/drawer_shadow.9.png rename to UI/src/main/res/drawable-mdpi/drawer_shadow.9.png diff --git a/UI/res/drawable-mdpi/ic_24_analytics_black50.png b/UI/src/main/res/drawable-mdpi/ic_24_analytics_black50.png similarity index 100% rename from UI/res/drawable-mdpi/ic_24_analytics_black50.png rename to UI/src/main/res/drawable-mdpi/ic_24_analytics_black50.png diff --git a/UI/res/drawable-mdpi/ic_24_country_black50.png b/UI/src/main/res/drawable-mdpi/ic_24_country_black50.png similarity index 100% rename from UI/res/drawable-mdpi/ic_24_country_black50.png rename to UI/src/main/res/drawable-mdpi/ic_24_country_black50.png diff --git a/UI/res/drawable-mdpi/ic_24_settings_white.png b/UI/src/main/res/drawable-mdpi/ic_24_settings_white.png similarity index 100% rename from UI/res/drawable-mdpi/ic_24_settings_white.png rename to UI/src/main/res/drawable-mdpi/ic_24_settings_white.png diff --git a/UI/res/drawable-mdpi/ic_action_new_event_dark.png b/UI/src/main/res/drawable-mdpi/ic_action_new_event_dark.png similarity index 100% rename from UI/res/drawable-mdpi/ic_action_new_event_dark.png rename to UI/src/main/res/drawable-mdpi/ic_action_new_event_dark.png diff --git a/UI/res/drawable-mdpi/ic_action_new_event_light.png b/UI/src/main/res/drawable-mdpi/ic_action_new_event_light.png similarity index 100% rename from UI/res/drawable-mdpi/ic_action_new_event_light.png rename to UI/src/main/res/drawable-mdpi/ic_action_new_event_light.png diff --git a/UI/res/drawable-mdpi/ic_action_settings_dark.png b/UI/src/main/res/drawable-mdpi/ic_action_settings_dark.png similarity index 100% rename from UI/res/drawable-mdpi/ic_action_settings_dark.png rename to UI/src/main/res/drawable-mdpi/ic_action_settings_dark.png diff --git a/UI/res/drawable-mdpi/ic_action_settings_light.png b/UI/src/main/res/drawable-mdpi/ic_action_settings_light.png similarity index 100% rename from UI/res/drawable-mdpi/ic_action_settings_light.png rename to UI/src/main/res/drawable-mdpi/ic_action_settings_light.png diff --git a/UI/res/drawable-mdpi/ic_allcalendars.png b/UI/src/main/res/drawable-mdpi/ic_allcalendars.png similarity index 100% rename from UI/res/drawable-mdpi/ic_allcalendars.png rename to UI/src/main/res/drawable-mdpi/ic_allcalendars.png diff --git a/UI/res/drawable-mdpi/ic_drawer.png b/UI/src/main/res/drawable-mdpi/ic_drawer.png similarity index 100% rename from UI/res/drawable-mdpi/ic_drawer.png rename to UI/src/main/res/drawable-mdpi/ic_drawer.png diff --git a/UI/res/drawable-mdpi/ic_faq.png b/UI/src/main/res/drawable-mdpi/ic_faq.png similarity index 100% rename from UI/res/drawable-mdpi/ic_faq.png rename to UI/src/main/res/drawable-mdpi/ic_faq.png diff --git a/UI/res/drawable-mdpi/ic_favouites.png b/UI/src/main/res/drawable-mdpi/ic_favouites.png similarity index 100% rename from UI/res/drawable-mdpi/ic_favouites.png rename to UI/src/main/res/drawable-mdpi/ic_favouites.png diff --git a/UI/res/drawable-mdpi/ic_feedback.png b/UI/src/main/res/drawable-mdpi/ic_feedback.png similarity index 100% rename from UI/res/drawable-mdpi/ic_feedback.png rename to UI/src/main/res/drawable-mdpi/ic_feedback.png diff --git a/UI/res/drawable-mdpi/ic_mycalendars.png b/UI/src/main/res/drawable-mdpi/ic_mycalendars.png similarity index 100% rename from UI/res/drawable-mdpi/ic_mycalendars.png rename to UI/src/main/res/drawable-mdpi/ic_mycalendars.png diff --git a/UI/res/drawable-mdpi/ic_settings.png b/UI/src/main/res/drawable-mdpi/ic_settings.png similarity index 100% rename from UI/res/drawable-mdpi/ic_settings.png rename to UI/src/main/res/drawable-mdpi/ic_settings.png diff --git a/UI/res/drawable-xhdpi/drawer_shadow.9.png b/UI/src/main/res/drawable-xhdpi/drawer_shadow.9.png similarity index 100% rename from UI/res/drawable-xhdpi/drawer_shadow.9.png rename to UI/src/main/res/drawable-xhdpi/drawer_shadow.9.png diff --git a/UI/res/drawable-xhdpi/ic_24_analytics_black50.png b/UI/src/main/res/drawable-xhdpi/ic_24_analytics_black50.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_24_analytics_black50.png rename to UI/src/main/res/drawable-xhdpi/ic_24_analytics_black50.png diff --git a/UI/res/drawable-xhdpi/ic_24_country_black50.png b/UI/src/main/res/drawable-xhdpi/ic_24_country_black50.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_24_country_black50.png rename to UI/src/main/res/drawable-xhdpi/ic_24_country_black50.png diff --git a/UI/res/drawable-xhdpi/ic_24_settings_white.png b/UI/src/main/res/drawable-xhdpi/ic_24_settings_white.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_24_settings_white.png rename to UI/src/main/res/drawable-xhdpi/ic_24_settings_white.png diff --git a/UI/res/drawable-xhdpi/ic_action_new_event_dark.png b/UI/src/main/res/drawable-xhdpi/ic_action_new_event_dark.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_action_new_event_dark.png rename to UI/src/main/res/drawable-xhdpi/ic_action_new_event_dark.png diff --git a/UI/res/drawable-xhdpi/ic_action_new_event_light.png b/UI/src/main/res/drawable-xhdpi/ic_action_new_event_light.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_action_new_event_light.png rename to UI/src/main/res/drawable-xhdpi/ic_action_new_event_light.png diff --git a/UI/res/drawable-xhdpi/ic_action_settings_dark.png b/UI/src/main/res/drawable-xhdpi/ic_action_settings_dark.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_action_settings_dark.png rename to UI/src/main/res/drawable-xhdpi/ic_action_settings_dark.png diff --git a/UI/res/drawable-xhdpi/ic_action_settings_light.png b/UI/src/main/res/drawable-xhdpi/ic_action_settings_light.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_action_settings_light.png rename to UI/src/main/res/drawable-xhdpi/ic_action_settings_light.png diff --git a/UI/res/drawable-xhdpi/ic_allcalendars.png b/UI/src/main/res/drawable-xhdpi/ic_allcalendars.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_allcalendars.png rename to UI/src/main/res/drawable-xhdpi/ic_allcalendars.png diff --git a/UI/res/drawable-xhdpi/ic_drawer.png b/UI/src/main/res/drawable-xhdpi/ic_drawer.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_drawer.png rename to UI/src/main/res/drawable-xhdpi/ic_drawer.png diff --git a/UI/res/drawable-xhdpi/ic_faq.png b/UI/src/main/res/drawable-xhdpi/ic_faq.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_faq.png rename to UI/src/main/res/drawable-xhdpi/ic_faq.png diff --git a/UI/res/drawable-xhdpi/ic_favouites.png b/UI/src/main/res/drawable-xhdpi/ic_favouites.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_favouites.png rename to UI/src/main/res/drawable-xhdpi/ic_favouites.png diff --git a/UI/res/drawable-xhdpi/ic_feedback.png b/UI/src/main/res/drawable-xhdpi/ic_feedback.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_feedback.png rename to UI/src/main/res/drawable-xhdpi/ic_feedback.png diff --git a/UI/res/drawable-xhdpi/ic_mycalendars.png b/UI/src/main/res/drawable-xhdpi/ic_mycalendars.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_mycalendars.png rename to UI/src/main/res/drawable-xhdpi/ic_mycalendars.png diff --git a/UI/res/drawable-xhdpi/ic_settings.png b/UI/src/main/res/drawable-xhdpi/ic_settings.png similarity index 100% rename from UI/res/drawable-xhdpi/ic_settings.png rename to UI/src/main/res/drawable-xhdpi/ic_settings.png diff --git a/UI/res/drawable-xxhdpi/ic_24_analytics_black50.png b/UI/src/main/res/drawable-xxhdpi/ic_24_analytics_black50.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_24_analytics_black50.png rename to UI/src/main/res/drawable-xxhdpi/ic_24_analytics_black50.png diff --git a/UI/res/drawable-xxhdpi/ic_24_country_black50.png b/UI/src/main/res/drawable-xxhdpi/ic_24_country_black50.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_24_country_black50.png rename to UI/src/main/res/drawable-xxhdpi/ic_24_country_black50.png diff --git a/UI/res/drawable-xxhdpi/ic_24_settings_white.png b/UI/src/main/res/drawable-xxhdpi/ic_24_settings_white.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_24_settings_white.png rename to UI/src/main/res/drawable-xxhdpi/ic_24_settings_white.png diff --git a/UI/res/drawable-xxhdpi/ic_action_new_event_dark.png b/UI/src/main/res/drawable-xxhdpi/ic_action_new_event_dark.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_action_new_event_dark.png rename to UI/src/main/res/drawable-xxhdpi/ic_action_new_event_dark.png diff --git a/UI/res/drawable-xxhdpi/ic_action_new_event_light.png b/UI/src/main/res/drawable-xxhdpi/ic_action_new_event_light.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_action_new_event_light.png rename to UI/src/main/res/drawable-xxhdpi/ic_action_new_event_light.png diff --git a/UI/res/drawable-xxhdpi/ic_action_settings_dark.png b/UI/src/main/res/drawable-xxhdpi/ic_action_settings_dark.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_action_settings_dark.png rename to UI/src/main/res/drawable-xxhdpi/ic_action_settings_dark.png diff --git a/UI/res/drawable-xxhdpi/ic_action_settings_light.png b/UI/src/main/res/drawable-xxhdpi/ic_action_settings_light.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_action_settings_light.png rename to UI/src/main/res/drawable-xxhdpi/ic_action_settings_light.png diff --git a/UI/res/drawable-xxhdpi/ic_allcalendars.png b/UI/src/main/res/drawable-xxhdpi/ic_allcalendars.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_allcalendars.png rename to UI/src/main/res/drawable-xxhdpi/ic_allcalendars.png diff --git a/UI/res/drawable-xxhdpi/ic_fa_star.png b/UI/src/main/res/drawable-xxhdpi/ic_fa_star.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_fa_star.png rename to UI/src/main/res/drawable-xxhdpi/ic_fa_star.png diff --git a/UI/res/drawable-xxhdpi/ic_fa_star_o.png b/UI/src/main/res/drawable-xxhdpi/ic_fa_star_o.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_fa_star_o.png rename to UI/src/main/res/drawable-xxhdpi/ic_fa_star_o.png diff --git a/UI/res/drawable-xxhdpi/ic_faq.png b/UI/src/main/res/drawable-xxhdpi/ic_faq.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_faq.png rename to UI/src/main/res/drawable-xxhdpi/ic_faq.png diff --git a/UI/res/drawable-xxhdpi/ic_favouites.png b/UI/src/main/res/drawable-xxhdpi/ic_favouites.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_favouites.png rename to UI/src/main/res/drawable-xxhdpi/ic_favouites.png diff --git a/UI/res/drawable-xxhdpi/ic_feedback.png b/UI/src/main/res/drawable-xxhdpi/ic_feedback.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_feedback.png rename to UI/src/main/res/drawable-xxhdpi/ic_feedback.png diff --git a/UI/res/drawable-xxhdpi/ic_mycalendars.png b/UI/src/main/res/drawable-xxhdpi/ic_mycalendars.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_mycalendars.png rename to UI/src/main/res/drawable-xxhdpi/ic_mycalendars.png diff --git a/UI/res/drawable-xxhdpi/ic_settings.png b/UI/src/main/res/drawable-xxhdpi/ic_settings.png similarity index 100% rename from UI/res/drawable-xxhdpi/ic_settings.png rename to UI/src/main/res/drawable-xxhdpi/ic_settings.png diff --git a/UI/res/drawable-xxxhdpi/ic_24_analytics_black50.png b/UI/src/main/res/drawable-xxxhdpi/ic_24_analytics_black50.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_24_analytics_black50.png rename to UI/src/main/res/drawable-xxxhdpi/ic_24_analytics_black50.png diff --git a/UI/res/drawable-xxxhdpi/ic_24_country_black50.png b/UI/src/main/res/drawable-xxxhdpi/ic_24_country_black50.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_24_country_black50.png rename to UI/src/main/res/drawable-xxxhdpi/ic_24_country_black50.png diff --git a/UI/res/drawable-xxxhdpi/ic_24_settings_white.png b/UI/src/main/res/drawable-xxxhdpi/ic_24_settings_white.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_24_settings_white.png rename to UI/src/main/res/drawable-xxxhdpi/ic_24_settings_white.png diff --git a/UI/res/drawable-xxxhdpi/ic_allcalendars.png b/UI/src/main/res/drawable-xxxhdpi/ic_allcalendars.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_allcalendars.png rename to UI/src/main/res/drawable-xxxhdpi/ic_allcalendars.png diff --git a/UI/res/drawable-xxxhdpi/ic_faq.png b/UI/src/main/res/drawable-xxxhdpi/ic_faq.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_faq.png rename to UI/src/main/res/drawable-xxxhdpi/ic_faq.png diff --git a/UI/res/drawable-xxxhdpi/ic_favouites.png b/UI/src/main/res/drawable-xxxhdpi/ic_favouites.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_favouites.png rename to UI/src/main/res/drawable-xxxhdpi/ic_favouites.png diff --git a/UI/res/drawable-xxxhdpi/ic_feedback.png b/UI/src/main/res/drawable-xxxhdpi/ic_feedback.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_feedback.png rename to UI/src/main/res/drawable-xxxhdpi/ic_feedback.png diff --git a/UI/res/drawable-xxxhdpi/ic_mycalendars.png b/UI/src/main/res/drawable-xxxhdpi/ic_mycalendars.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_mycalendars.png rename to UI/src/main/res/drawable-xxxhdpi/ic_mycalendars.png diff --git a/UI/res/drawable-xxxhdpi/ic_settings.png b/UI/src/main/res/drawable-xxxhdpi/ic_settings.png similarity index 100% rename from UI/res/drawable-xxxhdpi/ic_settings.png rename to UI/src/main/res/drawable-xxxhdpi/ic_settings.png diff --git a/UI/res/drawable/background_edittext.xml b/UI/src/main/res/drawable/background_edittext.xml similarity index 100% rename from UI/res/drawable/background_edittext.xml rename to UI/src/main/res/drawable/background_edittext.xml diff --git a/UI/res/drawable/background_edittext_active.xml b/UI/src/main/res/drawable/background_edittext_active.xml similarity index 93% rename from UI/res/drawable/background_edittext_active.xml rename to UI/src/main/res/drawable/background_edittext_active.xml index e358ae4..cbd9879 100644 --- a/UI/res/drawable/background_edittext_active.xml +++ b/UI/src/main/res/drawable/background_edittext_active.xml @@ -1,4 +1,4 @@ - + + + + + + + + + + + + + \ No newline at end of file diff --git a/UI/res/layout/activity_preferences.xml b/UI/src/main/res/layout/activity_preferences.xml similarity index 100% rename from UI/res/layout/activity_preferences.xml rename to UI/src/main/res/layout/activity_preferences.xml diff --git a/UI/res/layout/calendar_entry_item.xml b/UI/src/main/res/layout/calendar_entry_item.xml similarity index 67% rename from UI/res/layout/calendar_entry_item.xml rename to UI/src/main/res/layout/calendar_entry_item.xml index 70602b2..be25714 100644 --- a/UI/res/layout/calendar_entry_item.xml +++ b/UI/src/main/res/layout/calendar_entry_item.xml @@ -1,16 +1,17 @@ + android:background="@android:color/white"> + android:paddingLeft="16dp" + android:paddingRight="16dp"> @@ -43,31 +43,35 @@ android:layout_centerVertical="true" android:focusable="false" /> - + android:orientation="vertical"> - + + + + + + + \ No newline at end of file diff --git a/UI/res/layout/events_preview_list_item.xml b/UI/src/main/res/layout/events_preview_list_item.xml similarity index 100% rename from UI/res/layout/events_preview_list_item.xml rename to UI/src/main/res/layout/events_preview_list_item.xml diff --git a/UI/res/layout/events_preview_list_section_header.xml b/UI/src/main/res/layout/events_preview_list_section_header.xml similarity index 79% rename from UI/res/layout/events_preview_list_section_header.xml rename to UI/src/main/res/layout/events_preview_list_section_header.xml index 7d9d5a0..c96c3c1 100644 --- a/UI/res/layout/events_preview_list_section_header.xml +++ b/UI/src/main/res/layout/events_preview_list_section_header.xml @@ -2,9 +2,9 @@ + android:paddingRight="8dp"> + android:textColor="?attr/colorPrimary" /> \ No newline at end of file diff --git a/UI/src/main/res/layout/events_preview_list_section_header_flat.xml b/UI/src/main/res/layout/events_preview_list_section_header_flat.xml new file mode 100644 index 0000000..d7b74fc --- /dev/null +++ b/UI/src/main/res/layout/events_preview_list_section_header_flat.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/UI/res/layout/fragment_calendar_item.xml b/UI/src/main/res/layout/fragment_calendar_item.xml similarity index 58% rename from UI/res/layout/fragment_calendar_item.xml rename to UI/src/main/res/layout/fragment_calendar_item.xml index e4c4470..59e03d7 100644 --- a/UI/res/layout/fragment_calendar_item.xml +++ b/UI/src/main/res/layout/fragment_calendar_item.xml @@ -1,23 +1,21 @@ + android:orientation="vertical"> - + android:layout_height="wrap_content"> - + android:layout_height="wrap_content"> + android:layout_height="match_parent"> - + android:paddingRight="8sp"> - - - - + android:layout_height="@dimen/toolbar_shadow_height" /> \ No newline at end of file diff --git a/UI/res/layout/fragment_calendar_settings.xml b/UI/src/main/res/layout/fragment_calendar_settings.xml similarity index 100% rename from UI/res/layout/fragment_calendar_settings.xml rename to UI/src/main/res/layout/fragment_calendar_settings.xml diff --git a/UI/res/layout/fragment_calendar_sync_button.xml b/UI/src/main/res/layout/fragment_calendar_sync_button.xml similarity index 78% rename from UI/res/layout/fragment_calendar_sync_button.xml rename to UI/src/main/res/layout/fragment_calendar_sync_button.xml index 43f5684..6c2d826 100644 --- a/UI/res/layout/fragment_calendar_sync_button.xml +++ b/UI/src/main/res/layout/fragment_calendar_sync_button.xml @@ -2,9 +2,9 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?attr/primaryColorShaded" + android:background="?attr/colorPrimary" android:orientation="vertical" - tools:context=".MainActivity" > + tools:context=".MainActivity"> + android:paddingBottom="8dp" + android:paddingEnd="14dp" + android:paddingLeft="18dp" + android:paddingRight="14dp" + android:paddingStart="18dp" + android:paddingTop="8dp" + android:visibility="gone"> diff --git a/UI/res/layout/fragment_events_preview_detail.xml b/UI/src/main/res/layout/fragment_events_preview_detail.xml similarity index 100% rename from UI/res/layout/fragment_events_preview_detail.xml rename to UI/src/main/res/layout/fragment_events_preview_detail.xml diff --git a/UI/res/layout/fragment_input_text_dialog.xml b/UI/src/main/res/layout/fragment_input_text_dialog.xml similarity index 90% rename from UI/res/layout/fragment_input_text_dialog.xml rename to UI/src/main/res/layout/fragment_input_text_dialog.xml index 7229d5f..1f084aa 100644 --- a/UI/res/layout/fragment_input_text_dialog.xml +++ b/UI/src/main/res/layout/fragment_input_text_dialog.xml @@ -5,7 +5,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="vertical" - android:padding="8dp" > + android:padding="8dp"> @@ -31,7 +31,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="right" - android:orientation="horizontal" > + android:orientation="horizontal"> + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UI/res/layout/fragment_purchasable_item.xml b/UI/src/main/res/layout/fragment_purchasable_item.xml similarity index 92% rename from UI/res/layout/fragment_purchasable_item.xml rename to UI/src/main/res/layout/fragment_purchasable_item.xml index c5fa7ca..e8da971 100644 --- a/UI/res/layout/fragment_purchasable_item.xml +++ b/UI/src/main/res/layout/fragment_purchasable_item.xml @@ -1,13 +1,13 @@ + android:orientation="vertical"> + android:visibility="gone"> + android:gravity="center_vertical|right"> + android:visibility="gone"> - + android:layout_weight="1"> \ No newline at end of file diff --git a/UI/res/layout/fragment_purchase_dialog.xml b/UI/src/main/res/layout/fragment_purchase_dialog.xml similarity index 100% rename from UI/res/layout/fragment_purchase_dialog.xml rename to UI/src/main/res/layout/fragment_purchase_dialog.xml diff --git a/UI/res/layout/fragment_webcal_preferences.xml b/UI/src/main/res/layout/fragment_webcal_preferences.xml similarity index 100% rename from UI/res/layout/fragment_webcal_preferences.xml rename to UI/src/main/res/layout/fragment_webcal_preferences.xml diff --git a/UI/res/layout/generic_list.xml b/UI/src/main/res/layout/generic_list.xml similarity index 76% rename from UI/res/layout/generic_list.xml rename to UI/src/main/res/layout/generic_list.xml index c8ac8cd..75a042b 100644 --- a/UI/res/layout/generic_list.xml +++ b/UI/src/main/res/layout/generic_list.xml @@ -2,18 +2,16 @@ + android:layout_height="match_parent"> - + android:dividerHeight="0px" + tools:listitem="@layout/page_entry_item" /> + android:background="@android:color/white"> + android:paddingLeft="16dp" + android:paddingRight="16dp"> - + android:orientation="vertical"> - + + + + \ No newline at end of file diff --git a/UI/res/menu/calendar_item.xml b/UI/src/main/res/menu/calendar_item.xml similarity index 73% rename from UI/res/menu/calendar_item.xml rename to UI/src/main/res/menu/calendar_item.xml index ed58f3f..e06a0f0 100644 --- a/UI/res/menu/calendar_item.xml +++ b/UI/src/main/res/menu/calendar_item.xml @@ -1,13 +1,14 @@ - + + android:visible="false" + app:showAsAction="always" /> \ No newline at end of file diff --git a/UI/res/menu/event_preview.xml b/UI/src/main/res/menu/event_preview.xml similarity index 100% rename from UI/res/menu/event_preview.xml rename to UI/src/main/res/menu/event_preview.xml diff --git a/UI/res/menu/main.xml b/UI/src/main/res/menu/main.xml similarity index 75% rename from UI/res/menu/main.xml rename to UI/src/main/res/menu/main.xml index 458aeb2..26b1f2f 100644 --- a/UI/res/menu/main.xml +++ b/UI/src/main/res/menu/main.xml @@ -1,14 +1,15 @@ - + + android:visible="false" + app:showAsAction="always" /> \ No newline at end of file diff --git a/UI/res/menu/side_navigation.xml b/UI/src/main/res/menu/side_navigation.xml similarity index 100% rename from UI/res/menu/side_navigation.xml rename to UI/src/main/res/menu/side_navigation.xml diff --git a/UI/res/raw/countries.json b/UI/src/main/res/raw/countries.json similarity index 100% rename from UI/res/raw/countries.json rename to UI/src/main/res/raw/countries.json diff --git a/UI/res/values-da/strings.xml b/UI/src/main/res/values-da/strings.xml old mode 100755 new mode 100644 similarity index 97% rename from UI/res/values-da/strings.xml rename to UI/src/main/res/values-da/strings.xml index 08b9e3b..ef43329 --- a/UI/res/values-da/strings.xml +++ b/UI/src/main/res/values-da/strings.xml @@ -1,4 +1,4 @@ - + diff --git a/UI/res/values-de/strings.xml b/UI/src/main/res/values-de/strings.xml similarity index 100% rename from UI/res/values-de/strings.xml rename to UI/src/main/res/values-de/strings.xml diff --git a/UI/res/values-es/strings.xml b/UI/src/main/res/values-es/strings.xml old mode 100755 new mode 100644 similarity index 97% rename from UI/res/values-es/strings.xml rename to UI/src/main/res/values-es/strings.xml index b28c360..e8d9789 --- a/UI/res/values-es/strings.xml +++ b/UI/src/main/res/values-es/strings.xml @@ -1,4 +1,4 @@ - + diff --git a/UI/res/values-fi/strings.xml b/UI/src/main/res/values-fi/strings.xml similarity index 97% rename from UI/res/values-fi/strings.xml rename to UI/src/main/res/values-fi/strings.xml index f0f19b3..54f7b80 100644 --- a/UI/res/values-fi/strings.xml +++ b/UI/src/main/res/values-fi/strings.xml @@ -1,4 +1,4 @@ - + diff --git a/UI/res/values-fr/strings.xml b/UI/src/main/res/values-fr/strings.xml old mode 100755 new mode 100644 similarity index 97% rename from UI/res/values-fr/strings.xml rename to UI/src/main/res/values-fr/strings.xml index 61188ba..3e91867 --- a/UI/res/values-fr/strings.xml +++ b/UI/src/main/res/values-fr/strings.xml @@ -1,4 +1,4 @@ - + diff --git a/UI/res/values-hdpi-v16/styles.xml b/UI/src/main/res/values-hdpi-v16/styles.xml similarity index 99% rename from UI/res/values-hdpi-v16/styles.xml rename to UI/src/main/res/values-hdpi-v16/styles.xml index 7271dbe..0dc282f 100644 --- a/UI/res/values-hdpi-v16/styles.xml +++ b/UI/src/main/res/values-hdpi-v16/styles.xml @@ -35,7 +35,7 @@ @android:color/tertiary_text_light - - + \ No newline at end of file diff --git a/UI/res/values-hdpi/styles.xml b/UI/src/main/res/values-hdpi/styles.xml similarity index 99% rename from UI/res/values-hdpi/styles.xml rename to UI/src/main/res/values-hdpi/styles.xml index 3697260..c75a257 100644 --- a/UI/res/values-hdpi/styles.xml +++ b/UI/src/main/res/values-hdpi/styles.xml @@ -1,6 +1,6 @@ - + + + + \ No newline at end of file diff --git a/UI/res/values-v14/styles.xml b/UI/src/main/res/values-v14/styles.xml similarity index 100% rename from UI/res/values-v14/styles.xml rename to UI/src/main/res/values-v14/styles.xml diff --git a/UI/res/values-zh-rCN/strings.xml b/UI/src/main/res/values-zh-rCN/strings.xml old mode 100755 new mode 100644 similarity index 97% rename from UI/res/values-zh-rCN/strings.xml rename to UI/src/main/res/values-zh-rCN/strings.xml index a49d3ae..d413db2 --- a/UI/res/values-zh-rCN/strings.xml +++ b/UI/src/main/res/values-zh-rCN/strings.xml @@ -1,4 +1,4 @@ - + diff --git a/UI/res/values/alarms.xml b/UI/src/main/res/values/alarms.xml similarity index 100% rename from UI/res/values/alarms.xml rename to UI/src/main/res/values/alarms.xml diff --git a/UI/res/values/attrs.xml b/UI/src/main/res/values/attrs.xml similarity index 100% rename from UI/res/values/attrs.xml rename to UI/src/main/res/values/attrs.xml diff --git a/UI/res/values/colors.xml b/UI/src/main/res/values/colors.xml similarity index 100% rename from UI/res/values/colors.xml rename to UI/src/main/res/values/colors.xml diff --git a/UI/res/values/defaults.xml b/UI/src/main/res/values/defaults.xml similarity index 100% rename from UI/res/values/defaults.xml rename to UI/src/main/res/values/defaults.xml diff --git a/UI/res/values/dimens.xml b/UI/src/main/res/values/dimens.xml similarity index 60% rename from UI/res/values/dimens.xml rename to UI/src/main/res/values/dimens.xml index 31ca485..9c318f2 100644 --- a/UI/res/values/dimens.xml +++ b/UI/src/main/res/values/dimens.xml @@ -5,4 +5,9 @@ 16dp 240dp + + 48dp + + + 4dp \ No newline at end of file diff --git a/UI/res/values/strings.xml b/UI/src/main/res/values/strings.xml similarity index 100% rename from UI/res/values/strings.xml rename to UI/src/main/res/values/strings.xml diff --git a/UI/res/values/styles.xml b/UI/src/main/res/values/styles.xml similarity index 70% rename from UI/res/values/styles.xml rename to UI/src/main/res/values/styles.xml index b6b897f..d4aa26d 100644 --- a/UI/res/values/styles.xml +++ b/UI/src/main/res/values/styles.xml @@ -4,11 +4,22 @@ Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devices. --> - + + + + + + + + + + + + \ No newline at end of file diff --git a/UI/res/xml/webcal_preference.xml b/UI/src/main/res/xml/webcal_preference.xml similarity index 100% rename from UI/res/xml/webcal_preference.xml rename to UI/src/main/res/xml/webcal_preference.xml diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..833eee9 --- /dev/null +++ b/build.gradle @@ -0,0 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.1.0' + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/color-picker b/color-picker new file mode 160000 index 0000000..27e27a5 --- /dev/null +++ b/color-picker @@ -0,0 +1 @@ +Subproject commit 27e27a54dc2913a82436bf4a8e9e6167d6efd1ec diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..bd8a477 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,3 @@ +include ':UI', ':colorpicker' +include ':Demo' +project(':colorpicker').projectDir = new File('color-picker/colorpicker') \ No newline at end of file